機能 #3407
完了⑧ ダイレクトデータポート接続機能
100%
説明
同一プロセス内のデータポート接続において、OutPortがInPortの変数に直接書き込む(push型)、またはInPortがOutPortの変数を直接読む(Pull型)形でデータ転送をする方式を実装すること。
ファイル
miyamoto さんがほぼ9年前に更新
- ファイル test_DirectPort.py test_DirectPort.py を追加
実装¶
Push型
以下のクラスを実装した。
InPortDirectProvider
インポートプロバイダクラス
InPortProviderクラスを継承してある。
InterfaceTypeは「direct」に設定してある。
InPortDirectConsumer
インポートコンシュマークラス
InPortConsumerクラスを継承してある。
InPortDirectProviderのファクトリを登録するInPortDirectProviderInit関数、InPortDirectConsumerのファクトリを登録するInPortDirectConsumerInit関数をFactoryInit関数で呼び出すことで「direct」という名前のInterfaceTypeを有効にしている。
OutPortBaseクラスに以下の関数を実装した。
getLocalInPort関数:接続したインポートのサーバントを取得する
またInPortのサーバントの設定のためにcreateConnector関数にコードを追加した。
OutPortPushConnectorクラスに以下の関数を実装した。
setInPort関数:ダイレクトで接続する場合にインポートのサーバントを設定する
データの変数への書き込みのためにwrite関数にコードを追加した。
変数宣言のためにコンストラクタにコードを追加した。
InPortクラスに以下の関数を実装した。
write関数:変数_valueにデータを書き込む
変数読み込みのためにread関数にコードを追加した。
データ
変数宣言のためにコンストラクタにコードを追加した。
まずOutPortBaseオブジェクトのcreateConnector関数内でgetLocalInPort関数によりインポートのサーバントを取得し、OutPortPushConnectorオブジェクトのsetInPort関数でインポートのサーバントを設定する。
inport = self.getLocalInPort(profile)
(中略)connector.setInPort(inport)
そしてOutPortPushConnectorオブジェクトのwrite関数内でインポートオブジェクトのwrite関数を呼び出せばデータを直接書き込める。
self._directInPort.write(data)
バッファがないためデータ書き込んだ際にInPortオブジェクトの変数_directInPortをTrueにして、読み込んだ時にFalseにしている。
isNew関数は_directInPortを返し、isEmpty関数は_directInPortの否定を返す。
Pull型
以下のクラスを実装した。
OutPortDirectProvider
アウトポートプロバイダクラス
OutPortProviderクラスを継承してある。
InterfaceTypeは「direct」に設定してある。
OutPortDirectConsumer
アウトポートコンシュマークラス
OutPortConsumerクラスを継承してある。
Push型と同じく、Init関数を呼び出すことで「direct」のInterfaceTypeが有効になる。
OutPortPullConnectorクラスに以下の関数を追加した。
setInPort関数:ダイレクトに接続する際にInPortオブジェクトにOutPortPullConnectorオブジェクトを設定する
read関数:データをダイレクトに読み込む
変数書き込みのためにwrite関数にコードを追加した。
変数宣言のためにコンストラクタにもコードを追加した。
InPortクラスに以下の関数を追加した。
addOutPortConnector:対象のOutPortPullConnectorオブジェクトをリストに追加する
removeOutPortConnector:対象のOutPortPullConnectorオブジェクトをリストから削除する
データ読み込みのためにread関数にコードを追加した。
変数宣言のためにコンストラクタにもコードを追加した。
まず、Push型と同じくOutPortBaseオブジェクトのcreateConnector関数内でInPortのサーバントをOutPortPullConnectorオブジェクトのsetInPort関数に渡す。
OutPortPullConnectorオブジェクトのsetInPort関数ではInPortオブジェクトのaddOutPortConnector関数を呼び出しリスト_outPortConnectorListにOutPortPullConnectorオブジェクトを追加している。
OutPortPullConnectorオブジェクトのwrite関数で変数にデータを書き込み、InPortオブジェクトのread関数でリストのサイズが1以上の時にリスト内のOutPortPullConnectorオブジェクトから変数を読み込む。
切断された時はOutPortPullConnectorオブジェクトのdisconnect関数内でInPortオブジェクトのremoveOutPortConnector関数を呼び出しリストから削除する。
テスト¶
添付したテスト用コードでテストを行った。
テスト用コードは以下の動作を行う。
setUp関数
マネージャ初期化self.manager = OpenRTM_aist.Manager.init(sys.argv)
self.manager.activateManager()
データポート生成self._d_in = RTC.TimedLong(RTC.Time(0,0),0)
self._inIn = OpenRTM_aist.InPort("in", self._d_in)
prop = OpenRTM_aist.Properties()
self._inIn.init(prop)
self.inport_obj = self._inIn.getPortRef()
→インポートとアウトポートを生成する
test_Push関数
isNew関数でデータが書き込まれたか判定できるかの確認self._d_out.data = 100
self._outOut.write()
ret = self._inIn.isNew()
self.assertTrue(ret)
read関数でデータがダイレクトに読み込めるかの確認
data = self._inIn.read()
self.assertEqual(data.data, 100)
self.assertTrue(data is self._d_out)
test_Pull関数
データをダイレクトに読み込めるかの確認data = self._inIn.read()
self.assertEqual(data.data, 100)
self.assertTrue(data is self._d_out)
補足¶
プロバイダ、コンシュマーのファクトリを登録した際にRTシステムエディタのコネクタの設定でInterfaceTypeが増殖する不具合が発生した。
調べてみたところOutPortBaseクラスとInPortBaseクラスのinitProviders関数とinitProviders関数に問題があったので修正した。
self.appendProperty("dataport.interface_type",
OpenRTM_aist.flatten(consumer_types))
→for consumer_type in consumer_types:
self.appendProperty("dataport.interface_type",consumer_type)
self.appendProperty("dataport.interface_type",
OpenRTM_aist.flatten(provider_types))
→for provider_type in provider_types:
self.appendProperty("dataport.interface_type",provider_type)