セック ロボットサイト - データポートを利用する

データポートを利用する

RTCは他のRTCとデータをやりとりするためにデータポートを利用します。 データポートには、データを受信するためのデータ入力ポートと、 データを送信するためのデータ出力ポートがあります。

PyRTSeamでデータポートを利用するには、プロファイルでデータポートの定義を記述し、 ロジックでデータを処理します。

データポートの定義を記述する

データポートを定義するには、rtseam.Profile.__init__の引数inportsとoutports に辞書(ポート名:型)を与えます。利用可能な型は、OpenRTM-aistが提供するIDLファイル (BasicDataType.idl、ExtendedDataTypes.idlなど)で定義している構造体と、 RTC開発者が独自にIDLで定義した構造体(ユーザ定義型)です。 ユーザ定義型については、 データポートでユーザ定義型を利用する で説明しています。

“InputNumber”という名前で、型がRTC.TimedLongのデータ入力ポートを定義するには:

PROFILE = rtseam.Profile(inports={"InputNumber": RTC.TimedLong})

“OutputNumber”という名前で、型がRTC.TimedLongのデータ出力ポートを定義するには:

PROFILE = rtseam.Profile(outports={"OutputNumber": RTC.TimedLong})

データ入力ポートとデータ出力ポートを両方定義することもできます:

PROFILE = rtseam.Profile(inports={"InputNumber": RTC.TimedLong},
                         outports={"OutputNumber": RTC.TimedLong})

複数のデータポートを定義したい場合は辞書に複数のアイテムを入れます:

PROFILE = rtseam.Profile(inports={"InputData1": RTC.TimedLong,
                                  "InputData2": RTC.TimedDouble},
                         outports={"OutputData1": RTC.TimedLong,
                                   "OutputData2": RTC.TimedShort})

注意

データ入力ポートとデータ出力ポートの名前が重複してはいけません。 次のソースコードは不正です:

PROFILE = rtseam.Profile(name="Add",
                         inports={"Number": RTC.TimedLong},
                         outports={"Number": RTC.TimedDouble})

ロジックでデータを処理する

データ入力ポートを利用する場合、ロジックは、引数として辞書(ポート名:データ)を 受け取るようにします。 PyRTSeamは、RTCのonExecuteでロジックを呼び出す前に全てのデータ入力ポートから データを読み込み、読み込めたデータをロジックの引数に渡します。 例えば、”InputNumber”という名前のデータ入力ポートからデータを受け取って表示する RTCのロジックは次のように記述します:

def print_data(input_data):
    if "InputNumber" in input_data:
        print input_data["InputNumber"]

ノート

データ入力ポートからデータを読み込めなかった場合は、 そのデータ入力ポートのデータは辞書に含まれません。

ロジックをクラスで作成する場合は、__call__メソッドで同じようにします:

class DataDisplay(object):
    def __call__(self, input_data):
        if "InputNumber" in input_data:
            print input_data["InputNumber"]

データ出力ポートを利用する場合は、ロジックの戻り値で辞書(ポート名:データ)を返します。 PyRTSeamは、RTCのonExecuteでロジックを呼び出した後、戻り値が返ってくれば そのデータをデータ出力ポートに書き込みます。 例えば、”Velocity”という名前のデータ出力ポートに固定値を書き込むRTCのロジックは 次のように記述します:

def get_data():
    return {"Velocity": RTC.TimedDouble(RTC.Time(0, 0), 1.5)}

ロジックをクラスで作成する場合は、__call__メソッドで同じようにします:

class DataSender(object):
    def __call__(self):
        return {"Velocity": RTC.TimedDouble(RTC.Time(0, 0), 1.5)}

ソースコード例

データ入力ポートを持つRTC

データ入力ポートを1つ持ち、受け取ったデータを標準出力に表示するRTC:

import RTC
import rtseam.openrtm

PROFILE = rtseam.Profile(name="DataDisplay",
                         inports={"InputNumber": RTC.TimedLong})

def print_data(input_data):
    if "InputNumber" in input_data:
        print input_data["InputNumber"]

rtseam.openrtm.run(PROFILE, print_data)

データ出力ポート持つRTC

データ出力ポートを1つ持ち、固定値を繰り返し出力するRTC:

import RTC
import rtseam.openrtm

PROFILE = rtseam.Profile(name="ConstantSender",
                         outports={"OutputNumber": RTC.TimedLong})

def get_data():
    current_time = rtseam.openrtm.current_time()
    return {"OutputNumber": RTC.TimedLong(current_time, 100)}

rtseam.openrtm.run(PROFILE, get_data)

データ入力ポートとデータ出力ポートを両方持つRTC

データ入力ポートとデータ出力ポートを1つずつ持ち、入力された値に+1して出力するRTC:

import RTC
import rtseam.openrtm

PROFILE = rtseam.Profile(name="AddOne",
                         inports={"InputNumber": RTC.TimedLong},
                         outports={"OutputNumber": RTC.TimedLong})

def add_one(input_data):
    output_data = {}
    if "InputNumber" in input_data:
        value = input_data["InputNumber"]
        value.data += 1
        output_data["OutputNumber"] = value
    return output_data

rtseam.openrtm.run(PROFILE, add_one)