忍者ブログ
ロボット、千葉ロッテマリーンズについていいかげんなことを書きます。
[577]  [576]  [575]  [574]  [573]  [572]  [571]  [570]  [568]  [567]  [566
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

今回は独自の通信方法の実装方法をメモしておきます。

Push型の通信、OpenRTM-aistのPython版を前提にしていますが、C++版でも手順はほぼ同じです。

まずはOpenRTM-aistのPython版に含まれるInPortCorbaCdrConsumer.py、InPortCorbaCdrProvider.pyのクラスを継承したクラスを作成します。

とりあえず、InPortTestConsumer.py、InPortTestProvider.pyというファイルを作成してください。

後は適当にこんな感じでコードを書いておきます。



InPortTestConsumer.py
import OpenRTM_aist
class InPortTestConsumer(OpenRTM_aist.InPortCorbaCdrConsumer):
  def __init__(self):
    OpenRTM_aist.InPortCorbaCdrConsumer.__init__(self)
 
def InPortTestConsumerInit(manager):
  factory = OpenRTM_aist.InPortConsumerFactory.instance()
  factory.addFactory("test",
                     InPortTestConsumer,
                     OpenRTM_aist.Delete)

InPortTestProvider.py
import OpenRTM_aist
class InPortTestProvider(OpenRTM_aist.InPortCorbaCdrProvider):
  def __init__(self):
    OpenRTM_aist.InPortCorbaCdrProvider.__init__(self)
    self.setInterfaceType("test")
def InPortTestProviderInit(manager):
  factory = OpenRTM_aist.InPortProviderFactory.instance()
  factory.addFactory("test",
                     InPortTestProvider,
                     OpenRTM_aist.Delete)



次にInPortTestConsumer、InPortTestProviderのファクトリを登録しておく必要があるため、rtc.confのmanager.modules.preloadにInPortTestConsumer.py, InPortTestProvider.pyを記述しておくことで上記の初期化関数を呼び出します。

ただInPortCorbaCdrConsumer.py、InPortCorbaCdrProvider.pyの初期化関数には引数がないためrtc.confのmanager.modules.preloadに記述するとエラーが出て読み込めないみたいです。上のコードで使いもしないのにmanagerの引数を用意しているのはそのためです。





これで準備完了です。
適当なRTCを起動してデータポートを接続してください。


上手くできていればRTシステムエディタのコネクタプロファイル設定のInterface Typeにtestが追加されているはずなので、これを選択してコネクタを接続してください。





後はいつもどおり通信できていれば成功です。
ただ今回はInPortCorbaCdrProvider、InPortCorbaCdrConsumerを継承して作成しただけなので、通常の通信方法と何も変わりません。



独自の通信方法を実装するために詳細を見ていきます。
とりあえずRTC_A、RTC_Bの2つのコンポーネントがあって、RTC_AからRTC_Bにデータを送信するという事にします。

まず最初OutPortConnector.pyのwrite関数を見てください。
cdrMarshal関数でデータを符号化した後にself._publisher.write関数に渡しています。
この時点でデータはCDRというバイト列に変換されています。
当然ですがこの時点ではまだデータはRTC_A側にあります。

その後、データはInPortCorbaCdrConsumerのput関数に渡されます。
put関数を見てみると、引数のdataをinportcdr.put関数に渡しています。
inportcdrはDataPort.idlで定義されたInPortCdrのオブジェクトリファレンスなので、これを使ってInPortCorbaCdrProviderのput関数を呼び出しているという事になります。
つまりこの時点でRTC_AからRTC_Bにデータが送られたという事にはなります。pull型だと少し話は変わりますけど。

InPortCorbaCdrProviderのput関数でデータを受け取ると、self._connector.write関数に渡しています。そしてデータを受け取ったコネクタ(InPortPushConnector)のwrite関数内でcdrUnmarshalによりCDRからデータを復号化してバッファに書き込んでいます。



つまり新たにInPort~Consumer、InPort~Providerクラスを作成したとして、既にCDRに符号化したデータの通信する方法を変更する事ぐらいしか出来ないので、データを直接変数に書き込もうとした場合などはOpenRTM-aistのソースコード自体を変更するしかありません。


このコードではInPortTestConsumerクラスでput関数を定義してファイルにデータを書き込み→InPortTestProviderクラスのput関数内でファイルを読み込むという事をやっています。
ファイル名を別に送信していますが、実際にはコネクタプロファイルで設定できた方が効率的だとは思います。








今回は実験のためにInPortCorbaCdrProviderクラスとInPortCorbaCdrConsumerクラスを継承して作成しましたが、実際にはInPortProviderクラスとInPortConsumerクラスを継承して作成する事にはなると思います。



独自の通信方法を実装する場合は①あまり複雑にしない事、②仕様書を用意する事が必要かもしれないです。でないと他の言語で実装ができません。











にほんブログ村 科学ブログ ロボットへ
にほんブログ村のロボットのカテゴリから
全然人が来ない・・・

人気ブログランキングへ
PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
カレンダー
10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
フリーエリア
最新CM
[08/31 ysuga]
[08/31 Nobu]
[08/31 ysuga]
[12/11 Nobu]
[12/11 Kanamura]
最新TB
プロフィール
HN:
Nobu
年齢:
36
性別:
男性
誕生日:
1988/09/22
職業:
あれ
趣味:
妄想、自堕落
バーコード
ブログ内検索
P R
カウンター
忍者ブログ [PR]