RTシステム開発 (応用編)

DDS通信機能の利用

DDS(Data Distribution Service)はOMGが策定した出版・購読型モデルの通信ミドルウェア仕様です。 ドメイン内のDomain Participantがデータ配信を行うDDS Publisher、データ受信を行うDDS Subscriberにより他のDomain Participantと相互通信を行います。 Publisherは指定のトピック向けにデータを配信し、Subscriberは指定のトピック向けのデータを受信することができます。

dds1.png

DDSの概念図は上の図のようになっていますが、内部的にはUDP/IPによるマルチキャスト通信とユニキャスト通信によって通信しています。

dds2.png

ParticipantはPDP(Participant Discovery Protocol)で互いのParticipantを検出します。この時、マルチキャスト通信でユニキャストアドレスなどのメッセージを送信します。 次にSEDP(Endpoint Discovery Protocol)でユニキャスト通信によりDataWriterとDataReaderの情報を共有します。トピックとデータ型が一致した場合はエンドポイントが一致していると判定してデータの送受信を開始します。

この他にDDSには通信のQoS(Quality of Service)制御の機能があります。

利用可能な実装

現状、以下のDDS実装に対応している。

Fast DDS通信機能の利用

Fast DDS(以前のバージョンではFast RTPS)はeProsima社が開発しているOMG DDS 2.0、RTPS 2.2仕様の通信ミドルウェアです。

以下ではOpenRTM-aistのFast RTPSプラグインのインストール手順、使用方法を説明します。

ROS2通信機能がインストール済みの場合、Fast DDS通信機能も利用可能になっているため以下の手順は不要です。

C++版のみの対応です。

Windows

Fast DDSのインストール

以下のサイトからインストーラーをダウンロードしてインストールしてください。

OpenRTM-aistのビルド

CMake実行時にFASTRTPS_ENABLEのオプションをONにします。

 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc16 -G "Visual Studio 16 2019" -DFASTRTPS_ENABLE=ON ..

その他の手順は通常と同じです。

適当な場所にインストールしてください。

インストールするディレクトリはCMAKE_INSTALL_PREFIXのオプションで設定します。

 cmake .. -DCMAKE_INSTALL_PREFIX=C:/workspace/OpenRTM-aist/build/install
 cmake --build . --config Release --target install

動作確認

{インストールしたパス}\2.0.0\Components\C++\Examples\vc16のサンプルコンポーネントを実行します。

以下の内容のrtc.confを作成してください。

 manager.modules.load_path: {インストールしたパス}\\2.0.0\\ext\\transport
 manager.modules.preload: FastRTPSTransport.dll
 manager.components.preconnect: ConsoleOut0.in?interface_type=fast-rtps, ConsoleIn0.out?interface_type=fast-rtps
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

まずFastRTPSTransport.dllのロードが必要になります。 この設定はmanager.modules.preloadのオプションで設定できます。

次にコネクタ生成時にインターフェース型をfast-rtpsに設定する必要があります。 コネクタの生成はmanager.components.preconnectオプションにより設定します。 この例ではConsoleOut0コンポーネントのinのポート、ConsoleIn0コンポーネントのoutのポートにそれぞれコネクタを生成しています。

ConsoleInComp.exeConsoleOutComp.exeを実行すると通信ができるようになります。

Ubuntu

Fast DDSのインストール

依存ライブラリのインストール

asio、TinyXML-2をインストールします。

 sudo apt install libasio-dev libtinyxml2-dev

Fast-CDRをビルド、インストールします。

 export $OPENRTM_INSTALL_DIR=~/fastdds_install
 export FASTCDR_VERSION=1.0.23
 wget https://github.com/eProsima/Fast-CDR/archive/refs/tags/v${FASTCDR_VERSION}.tar.gz
 tar xf v${FASTCDR_VERSION}.tar.gz
 cd Fast-CDR-${FASTCDR_VERSION}/
 mkdir build
 cd build/
 cmake .. -DCMAKE_INSTALL_PREFIX=${OPENRTM_INSTALL_DIR}
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

foonathan/memoryをビルド、インストールします。

 export FOONATHAN_MEMORY_VERSION=1.2.1
 wget https://github.com/eProsima/foonathan_memory_vendor/archive/refs/tags/v${FOONATHAN_MEMORY_VERSION}.tar.gz
 tar xf v${FOONATHAN_MEMORY_VERSION}.tar.gz
 cd foonathan_memory_vendor-${FOONATHAN_MEMORY_VERSION}/
 mkdir build
 cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=${OPENRTM_INSTALL_DIR}
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

Fast DDSのビルド

Fast DDSのビルドにはCMake 3.11以上のバージョンが必要です。 Ubuntu 18.04環境ではaptでインストールされるCMakeのバージョンが3.10のため、新しいバージョンのCMakeをダウンロードしてPATHを設定してください。

 wget https://github.com/Kitware/CMake/releases/download/v3.22.3/cmake-3.22.3-linux-x86_64.tar.gz
 tar xf cmake-3.22.3-linux-x86_64.tar.gz
 export PATH=~/cmake-3.22.3-linux-x86_64/bin:$PATH

以下のコマンドでFast DDSをビルド、インストールしてください。

 export FASTDDS_VERSION=2.5.1
 wget https://github.com/eProsima/Fast-DDS/archive/refs/tags/v${FASTDDS_VERSION}.tar.gz
 tar xf v${FASTDDS_VERSION}.tar.gz
 cd Fast-DDS-${FASTDDS_VERSION}/
 mkdir build
 cd build
 cmake .. -Dfastcdr_DIR=${OPENRTM_INSTALL_DIR}/lib/cmake -Dfoonathan_memory_DIR=${OPENRTM_INSTALL_DIR}/lib/foonathan_memory -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=${OPENRTM_INSTALL_DIR}
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

OpenRTM-aistのビルド

CMake実行時にFASTRTPS_ENABLEのオプションをONにします。

 cmake .. -DFASTRTPS_ENABLE=ON -Dfastrtps_DIR=${OPENRTM_INSTALL_DIR}/share/fastrtps/cmake

その他の手順は通常と同じです。

適当な場所にインストールしてください。

インストールするディレクトリはCMAKE_INSTALL_PREFIXのオプションで設定します。

 cmake .. -DCMAKE_INSTALL_PREFIX=${OPENRTM_INSTALL_DIR}
 cmake --build . --config Release --target install

動作確認

{インストールしたパス}/share/openrtm-2.0/components/c++/examplesのサンプルコンポーネントを実行します。

以下の内容のrtc.confを作成してください。

 manager.modules.load_path: {インストールしたパス}/lib/openrtm-2.0/transport
 manager.modules.preload: FastRTPSTransport.so
 manager.components.preconnect: ConsoleOut0.in?interface_type=fast-rtps, ConsoleIn0.out?interface_type=fast-rtps
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

まずFastRTPSTransport.soのロードが必要になります。 この設定はmanager.modules.preloadのオプションで設定できます。

次にコネクタ生成時にインターフェース型をfast-rtpsに設定する必要があります。 コネクタの生成はmanager.components.preconnectオプションにより設定します。 この例ではConsoleOut0コンポーネントのinのポート、ConsoleIn0コンポーネントのoutのポートにそれぞれコネクタを生成しています。

ConsoleInCompConsoleOutCompを実行すると通信ができるようになります。

起動時のオプション

rtc.confでOpenRTM-aistのマネージャ起動時に以下のオプションを設定可能です。 ※開発中のOpenRTM-aistでは使用可能ですが、リリースしたバージョンでは未実装の場合があります。

オプション名 設定例 内容
fast-rtps.xmlprofile.filename C:/openrtminstall/2.0.0/ext/transport/FastRTPsQoSExample.xml Fast DDSの設定ファイルを指定する。
fast-rtps.participant.name participant_openrtm ロードするDomainParticipantのプロファイル名
fast-rtps.domain.id 0 ドメインのID
fast-rtps.dds.sec.auth.plugin builtin.PKI-DH 認証プラグインの名前
fast-rtps.dds.sec.auth.*** 認証プラグインの設定
fast-rtps.dds.sec.access.plugin builtin.Access-Permissions アクセス制御プラグインの名前
fast-rtps.dds.sec.access.*** アクセス制御プラグインの設定
fast-rtps.dds.sec.crypto.plugin builtin.AES-GCM-GMAC 暗号化プラグインの名前
fast-rtps.dds.sec.crypto.*** 暗号化プラグインの設定
fast-rtps.dds.sec.log.plugin builtin.DDS_LogTopic セキュリティロギングプラグインの名前
fast-rtps.dds.sec.log.*** セキュリティロギングプラグインの設定

以下に設定例を記載します。

 fast-rtps.xmlprofile.filename: ${OPENRTM_INSTALL_DIR}/transport/FastRTPsQoSExample.xml
 fast-rtps.participant.name: participant_openrtm

接続時のオプション

データポート接続時のコネクタプロファイルに設定できるオプションは以下の通りです。

オプション名 デフォルト値 オプション 内容
fast-rtps.topic chatter DDSトピックの名前。ROS2シリアライザを使う場合は先頭にrt/を付けた名前に自動的に変更する。
fast-rtps.subscriber.name ロードするSubscriberのプロファイル名
fast-rtps.subscriber.qos.deadline.period.seconds 2147483647 受信側の最小周期
fast-rtps.subscriber.qos.deadline.period.nanosec 4294967295
fast-rtps.subscriber.qos.destinationOrder BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
fast-rtps.subscriber.qos.disablePositiveACKs.enabled NO YES, NO
fast-rtps.subscriber.qos.disablePositiveACKs.duration.seconds 2147483647
fast-rtps.subscriber.qos.disablePositiveACKs.duration.nanosec 4294967295
fast-rtps.subscriber.qos.durability.kind VOLATILE_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS 受信側の堅牢性(VOLATILE_DURABILITY_QOS:変わりやすい、TRANSIENT_LOCAL_DURABILITY_QOS:一時的なローカル設定)
fast-rtps.subscriber.qos.durabilityService.history_depth 1
fast-rtps.subscriber.qos.durabilityService.history_kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
fast-rtps.subscriber.qos.durabilityService.max_instances -1
fast-rtps.subscriber.qos.durabilityService.max_samples -1
fast-rtps.subscriber.qos.durabilityService.max_samples_per_instance -1
fast-rtps.subscriber.qos.durabilityService.service_cleanup_delay.seconds 0
fast-rtps.subscriber.qos.durabilityService.service_cleanup_delay.nanosec 0
fast-rtps.subscriber.qos.latencyBudget.duration.seconds 0
fast-rtps.subscriber.qos.latencyBudget.duration.nanosec 0
fast-rtps.subscriber.qos.lifespan.duration.seconds 2147483647
fast-rtps.subscriber.qos.lifespan.duration.nanosec 4294967295
fast-rtps.subscriber.qos.liveliness.announcement_period.seconds 2147483647
fast-rtps.subscriber.qos.liveliness.announcement_period.nanosec 4294967295
fast-rtps.subscriber.qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
fast-rtps.subscriber.qos.liveliness.lease_duration.seconds 2147483647 受信側のハートビートの周期
fast-rtps.subscriber.qos.liveliness.lease_duration.nanosec 4294967295
fast-rtps.subscriber.qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
fast-rtps.subscriber.qos.presentation.access_scope INSTANCE_PRESENTATION_QOS INSTANCE_PRESENTATION_QOS, TOPIC_PRESENTATION_QOS, GROUP_PRESENTATION_QOS
fast-rtps.subscriber.qos.presentation.coherent_access NO YES, NO
fast-rtps.subscriber.qos.presentation.ordered_access NO YES, NO
fast-rtps.subscriber.qos.reliability.kind BEST_EFFORT_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS 受信側の信頼性(RELIABLE_RELIABILITY_QOS:高信頼、BEST_EFFORT_RELIABILITY_QOS:最高速度)
fast-rtps.subscriber.qos.reliability.max_blocking_time.seconds 0
fast-rtps.subscriber.qos.reliability.max_blocking_time.nanosec 100000000
fast-rtps.subscriber.qos.timeBasedFilter.minimum_separation.seconds 0
fast-rtps.subscriber.qos.timeBasedFilter.minimum_separation.nanosec 0
fast-rtps.subscriber.qos.type_consistency.force_type_validation NO YES, NO
fast-rtps.subscriber.qos.type_consistency.ignore_member_names NO YES, NO
fast-rtps.subscriber.qos.type_consistency.ignore_sequence_bounds YES YES, NO
fast-rtps.subscriber.qos.type_consistency.ignore_string_bounds YES YES, NO
fast-rtps.subscriber.qos.type_consistency.kind ALLOW_TYPE_COERCION DISALLOW_TYPE_COERCION, ALLOW_TYPE_COERCION
fast-rtps.subscriber.qos.type_consistency.prevent_type_widening NO YES, NO
fast-rtps.subscriber.history_memory_policy PREALLOCATED_WITH_REALLOC_MEMORY_MODE PREALLOCATED_MEMORY_MODE, PREALLOCATED_WITH_REALLOC_MEMORY_MODE, DYNAMIC_RESERVE_MEMORY_MODE, DYNAMIC_REUSABLE_MEMORY_MODE
fast-rtps.subscriber.topic.historyQos.depth 1
fast-rtps.subscriber.topic.historyQos.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
fast-rtps.subscriber.times.heartbeatResponseDelay.seconds 0
fast-rtps.subscriber.times.heartbeatResponseDelay.nanosec 5000000
fast-rtps.subscriber.times.initialAcknackDelay.seconds 0
fast-rtps.subscriber.times.initialAcknackDelay.nanosec 70000000
fast-rtps.publisher.name ロードするPublisherのプロファイル名
fast-rtps.publisher.qos.deadline.period.seconds 2147483647 送信側の最小周期
fast-rtps.publisher.qos.deadline.period.nanosec 4294967295
fast-rtps.publisher.qos.destinationOrder BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
fast-rtps.publisher.qos.disablePositiveACKs.enabled NO YES, NO
fast-rtps.publisher.qos.disablePositiveACKs.duration.seconds 2147483647
fast-rtps.publisher.qos.disablePositiveACKs.duration.nanosec 4294967295
fast-rtps.publisher.qos.durability.kind VOLATILE_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS 送信側の堅牢性(VOLATILE_DURABILITY_QOS:変わりやすい、TRANSIENT_LOCAL_DURABILITY_QOS:一時的なローカル設定)
fast-rtps.publisher.qos.durabilityService.history_depth 1
fast-rtps.publisher.qos.durabilityService.history_kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
fast-rtps.publisher.qos.durabilityService.max_instances -1
fast-rtps.publisher.qos.durabilityService.max_samples -1
fast-rtps.publisher.qos.durabilityService.max_samples_per_instance -1
fast-rtps.publisher.qos.durabilityService.service_cleanup_delay.seconds 0
fast-rtps.publisher.qos.durabilityService.service_cleanup_delay.nanosec 0
fast-rtps.publisher.qos.latencyBudget.duration.seconds 0
fast-rtps.publisher.qos.latencyBudget.duration.nanosec 0
fast-rtps.publisher.qos.lifespan.duration.seconds 2147483647 送信側の未送信データの保持時間
fast-rtps.publisher.qos.lifespan.duration.nanosec 4294967295
fast-rtps.publisher.qos.liveliness.announcement_period.seconds 2147483647
fast-rtps.publisher.qos.liveliness.announcement_period.nanosec 4294967295
fast-rtps.publisher.qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
fast-rtps.publisher.qos.liveliness.lease_duration.seconds 2147483647 送信側のハートビートの周期
fast-rtps.publisher.qos.liveliness.lease_duration.nanosec 4294967295
fast-rtps.publisher.qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
fast-rtps.publisher.qos.presentation.access_scope INSTANCE_PRESENTATION_QOS INSTANCE_PRESENTATION_QOS, TOPIC_PRESENTATION_QOS, GROUP_PRESENTATION_QOS
fast-rtps.publisher.qos.presentation.coherent_access NO YES, NO
fast-rtps.publisher.qos.presentation.ordered_access NO YES, NO
fast-rtps.publisher.qos.publishMode.kind SYNCHRONOUS_PUBLISH_MODE SYNCHRONOUS_PUBLISH_MODE, ASYNCHRONOUS_PUBLISH_MODE
fast-rtps.publisher.qos.reliability.kind BEST_EFFORT_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS 送信側の信頼性(RELIABLE_RELIABILITY_QOS:高信頼、BEST_EFFORT_RELIABILITY_QOS:最高速度、SYSTEM_DEFAULT)
fast-rtps.publisher.qos.reliability.max_blocking_time.seconds 0
fast-rtps.publisher.qos.reliability.max_blocking_time.nanosec 100000000
fast-rtps.publisher.qos.timeBasedFilter.minimum_separation.seconds 0
fast-rtps.publisher.qos.timeBasedFilter.minimum_separation.nanosec 0
fast-rtps.publisher.qos.type_consistency.force_type_validation NO YES, NO
fast-rtps.publisher.qos.type_consistency.ignore_member_names NO YES, NO
fast-rtps.publisher.qos.type_consistency.ignore_sequence_bounds YES YES, NO
fast-rtps.publisher.qos.type_consistency.ignore_string_bounds YES YES, NO
fast-rtps.publisher.qos.type_consistency.kind ALLOW_TYPE_COERCION DISALLOW_TYPE_COERCION, ALLOW_TYPE_COERCION
fast-rtps.publisher.qos.type_consistency.prevent_type_widening NO YES, NO
fast-rtps.publisher.history_memory_policy PREALLOCATED_WITH_REALLOC_MEMORY_MODE PREALLOCATED_MEMORY_MODE, PREALLOCATED_WITH_REALLOC_MEMORY_MODE, DYNAMIC_RESERVE_MEMORY_MODE, DYNAMIC_REUSABLE_MEMORY_MODE
fast-rtps.publisher.topic.historyQos.depth 1 送信側の保持するデータ数
fast-rtps.publisher.topic.historyQos.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS 送信データの保持方法(KEEP_LAST_HISTORY_QOS:すべてのデータを保持、KEEP_LAST_HISTORY_QOS:depthで指定したデータ数だけ保持)
fast-rtps.publisher.times.heartbeatPeriod.seconds 3
fast-rtps.publisher.times.heartbeatPeriod.nanosec 0
fast-rtps.publisher.times.initialHeartbeatDelay.seconds 0
fast-rtps.publisher.times.initialHeartbeatDelay.nanosec 12000000
fast-rtps.publisher.times.nackResponseDelay.seconds 0
fast-rtps.publisher.times.nackResponseDelay.nanosec 5000000
fast-rtps.publisher.times.nackSupressionDuration.seconds 0
fast-rtps.publisher.times.nackSupressionDuration.nanosec 0

以下に設定例を記載します。

 manager.components.preconnect: ConsoleOut0.in?interface_type=fast-rtps&fast-rtps.subscriber.name=subscriber_openrtm

セキュア通信機能の利用

Fast DDSはDDS Security仕様のセキュア通信機能を提供しています。

OpenRTM-aistのFast DDSプラグインでセキュア通信機能を使用するためには起動時のオプションを設定する必要があります。 以下に設定例を記載します。

 fast-rtps.dds.sec.auth.plugin: builtin.PKI-DH
 fast-rtps.dds.sec.auth.builtin.PKI-DH.identity_ca: file://C:/workspace/openrtm_test/build/install/2.0.0/ext//transport/mainexamplecacert.pem
 fast-rtps.dds.sec.auth.builtin.PKI-DH.identity_certificate: file://C:/workspace/openrtm_test/build/install/2.0.0/ext//transport/appexamplecert.pem
 fast-rtps.dds.sec.auth.builtin.PKI-DH.private_key: file://C:/workspace/openrtm_test/build/install/2.0.0/ext//transport/appexamplekey.pem
 fast-rtps.dds.sec.crypto.plugin: builtin.AES-GCM-GMAC

秘密鍵、証明書の作成

Fast DDSのマニュアルの手順で秘密鍵、証明書を作成します。

以下で秘密鍵、自己署名証明書を作成するコマンドを掲載します。 maincaconf.cnfはFast DDSのマニュアルのものを使用します。 出力するファイル名を変更したい場合は適宜maincaconf.cnfの以下の項目を変更してください。

 certificate = $dir/mainexamplecacert.pem
 private_key = $dir/mainexamplecakey.pem

また、req_distinguished_nameの項目は変更して、その内容に応じて変更したappconf.cnfを用意してください。

以下のコマンドを実行します。

 type nul > index.txt
 openssl ecparam -name prime256v1 > ecdsaparam
 openssl req -nodes -x509 -days 3650 -newkey ec:ecdsaparam -keyout mainexamplecakey.pem -out mainexamplecacert.pem -config maincaconf.cnf
 
 openssl ecparam -name prime256v1 > ecdsaparam
 openssl req -nodes -new -newkey ec:ecdsaparam -config appconf.cnf -keyout appexamplekey.pem -out appexamplereq.pem
 openssl ca -batch -create_serial -config maincaconf.cnf -days 3650 -in appexamplereq.pem -out appexamplecert.pem

秘密鍵appexamplekey.pem、証明書mainexamplecacert.pem、appexamplecert.pemを使用します。

OpenSplice通信機能の利用

Vortex OpenspliceはADLINK社が開発しているOMG DDS 1.4、DDSI-RTPS 2.3仕様の通信ミドルウェアです。

以下ではOpenRTM-aistのOpenSpliceプラグインのインストール、使用手順を説明します。

C++版

Windows

OpenSpliceの入手

以下からOpenSpliceをダウンロードして適当な場所に展開してください。

RapidXmlの入手

以下からRapidXmlをダウンロードして適当な場所に展開してください。

展開したら新たにrapidxmlフォルダを作成してヘッダーファイル(.hpp)をそこに移動させてください。 この時、展開したパスは以下のようになっています。

 rapidxml-1.13
    |- rapidxml
            |- rapidxml.hpp
            |- rapidxml_iterators.hpp
            |- rapidxml_print.hpp
            |- rapidxml_utils.hpp

OpenRTM-aistのビルド

OpenRTM-aistをビルドする前に、OpenSpliceのrelease.batを実行します。

 %OpenSplice_DIR%\x86.win32\release.bat

CMake実行時にOPENSPLICE_ENABLEオプションをONに設定し、RAPIDXML_DIRオプションにRapidXmlを展開したパスを指定します。

 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc16 -G "Visual Studio 16 2019" -DOPENSPLICE_ENABLE=ON -DRAPIDXML_DIR=%RAPIDXML_DIR% ..

その他の手順は通常と同じです。

適当な場所にインストールしてください。

インストールするディレクトリはCMAKE_INSTALL_PREFIXのオプションで設定します。

 cmake .. -DCMAKE_INSTALL_PREFIX=C:/workspace/OpenRTM-aist/build/install
 cmake --build . --config Release --target install

動作確認

{インストールしたパス}\2.0.0\Components\C++\Examples\vc16のサンプルコンポーネントを実行します。 RTC起動前にOpenSpliceのrelease.batを実行してください。

以下の内容のrtc.confを作成してください。

 manager.modules.load_path: {インストールしたパス}\\2.0.0\\ext\\transport
 manager.modules.preload: OpenSpliceTransport.dll
 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice, ConsoleIn0.out?interface_type=opensplice
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

まずOpenSpliceTransport.dllのロードが必要になります。 この設定はmanager.modules.preloadのオプションで設定できます。

次にコネクタ生成時にインターフェース型をopenspliceに設定する必要があります。 コネクタの生成はmanager.components.preconnectオプションにより設定します。 この例ではConsoleOut0コンポーネントのinのポート、ConsoleIn0コンポーネントのoutのポートにそれぞれコネクタを生成しています。

ConsoleInComp.exeConsoleOutComp.exeを実行すると通信ができるようになります。

Ubuntu

OpenSpliceの入手

以下からOpenSpliceをダウンロードして適当な場所に展開してください。

 wget https://github.com/ADLINK-IST/opensplice/releases/download/OSPL_V6_9_210323OSS_RELEASE/PXXX-VortexOpenSplice-6.9.210323OSS-HDE-x86_64.linux-gcc7-glibc2.27-installer.tar
 tar xf PXXX-VortexOpenSplice-6.9.210323OSS-HDE-x86_64.linux-gcc7-glibc2.27-installer.tar 

RapidXmlのインストール

以下のコマンドでRapidXmlをインストールしてください。

 sudo apt install librapidxml-dev

OpenRTM-aistのビルド

OpenRTM-aistをビルドする前に、OpenSpliceのrelease.comを実行します。

 source ${OPENSPLICE_DIR}/x86_64.linux/release.com

CMake実行時にOPENSPLICE_ENABLEオプションをONに設定します。

 cmake -DOPENSPLICE_ENABLE=ON ..

その他の手順は通常と同じです。

適当な場所にインストールしてください。

インストールするディレクトリはCMAKE_INSTALL_PREFIXのオプションで設定します。

 cmake .. -DCMAKE_INSTALL_PREFIX=~/workspace/OpenRTM-aist/build/install
 cmake --build . --config Release --target install

動作確認

{インストールしたパス}/share/openrtm-2.0/components/c++/examplesのサンプルコンポーネントを実行します。 RTC起動前にOpenSpliceのrelease.comを実行してください。

以下の内容のrtc.confを作成してください。

 manager.modules.load_path: {インストールしたパス}/lib/openrtm-2.0
 manager.modules.preload: OpenSpliceTransport.so
 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice, ConsoleIn0.out?interface_type=opensplice
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

まずOpenSpliceTransport.soのロードが必要になります。 この設定はmanager.modules.preloadのオプションで設定できます。

次にコネクタ生成時にインターフェース型をopenspliceに設定する必要があります。 コネクタの生成はmanager.components.preconnectオプションにより設定します。 この例ではConsoleOut0コンポーネントのinのポート、ConsoleIn0コンポーネントのoutのポートにそれぞれコネクタを生成しています。

ConsoleInCompConsoleOutCompを実行すると通信ができるようになります。

Python版

Windows

OpenSpliceのインストール

まずはOpenSpliceのPythonラッパーライブラリをインストールする必要があります。

適当な場所にビルド済みのOpenSpliceを展開してください。

次に展開したフォルダのHDE\x86_64.win64\tools\python\srcで以下のコマンドを実行するとインストールされます。

 {OpenSpliceを展開したディレクトリ}\HDE\x86_64.win64\release.bat
 python setup.py build
 python setup.py install

Cythonをインストールしていない場合は以下のコマンドを実行してください。

 pip install cython

※上記のsetup.pyによるビルドにはPythonをビルドしたVisual Studioと同じバージョンのVisual Studioがインストールされている必要があります。 Python 2.7ではVisual Studio 2008、Python 3.7ではVisual Studio 2017が必要になります。

OpenRTM-aistのインストール

OpenRTM-aist 1.2等をインストーラーでインストールしておいてください。 OpenRTM-aist Python版のソースコードを入手してください。

以下のコマンドでOpenRTM-aist Python版をインストールしてください。

 python setup.py build
 python setup.py install

動作確認

動作前に以下のコマンドを実行してください。

  {OpenSpliceを展開したディレクトリ}\HDE\x86_64.win64\release.bat

以下のようなrtc.confを作成し、OpenSpliceTransport.pyをロード後、インターフェース型にopenspliceを指定してRTCを起動します。

 manager.modules.load_path: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\transport\\OpenSplice
 manager.modules.preload: OpenSpliceTransport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice&marshaling_type=opensplice, ConsoleIn0.out?interface_type=opensplice&marshaling_type=opensplice

Ubuntu

OpenSpliceのインストール

まずはOpenSpliceのPythonラッパーライブラリをインストールする必要があります。 以下からOpenSpliceをダウンロードして適当な場所に展開してください。

 wget https://github.com/ADLINK-IST/opensplice/releases/download/OSPL_V6_9_210323OSS_RELEASE/PXXX-VortexOpenSplice-6.9.210323OSS-HDE-x86_64.linux-gcc7-glibc2.27-installer.tar
 tar xf PXXX-VortexOpenSplice-6.9.210323OSS-HDE-x86_64.linux-gcc7-glibc2.27-installer.tar 

次に展開したフォルダのHDE/x86_64.linux/tools/python/srcで以下のコマンドを実行するとインストールされます。

 source ${OPENSPLICE_DIR}/x86_64.linux/release.com
 python3 setup.py build
 sudo su
 # source ${OPENSPLICE_DIR}/x86_64.linux/release.com
 # python3 setup.py install
 # exit

Cythonをインストールしていない場合は以下のコマンドを実行してください。

 sudo apt install python3-pip
 pip3 install cython

omniORB-pythonのインストール

omniORBのPython版をインストールします。

 sudo su
 # echo "deb http://openrtm.org/pub/Linux/ubuntu/ $code_name main" >> /etc/apt/sources.list
 # wget -O- --secure-protocol=TLSv1_2 --no-check-certificate https://openrtm.org/pub/openrtm.key | apt-key add -
 # apt update
 # apt install python3-omniorb python3-omniorb-omg omniidl-python3
 # exit

OpenRTM-aistのインストール

OpenRTM-aist 1.2等をインストーラーでインストールしておいてください。 OpenRTM-aist Python版のソースコードを入手してください。

以下のコマンドでOpenRTM-aist Python版をインストールしてください。

 sudo apt install doxygen
 python3 setup.py build
 sudo python3 setup.py install

動作確認

動作前にrelease.comを実行してください。

以下のようなrtc.confを作成し、OpenSpliceTransport.pyをロード後、インターフェース型にopenspliceを指定してRTCを起動します。

 manager.modules.load_path: /usr/local/lib/python3.6/dist-packages/OpenRTM_aist/ext/transport/OpenSplice
 manager.modules.preload: OpenSpliceTransport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice&marshaling_type=opensplice, ConsoleIn0.out?interface_type=opensplice&marshaling_type=opensplice

起動時のオプション

C++

rtc.confでOpenRTM-aistのマネージャ起動時に以下のオプションを設定可能です。 ※開発中のOpenRTM-aistでは使用可能ですが、リリースしたバージョンでは未実装の場合があります。

オプション名 設定例 オプション 内容
opensplice.uri file://OpenSpliceQoSExample.xml OpenSpliceのQoS設定ファイルを指定する。
opensplice.profile testProfile QoSのプロファイル名を指定する。
opensplice.participant_qos.name testParticipant ロードするDomainParticipantのプロファイル名
opensplice.participant_qos.entity_factory.autoenable_created_entities YES YES,NO
opensplice.participant_qos.listener_scheduling.scheduling_class.kind SCHEDULE_DEFAULT SCHEDULE_DEFAULT,SCHEDULE_TIMESHARING,SCHEDULE_REALTIME
opensplice.participant_qos.listener_scheduling.scheduling_priority 1
opensplice.participant_qos.listener_scheduling.scheduling_priority_kind.kind PRIORITY_RELATIVE PRIORITY_RELATIVE,PRIORITY_ABSOLUTE
opensplice.participant_qos.watchdog_scheduling.scheduling_class.kind SCHEDULE_DEFAULT SCHEDULE_DEFAULT,SCHEDULE_TIMESHARING,SCHEDULE_REALTIME
opensplice.participant_qos.watchdog_scheduling.scheduling_priority 1
opensplice.participant_qos.watchdog_scheduling.scheduling_priority_kind.kind PRIORITY_RELATIVE PRIORITY_RELATIVE,PRIORITY_ABSOLUTE
opensplice.publisher_qos.entity_factory.autoenable_created_entities YES YES,NO
opensplice.publisher_qos.presentation.access_scope INSTANCE_PRESENTATION_QOS INSTANCE_PRESENTATION_QOS,TOPIC_PRESENTATION_QOS,GROUP_PRESENTATION_QOS
opensplice.publisher_qos.presentation.coherent_access YES YES,NO
opensplice.publisher_qos.presentation.ordered_access YES YES,NO
opensplice.publisher_qos.id testPublisher ロードするPublisherのプロファイル名
opensplice.subscriber_qos.entity_factory.autoenable_created_entities YES YES,NO
opensplice.subscriber_qos.presentation.access_scope INSTANCE_PRESENTATION_QOS INSTANCE_PRESENTATION_QOS,TOPIC_PRESENTATION_QOS,GROUP_PRESENTATION_QOS
opensplice.subscriber_qos.presentation.coherent_access YES YES,NO
opensplice.subscriber_qos.presentation.ordered_access YES YES,NO
opensplice.subscriber_qos.share.enable YES YES,NO
opensplice.subscriber_qos.id testSubscriber ロードするSubscriberのプロファイル名

以下に記述例を記載します。

 opensplice.uri: file://OpenSpliceQoSExample.xml
 opensplice.profile: testProfile

Python

オプション名 設定例 オプション 内容
opensplice.uri file://OpenSpliceQoSExample.xml OpenSpliceのQoS設定ファイルを指定する。
opensplice.profile testProfile QoSのプロファイル名を指定する。
opensplice.publisher_qos.presentation.access_scope
opensplice.publisher_qos.presentation.coherent_access
opensplice.publisher_qos.presentation.ordered_access
opensplice.subscriber_qos.presentation.access_scope
opensplice.subscriber_qos.presentation.coherent_access
opensplice.subscriber_qos.presentation.ordered_access

以下に記述例を記載します。

 opensplice.uri: file://OpenSpliceQoSExample.xml
 opensplice.profile: testProfile

接続時のオプション

C++

データポート接続時のコネクタプロファイルに設定できるオプションは以下の通りです。

オプション名 デフォルト値 オプション 内容
opensplice.topic chatter DDSトピックの名前
opensplice.reader_qos.id ロードするReaderのプロファイル名
opensplice.writer_qos.id ロードするWriterのプロファイル名
opensplice.topic_qos.id ロードするTopicのプロファイル名
opensplice.reader_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.reader_qos.deadline.period.sec 2147483647
opensplice.reader_qos.deadline.period.nanosec 2147483647
opensplice.reader_qos.latency_budget.duration.sec 0
opensplice.reader_qos.latency_budget.duration.nanosec 0
opensplice.reader_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.reader_qos.liveliness.lease_duration.sec 2147483647
opensplice.reader_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.reader_qos.reliability.kind BEST_EFFORT_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.reader_qos.reliability.max_blocking_time.sec 2147483647
opensplice.reader_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.reader_qos.reliability.synchronous NO YES, NO
opensplice.reader_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.reader_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.reader_qos.history.depth 1
opensplice.reader_qos.resource_limits.max_samples -1
opensplice.reader_qos.resource_limits.max_instances -1
opensplice.reader_qos.resource_limits.max_samples_per_instance -1
opensplice.reader_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.reader_qos.time_based_filter.minimum_separation.sec 0
opensplice.reader_qos.time_based_filter.minimum_separation.nanosec 0
opensplice.reader_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.sec 2147483647
opensplice.reader_qos.reader_data_lifecycle.autopurge_disposed_samples_delay.nanosec 2147483647
opensplice.reader_qos.reader_data_lifecycle.autopurge_dispose_all NO YES, NO
opensplice.reader_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.sec 2147483647
opensplice.reader_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec 2147483647
opensplice.reader_qos.reader_data_lifecycle.enable_invalid_samples YES YES, NO
opensplice.reader_qos.reader_data_lifecycle.invalid_sample_visibility.kind MINIMUM_INVALID_SAMPLES NO_INVALID_SAMPLES, MINIMUM_INVALID_SAMPLES, ALL_INVALID_SAMPLES
opensplice.writer_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.writer_qos.deadline.period.sec 2147483647
opensplice.writer_qos.deadline.period.nanosec 2147483647
opensplice.writer_qos.latency_budget.duration.sec 0
opensplice.writer_qos.latency_budget.duration.nanosec 0
opensplice.writer_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.writer_qos.liveliness.lease_duration.sec 2147483647
opensplice.writer_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.writer_qos.reliability.kind RELIABLE_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.writer_qos.reliability.max_blocking_time.sec 2147483647
opensplice.writer_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.writer_qos.reliability.synchronous NO YES, NO
opensplice.writer_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.writer_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.writer_qos.history.depth 1
opensplice.writer_qos.resource_limits.max_samples -1
opensplice.writer_qos.resource_limits.max_instances -1
opensplice.writer_qos.resource_limits.max_samples_per_instance -1
opensplice.writer_qos.transport_priority.value 0
opensplice.writer_qos.lifespan.duration.sec 2147483647
opensplice.writer_qos.lifespan.duration.nanosec 2147483647
opensplice.writer_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.writer_qos.ownership_strength.value 0
opensplice.writer_qos.writer_data_lifecycle.autodispose_unregistered_instances YES YES, NO
opensplice.writer_qos.writer_data_lifecycle.autopurge_suspended_samples_delay.sec 2147483647
opensplice.writer_qos.writer_data_lifecycle.autopurge_suspended_samples_delay.nanosec 2147483647
opensplice.writer_qos.writer_data_lifecycle.autounregister_instance_dela.sec 2147483647
opensplice.writer_qos.writer_data_lifecycle.autounregister_instance_dela.nanosec 2147483647
opensplice.topic_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.topic_qos.deadline.period.sec 2147483647
opensplice.topic_qos.deadline.period.nanosec 2147483647
opensplice.topic_qos.latency_budget.duration.sec 0
opensplice.topic_qos.latency_budget.duration.nanosec 0
opensplice.topic_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.topic_qos.liveliness.lease_duration.sec 2147483647
opensplice.topic_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.topic_qos.reliability.kind RELIABLE_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.topic_qos.reliability.max_blocking_time.sec 2147483647
opensplice.topic_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.topic_qos.reliability.synchronous NO YES, NO
opensplice.topic_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.topic_qos.history.kind KEEP_ALL_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.topic_qos.history.depth 1
opensplice.topic_qos.resource_limits.max_samples -1
opensplice.topic_qos.resource_limits.max_instances -1
opensplice.topic_qos.resource_limits.max_samples_per_instance -1
opensplice.topic_qos.transport_priority.value 0
opensplice.topic_qos.lifespan.duration.sec 2147483647
opensplice.topic_qos.lifespan.duration.nanosec 2147483647
opensplice.topic_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.topic_qos.transport_priority.value 0
opensplice.topic_qos.durability_service.history_depth 1
opensplice.topic_qos.durability_service.history_kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.topic_qos.durability_service.max_instances -1
opensplice.topic_qos.durability_service.max_samples -1
opensplice.topic_qos.durability_service.max_samples_per_instance -1
opensplice.topic_qos.durability_service.service_cleanup_delay.sec 0
opensplice.topic_qos.durability_service.service_cleanup_delay.nanosec 0

以下に設定例を記載します。

 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice&opensplice.topic=testtopic

Python

オプション名 デフォルト値 オプション 内容
opensplice.topic chatter DDSトピックの名前
opensplice.reader_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.reader_qos.deadline.period.sec 2147483647
opensplice.reader_qos.deadline.period.nanosec 2147483647
opensplice.reader_qos.latency_budget.duration.sec 0
opensplice.reader_qos.latency_budget.duration.nanosec 0
opensplice.reader_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.reader_qos.liveliness.lease_duration.sec 2147483647
opensplice.reader_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.reader_qos.reliability.kind BEST_EFFORT_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.reader_qos.reliability.max_blocking_time.sec 2147483647
opensplice.reader_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.reader_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.reader_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.reader_qos.history.depth 1
opensplice.reader_qos.resource_limits.max_samples -1
opensplice.reader_qos.resource_limits.max_instances -1
opensplice.reader_qos.resource_limits.max_samples_per_instance -1
opensplice.reader_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.reader_qos.time_based_filter.minimum_separation.sec 0
opensplice.reader_qos.time_based_filter.minimum_separation.nanosec 0
opensplice.reader_qos.autopurge_disposed_samples_delay.sec 2147483647
opensplice.reader_qos.autopurge_disposed_samples_delay.nanosec 2147483647
opensplice.reader_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.sec 2147483647
opensplice.reader_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec 2147483647
opensplice.writer_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.writer_qos.deadline.period.sec 2147483647
opensplice.writer_qos.deadline.period.nanosec 2147483647
opensplice.writer_qos.latency_budget.duration.sec 0
opensplice.writer_qos.latency_budget.duration.nanosec 0
opensplice.writer_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.writer_qos.liveliness.lease_duration.sec 2147483647
opensplice.writer_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.writer_qos.reliability.kind BEST_EFFORT_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.writer_qos.reliability.max_blocking_time.sec 2147483647
opensplice.writer_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.writer_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.writer_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.writer_qos.history.depth 1
opensplice.writer_qos.resource_limits.max_samples -1
opensplice.writer_qos.resource_limits.max_instances -1
opensplice.writer_qos.resource_limits.max_samples_per_instance -1
opensplice.writer_qos.transport_priority.value SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.writer_qos.lifespan.duration.sec 0
opensplice.writer_qos.lifespan.duration.nanosec 0
opensplice.writer_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.writer_qos.ownership_strength.value 0
opensplice.writer_qos.writer_data_lifecycle.autodispose_unregistered_instances YES YES, NO
opensplice.topic_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, TRANSIENT_DURABILITY_QOS, PERSISTENT_DURABILITY_QOS
opensplice.topic_qos.deadline.period.sec 2147483647
opensplice.topic_qos.deadline.period.nanosec 2147483647
opensplice.topic_qos.latency_budget.duration.sec 0
opensplice.topic_qos.latency_budget.duration.nanosec 0
opensplice.topic_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_PARTICIPANT_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS
opensplice.topic_qos.liveliness.lease_duration.sec 2147483647
opensplice.topic_qos.liveliness.lease_duration.nanosec 2147483647
opensplice.topic_qos.reliability.kind RELIABLE_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS
opensplice.topic_qos.reliability.max_blocking_time.sec 2147483647
opensplice.topic_qos.reliability.max_blocking_time.nanosec 2147483647
opensplice.topic_qos.destination_order.kind BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS, BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
opensplice.topic_qos.history.kind KEEP_ALL_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.topic_qos.history.depth 1
opensplice.topic_qos.resource_limits.max_samples -1
opensplice.topic_qos.resource_limits.max_instances -1
opensplice.topic_qos.resource_limits.max_samples_per_instance -1
opensplice.topic_qos.transport_priority.value 0
opensplice.topic_qos.lifespan.duration.sec 2147483647
opensplice.topic_qos.lifespan.duration.nanosec 2147483647
opensplice.topic_qos.ownership.kind SHARED_OWNERSHIP_QOS SHARED_OWNERSHIP_QOS, EXCLUSIVE_OWNERSHIP_QOS
opensplice.topic_qos.transport_priority.value 0
opensplice.topic_qos.durability_service.history_depth 1
opensplice.topic_qos.durability_service.history_kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS
opensplice.topic_qos.durability_service.max_instances -1
opensplice.topic_qos.durability_service.max_samples -1
opensplice.topic_qos.durability_service.max_samples_per_instance -1
opensplice.topic_qos.durability_service.service_cleanup_delay.sec 0
opensplice.topic_qos.durability_service.service_cleanup_delay.nanosec 0

 manager.components.preconnect: ConsoleOut0.in?interface_type=opensplice&opensplice.topic=testtopic

その他

OpenSpliceのコンフィギュレーションファイル

OpenSpliceのコンフィギュレーションファイルは環境変数${OSPL_URI}で設定している。

デフォルトでは${OSPL_URI}/etc/config/ospl.xmlが設定されている。

例えば、ドメインIDを変更するためにはospl.xmlの以下の部分を変更する。

 <OpenSplice>
     <Domain>
         <Name>ospl_sp_ddsi</Name>
         <!-- 以下を変更する -->
         <Id>1</Id>
         <SingleProcess>true</SingleProcess>

詳細なログを出力するためには以下の部分を追加する。

    <DDSI2Service name="ddsi2">
        <!-- 以下を追加する -->
        <Tracing>
             <Verbosity>FINEST</Verbosity>
        </Tracing>
        <!-- ここまで -->
        <General>

SSM通信機能の利用

このページではSSM(Streaming-data-Sharing-Manager )との通信プラグインの導入手順を説明します。

以降の作業はUbuntu 18.04環境を想定しています。

SSMのインストール

以下のコマンドでSSMをインストールします。

 git clone https://github.com/sitRyo/Distributed-Streaming-data-Sharing-Manager -b 32-64bit
 cd Distributed-Streaming-data-Sharing-Manager/
 ./configure --prefix=${OPENRTM_INSTALL_DIR}
 sudo autoreconf -i -f
 make
 make install

OpenRTM-aistのビルド、インストール

CMake実行時にSSM_ENABLEのオプションをONにします。SSMのインストール先を指定する場合はSSM_ROOTを設定します。

 cmake -DSSM_ENABLE=ON -DSSM_ROOT=${OPENRTM_INSTALL_DIR} ..

その他の手順は通常と同じです。

ビルド後にインストールしてください。

 cmake --build . --config Release --target install

動作確認

以下のrtc.confを作成します。

 manager.modules.load_path: /usr/local/lib/openrtm-2.0/transport/
 manager.modules.preload: SSMTransport.so
 manager.components.preconnect: ConsoleOut0.in?interface_type=ssm&ssm.stream_name=test_stream&dataflow_type=pull, ConsoleIn0.out?interface_type=ssm&ssm.stream_name=test_stream
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

RTCを起動する前にssm-coordinatorを起動します。

 ssm-coordinator

ConsoleInComp、ConsoleOutCompをそれぞれ別のターミナルで起動するとデータの転送が確認できます。

接続時のオプション

データポート接続時のコネクタプロファイルに設定できるオプションは以下の通りです。

オプション名 デフォルト値 内容
ssm.stream_name sensor_test
ssm.stream_size 0
ssm.life_ssm_time 5.0
ssm.cycle_ssm_time 0.05
ssm.stream_id 0

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、ROSTransportの簡単な動作確認用の設定ファイルがインストールされます。

 ${SSM_INSTALL_DIR}/bin/ssm-coordinator

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/transport/rtc.ssm.conf

Fluent Loggerによるログ収集

Fluentd、Fluent Bitはログの処理や転送を行うオープンソースのソフトウェアライブラリです。

Fluentd、Fluent Bitはデータを収集するInputプラグイン、データを送信するOutputプラグインを設定できます。 Fluentd、Fluent Bitの概要図は以下のようになっています。

fluentbit2.png

Inputは外部プロセスから受信、プロセス内部からのログ書き込み、CPU使用率やディスク使用率等を取得するなどで収集したデータをOutputに渡します。 Outputは受け取ったデータを外部プロセスへ送信、ファイルへ書き込み、標準出力等します。 Input、Outputはプラグインとして実装されており、プラグインを変更することでデータの収集方法や送信方法を変更できるため、以下のような様々なデータの収集方法、送信方法を選択できます。

またInputからOutputにデータを渡す前にFilterでデータの変換、追加、除外等を実行できます。

Inputにはタグが設定でき、Output、Filterにはマッチングルールを設定できます。 Output、Filerはマッチングルールに一致したタグのデータを受け取ることができます。

このページではOpenRTM-aistのFluent Loggerプラグインの使用方法を説明します。

C++版

Windows

Fluent Bitのインストール

Fluent BitのビルドにBison/Flexが必要なため適当な場所に展開して環境変数PATHに設定します。

set PATH=%WORKDIR%\win_flex_bison-2.5.24;%PATH%

OpenSSLを適当な場所に展開してください。

Windows用に修正したFluent Bitのソースコードを適当な場所に展開してPowerShellでそのフォルダに移動してください。

PowerShellで以下のコマンドを実行するとFluent Bitをビルドします。

 cmake -DFLB_RELEASE=On -DFLB_TRACE=Off -DFLB_SHARED_LIB=On -DFLB_EXAMPLES=Off  -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=${OpenSSL_INSTALL_DIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${FLUENTBIT_INSTALL_DIR}
 cmake --build . --config Release
 cmake --build . --target install --config Release

各種ライブラリのインストール

以下のコマンドで必要なヘッダーファイルをコピーします。

 $FLUENTBIT_BUILD_DIR = "${FLUENTBIT_SOURCE_DIR}\build"

 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\include\monkey\mk_core\external -destination $FLUENTBIT_INSTALL_DIR\include\monkey\mk_core -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\event.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\evutil.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\event2 -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\monkey\mk_core\deps\libevent\include\event2\event-config.h $FLUENTBIT_INSTALL_DIR\include\event2
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\msgpack-*\include\msgpack.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\msgpack-*\include\msgpack -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\mbedtls-*\include\mbedtls -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\c-ares-*\include\*.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_build.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_config.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_config.h $FLUENTBIT_INSTALL_DIR\include
 New-Item $FLUENTBIT_INSTALL_DIR\lib\fluent-bit -ItemType Directory
 Copy-Item $FLUENTBIT_BUILD_DIR\library\Release\fluent-bit.lib $FLUENTBIT_INSTALL_DIR\lib\fluent-bit
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\cmetrics\include\cmetrics -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\cmetrics\include\prometheus_remote_write -destination $FLUENTBIT_INSTALL_DIR\include -recurs

OpenRTM-aistのビルド

CMake実行時にFLUENTBIT_ENABLEFLUENTBIT_ROOTのオプションを設定します。

 cmake -DORB_ROOT=$ORB_ROOT -DFLUENTBIT_ENABLE=ON -DFLUENTBIT_ROOT=$FLUENTBIT_INSTALL_DIR -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR

他の手順は通常のビルド手順と同じです。

以下のコマンドでインストールしてください。

 cmake --build . --target install --config Release

動作確認

td-agent、もしくはtd-agent-bitをインストール、起動する必要があります。

RTCの起動

rtc.confで以下のように設定する。tagの名前は適宜変更する。

 
 logger.plugins: C:\\Program Files\\OpenRTM-aist\\logger\\2.0.0\\FluentBit.dll
 logger.logstream.fluentd.output0.plugin: forward
 logger.logstream.fluentd.output0.conf.match:*
 
 logger.logstream.fluentd.input0.plugin: lib
 logger.logstream.fluentd.input0.conf.tag: test.simpleio

RTCを実行するとログを送信する。

またはOpenRTM-aistに含まれるrtc.fluentbit_stream.confを使用して起動することもできます。

 ${OPENRTM_INSTALL_DIR}\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f ${OPENRTM_INSTALL_DIR}\2.0.0\ext\logger\rtc.fluentbit_stream.conf

Ubuntu

Fluent Bitのインストール

 sudo apt install flex bison
 wget https://github.com/fluent/fluent-bit/archive/v1.8.9.tar.gz
 tar xf v1.8.9.tar.gz
 cd fluent-bit-1.8.9/
 sed  -i -e 's/jemalloc-5.2.1\/configure/jemalloc-5.2.1\/configure --disable-initial-exec-tls/g' CMakeLists.txt
 cd build
 cmake .. -DFLB_RELEASE=On -DFLB_TRACE=Off -DFLB_JEMALLOC=On -DFLB_TLS=On -DFLB_SHARED_LIB=On -DFLB_EXAMPLES=Off -DFLB_HTTP_SERVER=On -DFLB_IN_SYSTEMD=On -DFLB_OUT_KAFKA=Off
 cmake --build . --config Release -- -j$(nproc)
 sudo cmake --build . --target install

各種ライブラリのインストール

以下のコマンドで必要なヘッダーファイルをコピーします。

 export FLUENTBIT_SOURCE_DIR=${WORKSPACE}/fluent-bit-1.8.9
 export FLUENTBIT_BUILD_DIR = ${FLUENTBIT_SOURCE_DIR}/build
 export FLUENTBIT_INSTALL_DIR=/usr/local

 mkdir -p ${FLUENTBIT_INSTALL_DIR}/include/lib/flb_libco
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/flb_libco/libco.h ${FLUENTBIT_INSTALL_DIR}/include/lib/flb_libco
 cp -r ${FLUENTBIT_BUILD_DIR}/include/jemalloc ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/msgpack-*/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/monkey/include/monkey ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/mbedtls-*/include/mbedtls ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/c-ares-*/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_BUILD_DIR}/lib/c-ares-*/ares_build.h ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_BUILD_DIR}/lib/c-ares-*/ares_config.h ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/cmetrics/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp ${FLUENTBIT_SOURCE_DIR}/lib/flb_libco/libco.h ${FLUENTBIT_INSTALL_DIR}/include/

OpenRTM-aistのビルド

CMake実行時にFLUENTBIT_ENABLEFLUENTBIT_ROOTのオプションを設定します。

 cmake -DFLUENTBIT_ENABLE=ON -DFLUENTBIT_ROOT=${FLUENTBITINSTALLDIR} ..

他の手順は通常のビルド手順と同じです。

以下のコマンドでインストールしてください。

 cmake --build . --target install

動作確認

td-agent、もしくはtd-agent-bitをインストール、起動する必要があります。

RTCの起動

rtc.confで以下のように設定する。tagの名前は適宜変更する。

 logger.plugins: /usr/local/lib/openrtm-2.0/logger/FluentBit.so
 logger.logstream.fluentd.output0.plugin: forward
 logger.logstream.fluentd.output0.conf.match:*
 
 logger.logstream.fluentd.input0.plugin: lib
 logger.logstream.fluentd.input0.tag: test.simpleio

RTCを実行するとログを送信する。

動作しない場合は/etc/ssl/certsから壊れたリンクを削除する。

またはOpenRTM-aistに含まれるrtc.fluentbit_stream.confを使用して起動することもできます。

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/logger/rtc.fluentbit_stream.conf

Python版

Python版のFluent LoggerプラグインはForward Outputのみに対応しています。 別にForward通信を受信するFluentd、Fluent Bitを起動して、処理して他のOutputプラグインで送信するという使い方ができます。

fluent-logger-pythonのインストール

fluent-logger-pythonのインストールが必要です。

 pip install fluent-logger

Ubuntuの場合はsudoで実行してください。

動作確認

td-agent、もしくはtd-agent-bitをインストールする必要があります。

RTCの起動

rtc.confに以下のように記述してRTCを起動するとfluentdにログが送信されます。

 manager.modules.load_path: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\logger\\fluentlogger
 logger.plugins: FluentLogger.py
 logger.logstream.fluentd.output0.tag: test.simpleio

manager.modules.load_pathはOpenRTM-aistをインストールしたPythonのパスによって適宜変更してください。 Ubuntuの場合は/usr/local/lib/python2.7/dist-packages/OpenRTM_aist/ext/logger/fluentlogger等になります。

fluentdでログは以下のように表示される。

 2018-12-26 09:06:18.000000000 +0900 test.simpleio: {"message":"exit","time":"2018-12-26 09:06:18,841","name":"fluent.ec_worker","level":"TRACE"}

メッセージの内容、名前、ログを送信した時間、ログレベルが送信される。

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、Fluent Loggerプラグインの簡単な動作確認用の設定ファイルがインストールされます。

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\logger\rtc.fluentbit_stream.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/logger/rtc.fluentbit_stream.conf

Kibana+Elasticsearchによるログ可視化

KibanaはElastic社の開発したデータ可視化ツールです。 分析エンジンElasticSearchと連携してWebブラウザ上でグラフなどのデータ可視化ができるようになります。

OpenRTM-aistのFluent BitプラグインからElasticSearchにログを送信して、Kibanaでデータを可視化する手順を説明します。

Elasticsearchのインストール

Ubuntu 18.04環境で以下のコマンドによりElasticsearchをインストールします。 Ubuntu 18.04ではElasticsearchのバージョン次第で動作しない場合があるので、こちらで動作を確認した7.8.0をインストールします。

 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
 add-apt-repository "deb https://artifacts.elastic.co/packages/7.x/apt stable main"
 sudo apt update
 sudo apt install elasticsearch=7.8.0
 sudo systemctl daemon-reload
 sudo systemctl enable elasticsearch.service

/etc/elasticsearch/elasticsearch.ymlを編集します。

 network.bind_host: 0
 discovery.seed_hosts: ["127.0.0.1", "[::1]"]

編集後にサービスを再起動します。

 sudo systemctl restart elasticsearch.service

メモリの不足で起動できない場合は/etc/elasticesearch/jvm.optionsを編集して調節してください。

 -Xms1g
 -Xmx1g

Kibanaのインストール

以下のコマンドでKibanaをインストールします。Elasticsearchと同じバージョンを指定します。

 sudo apt install kibana=7.8.0
 sudo systemctl daemon-reload
 sudo systemctl enable kibana.service

また、/etc/kibana/kibana.ymlに以下の行を追加します。

 server.port: 5601
 server.host: "0.0.0.0"

server.hostにNICに設定されたIPアドレスを指定してください。

 server.host: "192.168.11.2"

サービスを再起動します。

 sudo systemctl restart kibana.service

動作確認

以下のrtc.confを作成してください。

 logger.enable: YES
 logger.log_level: INFO
 
 
 logger.plugins: ${OPNRTM_INSTALL_DIR}/lib/openrtm-2.0/logger/FluentBit.so
 
 logger.logstream.fluentd.input.plugin: lib
 logger.logstream.fluentd.input.conf.tag: myRTCs_log
 
 logger.logstream.fluentd.output0.plugin: es
 logger.logstream.fluentd.output0.conf.match: *
 logger.logstream.fluentd.output0.conf.host: 127.0.0.1
 logger.logstream.fluentd.output0.conf.port: 9200
 logger.logstream.fluentd.output0.conf.Index: fluentbit

${OPNRTM_INSTALL_DIR}はOpenRTM-aistをインストールしたパスに置き換えてください。 hostportにElasticsearchのアドレスとポート番号を指定してください。 Indextagは任意の文字列を設定します。

このrtc.confを指定してRTCを起動します。

 ./share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

次にWebブラウザからKibanaにアクセスしてログを確認します。 http://127.0.0.1:5601にアクセスしてください。別の端末からアクセスする場合はIPアドレスを変更してください。

kibana1.png

可視化するデータのインデックスパターンを設定します。今回の例ではrtc.confでIndexをfluentbitに指定しました。 ページが開いたら左上をクリックして表示されたメニューからManagmentのStack Managementをクリックしてください。

kibana2.png

Stack Managementのページの左側のIndex Patternsをクリックします。

kibana3.png

Index patternsのページのCreate Index patternボタンを押します。

kibana4.png

Create index patternのページでIndex patternをfluentbit*に指定してNext stepボタンを押します。

kibana5.png

Step 2でTime Filter field nameは@timestampのままCreate index patternボタンを押します。

kibana6.png

ここからはデータを確認します。 ページ左上をクリックして、メニューからKibanaのDiscoverをクリックしてください。

kibana7.png

Discoverの画面で左側にインデックスパターンが表示されているため、インデックスパターンをクリックして先ほど設定したfluentbit*に切り替えます。

kibana8.png

これでログの一覧が確認できます。グラフなどで利用する手順についてはKibanaのマニュアルなどを参考にしてください。

kibana9.png

Pythonで動作確認

OpenRTM-aist Python版で動作確認する場合はElasticsearch Loggerプラグインを使用します。 まずはelasticsearchのPythonライブラリ、ECSentbit:https://fluentbit.io/]]

Fluentd、Fluent Bitはデータを収集するInputプラグイン、データを送信するOutputプラグインを設定できます。 Fluentd、Fluent Bitの概要図は以下のようになっています。

fluentbit2.png

Inputは外部プロセスから受信、プロセス内部からのログ書き込み、CPU使用率やディスク使用率等を取得するなどで収集したデータをOutputに渡します。 Outputは受け取ったデータを外部プロセスへ送信、ファイルへ書き込み、標準出力等します。 Input、Outputはプラグインとして実装されており、プラグインを変更することでデータの収集方法や送信方法を変更できるため、以下のような様々なデータの収集方法、送信方法を選択できます。

またInputからOutputにデータを渡す前にFilterでデータの変換、追加、除外等を実行できます。

Inputにはタグが設定でき、Output、Filterにはマッチングルールを設定できます。 Output、Filerはマッチングルールに一致したタグのデータを受け取ることができます。

このページではOpenRTM-aistのFluent Loggerプラグインの使用方法を説明します。

C++版

Windows

Fluent Bitのインストール

Fluent BitのビルドにBison/Flexが必要なため適当な場所に展開して環境変数PATHに設定します。

set PATH=%WORKDIR%\win_flex_bison-2.5.24;%PATH%

OpenSSLを適当な場所に展開してください。

Windows用に修正したFluent Bitのソースコードを適当な場所に展開してPowerShellでそのフォルダに移動してください。

PowerShellで以下のコマンドを実行するとFluent Bitをビルドします。

 cmake -DFLB_RELEASE=On -DFLB_TRACE=Off -DFLB_SHARED_LIB=On -DFLB_EXAMPLES=Off  -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=${OpenSSL_INSTALL_DIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${FLUENTBIT_INSTALL_DIR}
 cmake --build . --config Release
 cmake --build . --target install --config Release

各種ライブラリのインストール

以下のコマンドで必要なヘッダーファイルをコピーします。

 $FLUENTBIT_BUILD_DIR = "${FLUENTBIT_SOURCE_DIR}\build"

 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\include\monkey\mk_core\external -destination $FLUENTBIT_INSTALL_DIR\include\monkey\mk_core -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\event.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\evutil.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\monkey\mk_core\deps\libevent\include\event2 -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\monkey\mk_core\deps\libevent\include\event2\event-config.h $FLUENTBIT_INSTALL_DIR\include\event2
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\msgpack-*\include\msgpack.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\msgpack-*\include\msgpack -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\mbedtls-*\include\mbedtls -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\c-ares-*\include\*.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_build.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_config.h $FLUENTBIT_INSTALL_DIR\include
 Copy-Item $FLUENTBIT_BUILD_DIR\lib\c-ares-*\ares_config.h $FLUENTBIT_INSTALL_DIR\include
 New-Item $FLUENTBIT_INSTALL_DIR\lib\fluent-bit -ItemType Directory
 Copy-Item $FLUENTBIT_BUILD_DIR\library\Release\fluent-bit.lib $FLUENTBIT_INSTALL_DIR\lib\fluent-bit
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\cmetrics\include\cmetrics -destination $FLUENTBIT_INSTALL_DIR\include -recurs
 Copy-Item $FLUENTBIT_SOURCE_DIR\lib\cmetrics\include\prometheus_remote_write -destination $FLUENTBIT_INSTALL_DIR\include -recurs

OpenRTM-aistのビルド

CMake実行時にFLUENTBIT_ENABLEFLUENTBIT_ROOTのオプションを設定します。

 cmake -DORB_ROOT=$ORB_ROOT -DFLUENTBIT_ENABLE=ON -DFLUENTBIT_ROOT=$FLUENTBIT_INSTALL_DIR -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR

他の手順は通常のビルド手順と同じです。

以下のコマンドでインストールしてください。

 cmake --build . --target install --config Release

動作確認

td-agent、もしくはtd-agent-bitをインストール、起動する必要があります。

RTCの起動

rtc.confで以下のように設定する。tagの名前は適宜変更する。

 
 logger.plugins: C:\\Program Files\\OpenRTM-aist\\logger\\2.0.0\\FluentBit.dll
 logger.logstream.fluentd.output0.plugin: forward
 logger.logstream.fluentd.output0.conf.match:*
 
 logger.logstream.fluentd.input0.plugin: lib
 logger.logstream.fluentd.input0.conf.tag: test.simpleio

RTCを実行するとログを送信する。

またはOpenRTM-aistに含まれるrtc.fluentbit_stream.confを使用して起動することもできます。

 ${OPENRTM_INSTALL_DIR}\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f ${OPENRTM_INSTALL_DIR}\2.0.0\ext\logger\rtc.fluentbit_stream.conf

Ubuntu

Fluent Bitのインストール

 sudo apt install flex bison
 wget https://github.com/fluent/fluent-bit/archive/v1.8.9.tar.gz
 tar xf v1.8.9.tar.gz
 cd fluent-bit-1.8.9/
 sed  -i -e 's/jemalloc-5.2.1\/configure/jemalloc-5.2.1\/configure --disable-initial-exec-tls/g' CMakeLists.txt
 cd build
 cmake .. -DFLB_RELEASE=On -DFLB_TRACE=Off -DFLB_JEMALLOC=On -DFLB_TLS=On -DFLB_SHARED_LIB=On -DFLB_EXAMPLES=Off -DFLB_HTTP_SERVER=On -DFLB_IN_SYSTEMD=On -DFLB_OUT_KAFKA=Off
 cmake --build . --config Release -- -j$(nproc)
 sudo cmake --build . --target install

各種ライブラリのインストール

以下のコマンドで必要なヘッダーファイルをコピーします。

 export FLUENTBIT_SOURCE_DIR=${WORKSPACE}/fluent-bit-1.8.9
 export FLUENTBIT_BUILD_DIR = ${FLUENTBIT_SOURCE_DIR}/build
 export FLUENTBIT_INSTALL_DIR=/usr/local

 mkdir -p ${FLUENTBIT_INSTALL_DIR}/include/lib/flb_libco
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/flb_libco/libco.h ${FLUENTBIT_INSTALL_DIR}/include/lib/flb_libco
 cp -r ${FLUENTBIT_BUILD_DIR}/include/jemalloc ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/msgpack-*/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/monkey/include/monkey ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/mbedtls-*/include/mbedtls ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/c-ares-*/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_BUILD_DIR}/lib/c-ares-*/ares_build.h ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_BUILD_DIR}/lib/c-ares-*/ares_config.h ${FLUENTBIT_INSTALL_DIR}/include/
 cp -r ${FLUENTBIT_SOURCE_DIR}/lib/cmetrics/include/* ${FLUENTBIT_INSTALL_DIR}/include/
 cp ${FLUENTBIT_SOURCE_DIR}/lib/flb_libco/libco.h ${FLUENTBIT_INSTALL_DIR}/include/

OpenRTM-aistのビルド

CMake実行時にFLUENTBIT_ENABLEFLUENTBIT_ROOTのオプションを設定します。

 cmake -DFLUENTBIT_ENABLE=ON -DFLUENTBIT_ROOT=${FLUENTBITINSTALLDIR} ..

他の手順は通常のビルド手順と同じです。

以下のコマンドでインストールしてください。

 cmake --build . --target install

動作確認

td-agent、もしくはtd-agent-bitをインストール、起動する必要があります。

RTCの起動

rtc.confで以下のように設定する。tagの名前は適宜変更する。

 logger.plugins: /usr/local/lib/openrtm-2.0/logger/FluentBit.so
 logger.logstream.fluentd.output0.plugin: forward
 logger.logstream.fluentd.output0.conf.match:*
 
 logger.logstream.fluentd.input0.plugin: lib
 logger.logstream.fluentd.input0.tag: test.simpleio

RTCを実行するとログを送信する。

動作しない場合は/etc/ssl/certsから壊れたリンクを削除する。

またはOpenRTM-aistに含まれるrtc.fluentbit_stream.confを使用して起動することもできます。

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/logger/rtc.fluentbit_stream.conf

Python版

Python版のFluent LoggerプラグインはForward Outputのみに対応しています。 別にForward通信を受信するFluentd、Fluent Bitを起動して、処理して他のOutputプラグインで送信するという使い方ができます。

fluent-logger-pythonのインストール

fluent-logger-pythonのインストールが必要です。

 pip install fluent-logger

Ubuntuの場合はsudoで実行してください。

動作確認

td-agent、もしくはtd-agent-bitをインストールする必要があります。

RTCの起動

rtc.confに以下のように記述してRTCを起動するとfluentdにログが送信されます。

 manager.modules.load_path: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\logger\\fluentlogger
 logger.plugins: FluentLogger.py
 logger.logstream.fluentd.output0.tag: test.simpleio

manager.modules.load_pathはOpenRTM-aistをインストールしたPythonのパスによって適宜変更してください。 Ubuntuの場合は/usr/local/lib/python2.7/dist-packages/OpenRTM_aist/ext/logger/fluentlogger等になります。

fluentdでログは以下のように表示される。

 2018-12-26 09:06:18.000000000 +0900 test.simpleio: {"message":"exit","time":"2018-12-26 09:06:18,841","name":"fluent.ec_worker","level":"TRACE"}

メッセージの内容、名前、ログを送信した時間、ログレベルが送信される。

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、Fluent Loggerプラグインの簡単な動作確認用の設定ファイルがインストールされます。

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\logger\rtc.fluentbit_stream.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/logger/rtc.fluentbit_stream.conf

Kibana+Elasticsearchによるログ可視化

KibanaはElastic社の開発したデータ可視化ツールです。 分析エンジンElasticSearchと連携してWebブラウザ上でグラフなどのデータ可視化ができるようになります。

OpenRTM-aistのFluent BitプラグインからElasticSearchにログを送信して、Kibanaでデータを可視化する手順を説明します。

Elasticsearchのインストール

Ubuntu 18.04環境で以下のコマンドによりElasticsearchをインストールします。 Ubuntu 18.04ではElasticsearchのバージョン次第で動作しない場合があるので、こちらで動作を確認した7.8.0をインストールします。

 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
 add-apt-repository "deb https://artifacts.elastic.co/packages/7.x/apt stable main"
 sudo apt update
 sudo apt install elasticsearch=7.8.0
 sudo systemctl daemon-reload
 sudo systemctl enable elasticsearch.service

/etc/elasticsearch/elasticsearch.ymlを編集します。

 network.bind_host: 0
 discovery.seed_hosts: ["127.0.0.1", "[::1]"]

編集後にサービスを再起動します。

 sudo systemctl restart elasticsearch.service

メモリの不足で起動できない場合は/etc/elasticesearch/jvm.optionsを編集して調節してください。

 -Xms1g
 -Xmx1g

Kibanaのインストール

以下のコマンドでKibanaをインストールします。Elasticsearchと同じバージョンを指定します。

 sudo apt install kibana=7.8.0
 sudo systemctl daemon-reload
 sudo systemctl enable kibana.service

また、/etc/kibana/kibana.ymlに以下の行を追加します。

 server.port: 5601
 server.host: "0.0.0.0"

server.hostにNICに設定されたIPアドレスを指定してください。

 server.host: "192.168.11.2"

サービスを再起動します。

 sudo systemctl restart kibana.service

動作確認

以下のrtc.confを作成してください。

 logger.enable: YES
 logger.log_level: INFO
 
 
 logger.plugins: ${OPNRTM_INSTALL_DIR}/lib/openrtm-2.0/logger/FluentBit.so
 
 logger.logstream.fluentd.input.plugin: lib
 logger.logstream.fluentd.input.conf.tag: myRTCs_log
 
 logger.logstream.fluentd.output0.plugin: es
 logger.logstream.fluentd.output0.conf.match: *
 logger.logstream.fluentd.output0.conf.host: 127.0.0.1
 logger.logstream.fluentd.output0.conf.port: 9200
 logger.logstream.fluentd.output0.conf.Index: fluentbit

${OPNRTM_INSTALL_DIR}はOpenRTM-aistをインストールしたパスに置き換えてください。 hostportにElasticsearchのアドレスとポート番号を指定してください。 Indextagは任意の文字列を設定します。

このrtc.confを指定してRTCを起動します。

 ./share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

次にWebブラウザからKibanaにアクセスしてログを確認します。 http://127.0.0.1:5601にアクセスしてください。別の端末からアクセスする場合はIPアドレスを変更してください。

kibana1.png

可視化するデータのインデックスパターンを設定します。今回の例ではrtc.confでIndexをfluentbitに指定しました。 ページが開いたら左上をクリックして表示されたメニューからManagmentのStack Managementをクリックしてください。

kibana2.png

Stack Managementのページの左側のIndex Patternsをクリックします。

kibana3.png

Index patternsのページのCreate Index patternボタンを押します。

kibana4.png

Create index patternのページでIndex patternをfluentbit*に指定してNext stepボタンを押します。

kibana5.png

Step 2でTime Filter field nameは@timestampのままCreate index patternボタンを押します。

kibana6.png

ここからはデータを確認します。 ページ左上をクリックして、メニューからKibanaのDiscoverをクリックしてください。

kibana7.png

Discoverの画面で左側にインデックスパターンが表示されているため、インデックスパターンをクリックして先ほど設定したfluentbit*に切り替えます。

kibana8.png

これでログの一覧が確認できます。グラフなどで利用する手順についてはKibanaのマニュアルなどを参考にしてください。

kibana9.png

Pythonで動作確認

OpenRTM-aist Python版で動作確認する場合はElasticsearch Loggerプラグインを使用します。 まずはelasticsearchのPythonライブラリ、ECSフォーマッタ をインストールします。elasticsearchのバージョンには注意してください。

 pip install elasticsearch==7.8.0
 pip install ecs-logging

以下のようなrtc.confを用意してESLogger.pyをロードしてください。

 logger.enable: YES
 logger.log_level: PARANOID
 
 logger.plugins: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\logger\\eslogger\\ESLogger.py
 
 logger.logstream.elasticsearch.output0.host: 127.0.0.1
 logger.logstream.elasticsearch.output0.port: 9200
 logger.logstream.elasticsearch.output0.index: fluentbit

接続先のElasticsearchサーバーのアドレス、ポート番号、データを登録するインデックスを指定してください。

このrtc.confを指定してRTCを起動します。

 ConsoleOut.py -f rtc.conf

ログ収集ソフトウェアのインストール、起動手順

Windows

Fluentdのインストール、起動

ほとんど以下のページと手順は同じです。

Fluentdをインストールしてください。

インストール後、Td-agent Command Promptを起動してください。

次にtd-agentをインストールしたフォルダ(C:\opt\td-agent)にconf\td-agent.confというファイルを作成します。

 C:\opt\td-agent
                 |- conf
                       |-td-agent.conf

td-agent.confには以下の内容を記述します。

 <source>
   @type forward
 </source>
 
 <match test.**>
   @type stdout
 </match>

Td-agent Command Promptで以下のコマンドを入力してfluentdを実行します。

 > fluentd -c conf\td-agent.conf

Ubuntu

td-agentのインストール、起動

以下のコマンドでFluentdをインストールします。

 curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-bionic-td-agent4.sh | sh

次に設定ファイル(/etc/td-agent/td-agent.conf)を編集します。

 <source>
    @type forward
 </source>
 
 <match test.**>
    @type stdout
 </match>

以下のコマンドでtd-agentを起動します。念のためtd-agentサービスは停止します。

 sudo systemctl stop td-agent.service ※念のためサービス停止
 /usr/sbin/td-agent

td-agent-bitのインストール、起動

以下のコマンドでtd-agent-bitをインストールします。

 wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add -
 sudo echo "deb https://packages.fluentbit.io/ubuntu/bionic bionic main" >> /etc/apt/sources.list
 sudo apt-get update
 sudo apt-get install td-agent-bit

以下のコマンドでfluent-bitを起動します。

 fluent-bit -i forward -F stdout -m 'test.*' -o null

ROS2通信機能の利用

C++版

Windows

Chocolateyのインストール

以下のページの指示に従いインストールします。

Python3のインストール

以下のコマンドでインストールします。

 > choco install -y python

OpenSSLのインストール

以下からWin64OpenSSL-1_0_2r.exeを入手して、それを実行してインストールします。

以下の環境変数を設定します。

OPENSSL_CONF C:\OpenSSL-Win64\bin\openssl.cfg

環境変数PATHにC:\OpenSSL-Win64\binを追加します。

asio、eigen、tinyxml、tinyxml-usestl、log4cxxのインストール

以下のページからNuGetパッケージ(.nupkg)ファイルをダウンロードしてください。

以下のコマンドでインストールします。依存するNugetパッケージが増える場合もあるようなので、適宜変更してください。

 > choco install -y -s <'''ダウンロードしたパス'''> asio eigen tinyxml-usestl tinyxml2 log4cxx

Python用パッケージのインストール

以下のコマンドでインストールします。

 > python -m pip install -U catkin_pkg empy pyparsing pyyaml setuptools

ROS2のインストール

以下のページからros2-****-********-windows-release-amd64.zipをダウンロードします。

C:\dev\ros2等に展開して完了です。

OpenRTM-aistのビルド

CMake実行前にROS2の環境を設定するスクリプトを実行します。

 > call C:\dev\ros2\local_setup.bat

CMake実行時にFASTRTPS_ENABLEROS2_ENABLEのオプションをONにします。

 > cmake  -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc14 -G "Visual Studio 16 2019" -A x64 -DFASTRTPS_ENABLE=ON -DROS2_ENABLE=ON ..

その他の手順は通常と同じです。

適当な場所にインストールしてください。

インストールするディレクトリはCMAKE_INSTALL_PREFIXのオプションで設定します。

 > cmake .. -DCMAKE_INSTALL_PREFIX=C:/workspace/OpenRTM-aist/build_omni/install
 > cmake --build . --config Release --target install

動作確認

<'インストールしたパス'>\2.0.0\Components\C++\Examples\vc14のサンプルコンポーネントを実行します。

以下の内容のrtc.confを作成してください。

 manager.modules.load_path: {インストールしたパス}\\2.0.0\\ext\\transport
 manager.modules.preload: FastRTPSTransport.dll, ROS2Transport.dll
 manager.components.preconnect: ConsoleOut0.in?interface_type=fast-rtps&marshaling_type=ros2:std_msgs/Float32&fast-rtps.topic=chatter, ConsoleIn0.out?interface_type=fast-rtps&marshaling_type=ros2:std_msgs/Float32&fast-rtps.topic=chatter
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.module.load_path
シリアライザ用モジュール(FastRTPSTransport.dllとROS2Transport.dll)が置かれている場所
manager.modules.preload
シリアライザ用モジュールを読み込む順番で指定
manager.components.preconnect
コネクタ生成時の設定を記述します。interface_type(インターフェース型)にfast-rtpsを、marshaling_type(マーシャリング型)に対応シリアライザ名を、fast-rtps.topic(トピック)に適当な任意の名前を記述します。

ROS/ROS2用のシリアライザと対応するROS/ROS2メッセージ型の関係を以下のリンクで示します。

コネクタの生成はmanager.components.preconnectオプションにより設定します。 この例ではConsoleOut0コンポーネントのinのポート、ConsoleIn0コンポーネントのoutのポートにそれぞれコネクタを生成しています。

実行前に環境変数PATHに以下を追加する必要があります。

  • <インストールしたパス>\2.0.0\bin\vc14
  • <インストールしたパス>\2.0.0\omniORB\4.2.3_vc14\bin\x86_win32
  • C:\dev\ros2\bin
  • C:\ProgramData\chocolatey\lib\tinyxml2\lib
  • C:\ProgramData\chocolatey\lib\log4cxx\lib

ConsoleInComp.exeConsoleOutComp.exeを実行すると通信ができるようになります。

Ubuntu

ROS2のインストール

以下のコマンドでインストールします。

 $ curl http://repo.ros2.org/repos.key | sudo apt-key add -
 $ sudo sh -c 'echo "deb [arch=amd64,arm64] http://repo.ros2.org/ubuntu/main $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list'
 $ export ROS_DISTRO=crystal
 $ sudo apt update
 $ sudo apt install ros-${ROS_DISTRO}-ros-core

ROS2用にbashの設定を以下のように行います。(次回以降のbash起動時の設定と、現在実行中のbashの設定を行います。)

 echo "source /opt/ros/crystal/setup.bash" >> ~/.bashrc
 source ~/.bashrc

OpenRTM-aistのビルド

CMake実行時にFASTRTPS_ENABLEROS2_ENABLEのオプションをONにします。

 $ cmake -DCORBA=omniORB -DCMAKE_BUILD_TYPE=Release -DFASTRTPS_ENABLE=ON -DROS2_ENABLE=ON ..

その他の手順は通常と同じです。

ビルド後にインストールしてください。

 $ cmake --build . --target install

動作確認

以下のrtc.confを作成します。

 manager.modules.load_path: /usr/local/lib/openrtm-2.0/transport/
 manager.modules.preload: FastRTPSTransport.so, ROS2Transport.so
 manager.components.preconnect: ConsoleOut0.in?interface_type=fast-rtps&marshaling_type=ros2:std_msgs/Float32&fast-rtps.topic=chatter, ConsoleIn0.out?interface_type=fast-rtps&marshaling_type=ros2:std_msgs/Float32&fast-rtps.topic=chatter
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.module.load_path
シリアライザ用モジュール(FastRTPSTransport.soとROS2Transport.so)が置かれている場所
manager.modules.preload
シリアライザ用モジュールを読み込む順番で指定
manager.components.preconnect
コネクタ生成時の設定を記述します。interface_type(インターフェース型)にfast-rtpsを、marshaling_type(マーシャリング型)に対応シリアライザ名を、fast-rtps.topic(トピック)に適当な任意の名前を記述します。

OpenRTM-aistのシリアライザが対応しているメッセージ型を以下に示します。

RTCを起動して動作確認します。

それぞれ別のターミナルから起動してください。

 /usr/local/share/openrtm-2.0/components/c++/examples/ConsoleInComp

 /usr/local/share/openrtm-2.0/components/c++/examples/ConsoleOutComp

Python版

Windows

C++版と同じ手順でROS2をインストールしてください。

OpenRTM-aistのインストール

OpenRTM-aist 1.2等をインストーラーでインストールしておいてください。 OpenRTM-aist Python版のソースコードを入手してください。

以下のコマンドでOpenRTM-aist Python版をインストールしてください。

 python setup.py build
 python setup.py install

動作確認

動作前に以下のコマンドを実行してください。

  call C:\dev\ros2\setup.bat

以下のようなrtc.confを作成し、ROS2Transport.pyをロード後、インターフェース型にopenspliceを指定して起動します。

 manager.modules.load_path: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\transport\\ROS2Transport
 manager.modules.preload: ROS2Transport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32&ros2.topic=chatter, ConsoleIn0.out?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32&ros2.topic=chatter
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.module.load_path
シリアライザ用モジュール(ROS2Transport.py)が置かれている場所
manager.modules.preload
シリアライザ用モジュールを読み込む順番で指定
manager.components.preconnect
コネクタ生成時の設定を記述します。interface_type(インターフェース型)にros2を、marshaling_type(マーシャリング型)に対応シリアライザ名を、ros2.topic(トピック)に適当な任意の名前を記述します。

Ubuntu

ROS2のインストール

以下のコマンドでインストールします。

 $ curl http://repo.ros2.org/repos.key | sudo apt-key add -
 $ sudo sh -c 'echo "deb [arch=amd64,arm64] http://repo.ros2.org/ubuntu/main $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list'
 $ export ROS_DISTRO=crystal
 $ sudo apt update
 $ sudo apt install ros-${ROS_DISTRO}-desktop

ROS2の環境設定のbashを実行するようにします。

 $ echo "source /opt/ros/crystal/setup.bash" >> ~/.bashrc
 $ source ~/.bashrc

 $  sudo apt-get install python-omniorb-omg omniidl-python doxygen

OpenRTM-aistのインストール

OpenRTM-aist Python版のソースコードを入手してください。

以下のコマンドでOpenRTM-aist Python版をビルド/インストールしてください。

 $ python setup.py build
 $ python setup.py install

動作確認

ros2のsetup.bashを実行するとPYTHONPATHが上書きされるようなので以下のコマンドを実行する。

 $ export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.6/site-packages
 $ export PATH=$PATH:/usr/local/lib/python3.6/site-packages/

omniORBpyがインストールされているディレクトリにあわせて変更してください。

以下のようなrtc.confを作成し、ROS2Transport.pyをロードし、インターフェース型にros2、シリアライザにros2:std_msgs/Float32を指定して起動するように指定します。

 manager.modules.load_path: /usr/local/lib/python3.6/site-packages/OpenRTM_aist/ext/transport/ROS2Transport/
 manager.modules.preload: ROS2Transport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32&ros2.topic=chatter, ConsoleIn0.out?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32&ros2.topic=chatter
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

OpenRTM-aistのシリアライザが対応しているメッセージ型を以下に示します。

以下のコマンドでRTCを起動して動作確認してください。

 $ python /usr/local/share/openrtm-2.0/components/python/SimpleIO/ConsoleIn.py

 $ python /usr/local/share/openrtm-2.0/components/python/SimpleIO/ConsoleOut.py

起動時のオプション

C++

Fast DDS通信機能のオプションを設定してください。

Python

以下のオプションが設定できます。

オプション名 設定例 内容
ros2.args rclpy.initの引数args
ros2.node.name node_name ノード名

接続時のオプション

C++

Fast DDS通信機能のオプションを設定してください。

Python

接続時に設定可能な項目は以下の通りです。

オプション名 デフォルト値 オプション 内容
marshaling_type シリアライザの種類。ros:std_msgs/Float32などが設定できる。
ros2.topic chatter DDSトピック名
ros2.reader_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, SYSTEM_DEFAULT_QOS 送信側の堅牢性(VOLATILE_DURABILITY_QOS:変わりやすい、TRANSIENT_LOCAL_DURABILITY_QOS:一時的なローカル設定)
ros2.reader_qos.deadline.period.sec 0 受信側の最小周期
ros2.reader_qos.deadline.period.nanosec 0
ros2.reader_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS, SYSTEM_DEFAULT_LIVELINESS_QOS
ros2.reader_qos.liveliness.lease_duration.sec 0 受信側のハートビートの周期
ros2.reader_qos.liveliness.lease_duration.nanosec 0
ros2.reader_qos.reliability.kind RELIABLE_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS, SYSTEM_DEFAULT_RELIABILITY_QOS 受信側の信頼性(RELIABLE_RELIABILITY_QOS:高信頼、BEST_EFFORT_RELIABILITY_QOS:最高速度)
ros2.reader_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS, SYSTEM_DEFAULT_HISTORY_QOS 受信データの保持方法(KEEP_ALL_HISTORY_QOS:すべてのデータを保持、KEEP_LAST_HISTORY_QOSで指定したデータ数だけ保持) KEEP_LAST
ros2.reader_qos.history.depth 1 受信側の保持するデータ数
ros2.reader_qos.lifespan.duration.sec 0
ros2.reader_qos.lifespan.duration.nanosec 0
ros2.reader_qos.avoid_ros_namespace_conventions YES YES, NO
ros2.writer_qos.durability.kind TRANSIENT_DURABILITY_QOS VOLATILE_DURABILITY_QOS, TRANSIENT_LOCAL_DURABILITY_QOS, SYSTEM_DEFAULT_QOS 送信側の堅牢性(VOLATILE_DURABILITY_QOS:変わりやすい、TRANSIENT_LOCAL_DURABILITY_QOS:一時的なローカル設定)
ros2.writer_qos.deadline.period.sec 0 送信側の最小周期
ros2.writer_qos.deadline.period.nanosec 0
ros2.writer_qos.liveliness.kind AUTOMATIC_LIVELINESS_QOS AUTOMATIC_LIVELINESS_QOS, MANUAL_BY_TOPIC_LIVELINESS_QOS, SYSTEM_DEFAULT_LIVELINESS_QOS
ros2.writer_qos.liveliness.lease_duration.sec 0 送信側のハートビートの周期
ros2.writer_qos.liveliness.lease_duration.nanosec 0
ros2.writer_qos.reliability.kind RELIABLE_RELIABILITY_QOS BEST_EFFORT_RELIABILITY_QOS, RELIABLE_RELIABILITY_QOS, SYSTEM_DEFAULT_RELIABILITY_QOS 送信側の信頼性(RELIABLE_RELIABILITY_QOS:高信頼、BEST_EFFORT_RELIABILITY_QOS:最高速度)
ros2.writer_qos.history.kind KEEP_LAST_HISTORY_QOS KEEP_LAST_HISTORY_QOS, KEEP_ALL_HISTORY_QOS, SYSTEM_DEFAULT_HISTORY_QOS 送信データの保持方法(KEEP_ALL_HISTORY_QOS:すべてのデータを保持、KEEP_LAST_HISTORY_QOSで指定したデータ数だけ保持)
ros2.writer_qos.history.depth 1 送信側の保持するデータ数
ros2.writer_qos.lifespan.duration.sec 0 送信側の未送信データの保持時間
ros2.writer_qos.lifespan.duration.nanosec 0
ros2.writer_qos.avoid_ros_namespace_conventions YES YES, NO

以下に設定例を記載します。

 manager.components.preconnect: ConsoleOut0.in?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32, ConsoleIn0.out?interface_type=ros2&marshaling_type=ros2:std_msgs/Float32

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、ROS2Transportの簡単な動作確認用の設定ファイルがインストールされます。

 D:\ros2-windows\setup.bat
 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\transport\rtc.ros2.conf

 source /opt/ros/dashing/setup.sh
 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/transport/rtc.ros2.conf

ROS通信機能の利用

C++版

Windows

ROSのインストール

以下のサイトの手順に従ってRos4WinをUSBメモリにインストールしてください。

※リポジトリのURLが変わった関係でrptが正常に動作しない場合があります。修正済みでない場合はまずsrc\rpt\ros4win.pyのファイルを修正してください。

 #PKG_REPO_BASE="http://hara.jpn.com/cgi/" #修正前
 PKG_REPO_BASE="http://hara-jp.com/cgi/"  #修正後

以下のコマンドでRos4Winをインストールしてください。

 git clone https://github.com/haraisao/rpt
 cd rqt
 python src\rpt\rpt.py update
 python src\rpt\rpt.py install ros_base
 python src\rpt\rpt.py install ros_setup

OpenRTM-aistのビルド

最初に以下のコマンドでCMAKE_PREFIX_PATHROS_HOME_DRIVEの環境変数を設定します。 ここではドライブ"D:"にインストールしたUSBドライブが刺さっている前提でコマンドを示していますが、違うドライブに刺さっている場合は"D:"の部分をそのドライブ名に変更してください。

 set ROS_HOME_DRIVE=D:
 set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%ROS_HOME_DRIVE%/opt/ros/melodic/share

以降の作業の前に以下のコマンドでROSの環境を設定します。

 D:\opt\ros\melodic\ros_setup.bat

CMake実行時にROS_ENABLEのオプションをONにします。

 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc14 -DCORBA=omniORB -G "Visual Studio 16 2019" -A x64 -DROS_ENABLE=ON ..

その他の手順は通常と同じです。

ビルド後にインストールしてください。

 cmake --build . --config Release --target install

動作確認

以下のrtc.confを作成します。

 manager.modules.load_path: C:\\workspace\\openrtm\\build_omni\\devel\\bin\\Release
 manager.modules.preload: ROSTransport.dll
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleOut0, ConsoleIn0.out?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleIn0
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.modules.load_path
シリアライザーモジュール(ROSTransport.dll)を置く場所を指定します。
manager.modules.preload
ROS通信のためのシリアライザーモジュールのの指定をします。Windowsの場合にはROSTransport.dllを指定します。
manager.components.preconnect
コネクタ生成に関する設定をしています。interface_type(インターフェース型)にros、marshaling_type(マーシャリング型)に対応シリアライザの名前、ros.topic(トピック名)に適当な任意の名前を設定します。

OpenRTM-aistのシリアライザーモジュール(ROSTransport.dll)が対応しているメッセージ型は以下のようになります。

RTCを起動して動作確認します。 以下のコマンドでClinkを起動してください。

 D:\opt\start_ros.bat

以降の作業はClink上で実行します。

以下のファイルを実行します。この時上記の変更をしたrtc.confは、VC14等のOpenRTM-aistをインストール時に指定したVisual Studioのバージョンに関連したのフォルダー(デフォルトではExamplesの下のVC14)に実行するexeファイルがありますので、そこと同じディレクトリに置くようにしてください。

 ${OpenRTM_INSTALL_DIR}\2.0\Components\C++\Examples\ConsoleInComp.exe
 ${OpenRTM_INSTALL_DIR}\2.0\Components\C++\Examples\ConsoleOutComp.exe

Ubuntu

ROSのインストール

以下のコマンドでインストールしてください。

 $ export ROS_DISTRO=melodic
 $ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
 $ sudo apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-key 421C365BD9FF1F717815A3895523BAEEB01FA116
 $ sudo apt-get -y update
 $ sudo apt-get -y install ros-${ROS_DISTRO}-ros-base
 $ sudo rosdep init
 $ rosdep update

ROS用にbashの設定を以下のように行います。(次回以降のbash起動時の設定と、現在実行中のbashの設定を行います。)

 $ echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc
 $ source ~/.bashrc

OpenRTM-aistのビルド

CMake実行時にROS_ENABLEのオプションをONにします。

 $ cmake -DCORBA=omniORB -DCMAKE_BUILD_TYPE=Release -DROS_ENABLE=ON ..

その他の手順は通常と同じです。

ビルド後にインストールしてください。

 $ cmake --build . --target install

動作確認

以下のrtc.confを作成します。このファイルは下記のRTCコンポーネントを起動する時に使うカレントワーキングディレクトリにおいてください。

 manager.modules.load_path: /usr/local/lib/openrtm-2.0/transport/
 manager.modules.preload: ROSTransport.so
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleOut0, ConsoleIn0.out?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleIn0
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.modules.load_path
シリアライザーモジュール(ROSTransport.so)を置く場所を指定します。
manager.modules.preload
ROS通信のためのシリアライザーモジュールのの指定をします。Ubuntuの場合にはROSTransport.soを指定します。
manager.components.preconnect
コネクタ生成に関する設定をしています。interface_type(インターフェース型)にros、marshaling_type(マーシャリング型)に対応シリアライザの名前、ros.topic(トピック名)に適当な任意の名前を設定します。

OpenRTM-aistのシリアライザーモジュール(ROSTransport.so)が対応しているメッセージ型は以下のようになります。

ConsoleInComp、ConsoleOutCompを起動して動作確認します。

それぞれ別のターミナルから起動してください。

 $ /usr/local/share/openrtm-2.0/components/c++/examples/ConsoleInComp

 $ /usr/local/share/openrtm-2.0/components/c++/examples/ConsoleOutComp

Python版

Windows

ROSのインストール

以下のページに従ってROSをUSBメモリにインストールしてください。

OpenRTM-aistのインストール

OpenRTM-aist 1.2等をインストーラーでインストールしておいてください。 OpenRTM-aist Python版のソースコードを入手してください。

以下のコマンドでOpenRTM-aist Python版をインストールしてください。

 python setup.py build
 python setup.py install

動作確認

start_ros.batを2回実行して、ROSの環境設定をしたウインドウを2つ開いてください。

 D:\opt\start_ros.bat

片方のウインドウでroscoreを起動します。

 roscore

もう片方のウインドウでOpenRTM-aistをインストールしたディレクトリをPYTHONPATHに設定します。

 set PYTHONPATH=%PYTHONPATH%;C:\Python37\Lib\site-packages;C:\Python37\Lib\site-packages\OpenRTM_aist;C:\Python37\Lib\site-packages\OpenRTM_aist\utils;C:\Python37\Lib\site-packages\OpenRTM_aist\RTM_IDL

以下のrtc.confを作成します。(rtc.confはRTCのexeファイルが実行される時のディレクトリに作成してください。サンプルバッチファイルを使う場合は、バッチファイルから起動されるexeファイルが置かれているディレクトリになります。)

 manager.modules.load_path: C:\\Python37\\Lib\\site-packages\\OpenRTM_aist\\ext\\transport\\ROSTransport
 manager.modules.preload: ROSTransport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleOut0, ConsoleIn0.out?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleIn0
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.modules.load_path
シリアライザーモジュール(ROSTransport.py)を置く場所を指定します。
manager.modules.preload
ROS通信のためのシリアライザーモジュールのの指定をします。Pythonの場合にはROSTransport.pyを指定します。
manager.components.preconnect
コネクタ生成に関する設定をしています。interface_type(インターフェース型)にros、marshaling_type(マーシャリング型)に対応シリアライザの名前、ros.topic(トピック名)に適当な任意の名前を設定します。

OpenRTM-aistのシリアライザーモジュール(ROSTransport.py)が対応しているメッセージ型は以下のようになります。

上記のrtc.confを用いてRTCを起動して動作確認してください。

Ubuntu

ROSのインストール

C++版と同じ手順でROSをインストールしてください。

OpenRTM-aistのインストール

以下のパッケージをインストールしてください。

 $ sudo apt-get install python-omniorb-omg omniidl-python doxygen

以下のコマンドでOpenRTM-aist Python版をインストールします。

 $ git clone https://github.com/OpenRTM/OpenRTM-aist-Python
 $ cd OpenRTM-aist-Python
 $ python setup.py build
 $ sudo python setup.py install

動作確認

以下のrtc.confを作成します。(rtc.confはRTCを実行する時のカレントワーキングディレクトリに作成してください。)

 manager.modules.load_path: /usr/local/lib/python2.7/dist-packages/OpenRTM_aist/ext/transport/ROSTransport/
 manager.modules.preload: ROSTransport.py
 manager.components.preconnect: ConsoleOut0.in?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleOut0, ConsoleIn0.out?interface_type=ros&marshaling_type=ros:std_msgs/Float32&ros.topic=chatter&ros.node.name=ConsoleIn0
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

manager.modules.load_path
シリアライザーモジュール(ROSTransport.py)を置く場所を指定します。
manager.modules.preload
ROS通信のためのシリアライザーモジュールのの指定をします。Pythonの場合にはROSTransport.pyを指定します。
manager.components.preconnect
コネクタ生成に関する設定をしています。interface_type(インターフェース型)にros、marshaling_type(マーシャリング型)に対応シリアライザの名前、ros.topic(トピック名)に適当な任意の名前を設定します。

OpenRTM-aistのシリアライザーモジュール(ROSTransport.py)が対応しているメッセージ型は以下のようになります。

以下のコマンドでRTCを起動して動作確認してください。

 $ python /usr/local/share/openrtm-2.0/components/python/SimpleIO/ConsoleIn.py

 $ python /usr/local/share/openrtm-2.0/components/python/SimpleIO/ConsoleOut.py

接続時のオプション

C++

データポート接続時のコネクタプロファイルに設定できるオプションは以下の通りです。

オプション名 デフォルト値 オプション 内容
marshaling_type シリアライザの種類。ros:std_msgs/Float32などが設定できる。
ros.topic chatter トピック名
ros.roscore.host localhost ROS Masterのホスト名
ros.roscore.port 11311 ROS Masterのポート番号
ros.node.name ROSノードの名前
ros.node.anonymous NO YES,NO
ros.so_keepalive YES YES,NO
ros.tcp_nodelay YES YES,NO YES:ROSノード名をUUIDで設定、NO:ROSノードをrtcompに設定
ros.tcp_keepcnt 9
ros.tcp_keepidle 60
ros.tcp_keepintvl 10

Python

データポート接続時のコネクタプロファイルに設定できるオプションは以下の通りです。

オプション名 デフォルト値 オプション 内容
marshaling_type シリアライザの種類。ros:std_msgs/Float32などが設定できる。
ros.topic chatter トピック名
ros.roscore.host localhost ROS Masterのホスト名
ros.roscore.port 11311 ROS Masterのポート番号
ros.node.name ROSノードの名前
ros.node.anonymous NO YES,NO
ros.so_reuseaddr YES YES,NO
ros.so_keepalive YES YES,NO
ros.tcp_nodelay YES YES,NO YES:ROSノード名をUUIDで設定、NO:ROSノードをrtcompに設定
ros.tcp_keepcnt 9
ros.tcp_keepidle 60
ros.tcp_keepintvl 10
ros.sock.timeout 60

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、ROSTransportの簡単な動作確認用の設定ファイルがインストールされます。

 D:\opt\ros\melodic\ros_setup.bat
 roscore

 D:\opt\ros\melodic\ros_setup.bat
 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\transport\rtc.ros.conf

 source /opt/ros/melodic/setup.bash
 roscore

 source /opt/ros/melodic/setup.bash
 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/transport/rtc.ros.conf

シリアライザ名とROS/ROS2メッセージ型

ROS,ROS2通信機能を使用する場合、以下のROS/ROS2メッセージ型に対応のシリアライザをOpenRTM-aistは備えています。以下のメッセージ型以外が必要な場合は、そのメッセージ型に変換するシリアライザを独自に実装してください。

シリアライザ名 RTMデータ型 ROS,ROS2メッセージ型
ros:std_msgs/Float32,
ros2:std_msgs/Float32
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/Float32
ros:std_msgs/Float64,
ros2:std_msgs/Float64
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/Float64
ros:std_msgs/Int8,
ros2:std_msgs/Int8
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/Int8
ros:std_msgs/Int16,
ros2:std_msgs/Int16
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/Int16
ros:std_msgs/Int32,
ros2:std_msgs/Int32
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/UInt8
ros:std_msgs/Int64,
ros2:std_msgs/Int64
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/UInt16
ros:std_msgs/UInt32,
ros2:std_msgs/UInt32
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/UInt32
ros:std_msgs/UInt64,
ros2:std_msgs/UInt64
TimedState,TimedShort,
TimedLong,TimedUShort,
TimedULong,TimedFloat,
TimedDouble
std_msgs/UInt64
ros:std_msgs/Float32MultiArray,
ros2:std_msgs/Float32MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Float32MultiArray
ros:std_msgs/Float32MultiArray,
ros2:std_msgs/Float32MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Float32MultiArray
ros:std_msgs/Float64MultiArray,
ros2:std_msgs/Float64MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq, TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Float64MultiArray
ros:std_msgs/Int8MultiArray,
ros2:std_msgs/Int8MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Int8MultiArray
ros:std_msgs/Int16MultiArray,
ros2:std_msgs/nt16MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Int16MultiArray
ros:std_msgs/Int32MultiArray,
ros2:std_msgs/Int32MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Int32MultiArray
ros:std_msgs/Int64MultiArray,
ros2:std_msgs/Int64MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/Int64MultiArray
ros:std_msgs/UInt8MultiArray,
ros2:std_msgs/UInt8MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/UInt8MultiArray
ros:std_msgs/UInt16MultiArray,
ros2:std_msgs/UInt16MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/UInt16MultiArray
ros:std_msgs/UInt32MultiArray,
ros2:std_msgs/UInt32MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/UInt32MultiArray
ros:std_msgs/UInt64MultiArray,
ros2:std_msgs/UInt64MultiArray
TimedShortSeq,TimedLongSeq,
TimedUShortSeq,TimedULongSeq,
TimedFloatSeq,TimedDoubleSeq
std_msgs/UInt64MultiArray
ros:std_msgs/String,
ros2:std_msgs/String
TimedString std_msgs/String
ros:geometry_msgs/PointStamped,
ros2:geometry_msgs/PointStamped
TimedPoint3D geometry_msgs/PointStamped
ros:geometry_msgs/QuaternionStamped,
ros2:geometry_msgs/QuaternionStamped
TimedQuaternion geometry_msgs/QuaternionStamped
ros:geometry_msgs/Vector3Stamped,
ros2:geometry_msgs/Vector3Stamped
TimedVector3D geometry_msgs/Vector3Stamped
ros:sensor_msgs/Image,
ros2:sensor_msgs/Image
CameraImage sensor_msgs/Image

RTC(EC)の状態を取得する

エラーを取得する方法として2つの方法があります。 rtctree (rtshell のもととなっているライブラリ)ですと簡単に実現できますが、 まずは原理的なところから説明させていただきます。

1) ECに対してポーリングをする あるRTCにアタッチされている実行コンテキスト(EC)に対して get_component_state() で 現在の状態を問い合わせる。 この方法はポーリングですので多用するとシステムの速度低下を招きます。

疑似コードで説明いたします。

rtc = <何らかの方法でRTCのオブジェクトリファレンスを取得> ec_list = rtc.get_owned_contexts(); switch (ec_list[0].get_component_state(rtc)) {

  case CREATED_STATE:
    printf("Created state.");
    break;
  case INACTIVE_STATE:
    printf("Inactive state.");
    break;
  case ACTIVE_STATE:
    printf("Active state.");
    break;
  case ERROR_STATE:
    printf("Error state.");
   break;
  default:
     printf("Unknown state");
     break;
}

まずRTCからECを取得して、そのECに対してRTCを引数にして状態を取得しています。 このような呼び出し方をしているのは、以下の様な考え方からです。

RTCのステータスとして Inactive-Active-Error とされているのは、実際にはRTC の状態 ではなく、ある実行コンテキスト(EC)があるRTCと結びついたときの状態です。 (すなわち、状態はEC側にある、という考え方です。) http://www.omg.org/spec/RTC/ のFigure5.6 がそれに当たります。

通常は自身のECしかないため、ECの状態とRTCの状態を同一視しても問題ないのですが、 実際には一つのRTCは複数のECにアタッチされる可能性があることをご理解ください。

2) ComponentObserver を利用する もう一つはComponentObserver (1.1.0以降で導入) を利用する方法です。 ComponentObserverは以下の様なインターフェースを持っており、問い合わせをしたい側で サーバントを実装し、このオブジェクトをRTCにアタッチすることで状態が変わったとき などにコールバックさせます。

http://svn.openrtm.org/OpenRTM-aist/tags/RELEASE_1_1_0/OpenRTM-aist/src/ext/sdo/observer/ComponentObserver.idl

@interface ComponentObserver の項をご覧ください。

obs_svt = new ComponentOberver_impl(); // サーバント OpenRTM::ComponentObserver obs_ref = obs_svt._this(); // オブジェクト参照 SDO::ServiceProfile profile; profile.id = UUID(); profile.interface_type = CORBA_Util::toRepositoryId<OpenRTM::ComponentObserver>(); // rtm/Typename.h CORBA_SeqUtil.push_back(profile.properties, NVUtil::newNV("observed_status", "RTC_STATUS")); CORBA_SeqUtil.push_back(profile.properties, NVUtil::newNV("heartbeat.enable", "YES")); CORBA_SeqUtil.push_back(profile.properties, NVUtil::newNV("heartbeat.interval", "1.0")); profile.service = obs_ref;

rtc = <何らかの方法でRTCのオブジェクトリファレンスを取得> SDO::Configuration conf = rtc.get_configuration(); // SDO::get_configuration() conf.add_service_profile(profile);

状態がACTIVEに変わったら、上記 ovs_svt の ComponentOberver_impl::update_status("RTC_STATUS", "ACTIVE:0"); 状態がINACTIVEに変わったら、 ComponentOberver_impl::update_status("RTC_STATUS", "INACTIVE:0"); 状態がERRORに変わったら、 ComponentOberver_impl::update_status("RTC_STATUS", "ERROR:0"); が呼び出される。

ちなみに、rtshellのもととなっているrtctreeでは、たとえば RTCTree のコンストラクタに dynamic = True をセットするとツリーオブジェクトがRTCの状態を取得する際に ComponentObserverを利用して状態を取得するようになります。

https://github.com/gbiggs/rtctree/blob/master/rtctree/tree.py

また TreeNode::add_callback() を利用すると、イベントをフックできるようです。

https://github.com/gbiggs/rtctree/blob/master/rtctree/node.py

このファイルの一番下にイベント名が定義されています。 https://github.com/gbiggs/rtctree/blob/master/rtctree/component.py

独自実行コンテキストの作成手順

RTC操作関数(CORBA_RTCUtil)利用マニュアル

このページではOpenRTM-aistのRTC操作関数群CORBA_RTCUtil機能の利用方法に説明します。

今回使用したソースコードは以下から入手できます。

事前準備

C++

C++の場合はOpenRTM-aistとリンクしたプログラムをビルドする環境が必要です。

以下のCMakeLists.txtを作成してください。

 cmake_minimum_required(VERSION 3.1)
 
 set(target CORBA_RTCUtil_test)
 project(${target} CXX)
 
 find_package(OpenRTM REQUIRED)
 
 add_definitions(${OPENRTM_CFLAGS})
 link_directories(${OPENRTM_LIBRARY_DIRS})
 
 add_executable(${target} ${target}.cpp)
 target_link_libraries(${target} ${OPENRTM_LIBRARIES})
 target_include_directories(${target} SYSTEM PRIVATE ${OPENRTM_INCLUDE_DIRS})

また、CORBA_RTCUtil_test.cppのソースファイルを作成してCMakeを実行します。 ソースコードからビルドしたOpenRTM-aistを使う場合は、environment-setup.omniorb.vc**.batを実行します。

 %OPENRTM_INSTALL_DIR%\2.0.0\ext\environment-setup.omniorb.vc16.bat
 mkdir build
 cd build
 cmake ..

CORBA_RTCUtil_test.cppには以下の内容を記述しておきます。

 #include <rtm/Manager.h>
 #include <rtm/NamingManager.h>
 #include <rtm/CORBA_RTCUtil.h>
 #include <iostream>
 
 
 int main (int argc, char** argv)
 {
  RTC::Manager* manager;
  manager = RTC::Manager::init(argc, argv);
 
  manager->activateManager();
  manager->runManager(true);
 
  RTC::RTObject_var consolein = RTC::RTObject::_nil();
  RTC::RTObject_var consoleout = RTC::RTObject::_nil();
 
  RTC::NamingManager* nm = RTC::Manager::instance().getNaming();
  RTC::RTCList consoleinlist = nm->string_to_component("rtcname://localhost:2809/*/ConsoleIn0");
 
  if (consoleinlist.length() > 0)
  {
    consolein = consoleinlist[0];
  }
  else
  {
    std::cout << "Could not found ConsoleIn0" << std::endl;
    return 1;
  }
 
  RTC::RTCList consoleoutlist = nm->string_to_component("rtcname://localhost:2809/*/ConsoleOut0");
  
  if (consoleoutlist.length() > 0)
  {
    consoleout = consoleoutlist[0];
  }
  else
  {
    std::cout << "Could not found ConsoleOut0" << std::endl;
    return 1;
  }
  
  RTC::RTObject_var configsample = RTC::RTObject::_nil();
  RTC::RTCList configsamplelist = nm->string_to_component("rtcname://localhost:2809/*/ConfigSample0");
 
  if (configsamplelist.length() > 0)
  {
    configsample = configsamplelist[0];
  }
  else
  {
    std::cout << "Could not found ConfigSample0" << std::endl;
    return 1;
  }
  
  RTC::RTObject_var myserviceprovider = RTC::RTObject::_nil();
  RTC::RTCList myserviceproviderlist = nm->string_to_component("rtcname://localhost:2809/*/MyServiceProvider0");
 
  if (myserviceproviderlist.length() > 0)
  {
    myserviceprovider = myserviceproviderlist[0];
  }
  else
  {
    std::cout << "Could not found MyServiceProvider0" << std::endl;
    return 1;
  }
  
  RTC::RTObject_var myserviceconsumer = RTC::RTObject::_nil();
  RTC::RTCList myserviceconsumerlist = nm->string_to_component("rtcname://localhost:2809/*/MyServiceConsumer0");
 
  if (myserviceconsumerlist.length() > 0)
  {
    myserviceconsumer = myserviceconsumerlist[0];
  }
  else
  {
    std::cout << "Could not found MyServiceConsumer0" << std::endl;
    return 1;
  }
 
  //以降の処理はここに記述する
 
  manager->terminate();
  manager->join();
 
  return 0;
 }

Python

Pythonの場合は以下のCORBA_RTCUtil_test.pyを用意してください。

 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 # -*- Python -*-
 
 import sys
 
 import OpenRTM_aist
 import OpenRTM_aist.CORBA_RTCUtil
 from omniORB import CORBA
 
 def main():
    mgr = OpenRTM_aist.Manager.init(sys.argv)
    mgr.activateManager()
    mgr.runManager(True)
 
 
    nm = OpenRTM_aist.Manager.instance().getNaming()
    consoleinlist = nm.string_to_component(
        "rtcname://localhost:2809/*/ConsoleIn0")
 
    if consoleinlist:
        consolein = consoleinlist[0]
    else:
        print("Could not found ConsoleIn0")
        sys.exit(1)
 
    consoleoutlist = nm.string_to_component(
        "rtcname://localhost:2809/*/ConsoleOut0")
    if consoleoutlist:
        consoleout = consoleoutlist[0]
    else:
        print("Could not found ConsoleOut0")
        sys.exit(1)
    
    configsamplelist = nm.string_to_component(
        "rtcname://localhost:2809/*/ConfigSample0")
    if consoleoutlist:
        configsample = consoleoutlist[0]
    else:
        print("Could not found ConfigSample0")
        sys.exit(1)
 
    myserviceproviderlist = nm.string_to_component(
        "rtcname://localhost:2809/*/MyServiceProvider0")
    if myserviceproviderlist:
        myserviceprovider = myserviceproviderlist[0]
    else:
        print("Could not found MyServiceProvider0")
        sys.exit(1)
 
    myserviceconsumerlist = nm.string_to_component(
        "rtcname://localhost:2809/*/ConsoleOut0")
    if myserviceconsumerlist:
        myserviceconsumer = myserviceconsumerlist[0]
    else:
        print("Could not found ConsoleOut0")
        sys.exit(1)
 
    #以降の処理はここに記述する
 
    mgr.shutdown()
 
 
 if __name__ == "__main__":
    main()

rtc.confの作成

以下の内容のrtc.confを作成してください。

 manager.shutdown_auto: NO

サンプルコンポーネントの起動

ConsoleIn、ConsoleOut、ConfiguSample、MyServiceProvider、MyServiceConsumerのサンプルコンポーネントを起動しておきます。

CORBA_RTCUtilの利用

ポートの操作

ポートのオブジェクトリファレンス取得

データポートの接続のために、ポートのオブジェクトリファレンスを取得するget_port_by_name関数を使用します。

関数名 get_port_by_name
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
name std::string& RTC名.ポート名
戻り値
型名 意味
RTC::PortService_ptr ポートのオブジェクトリファレンス

  RTC::PortService_var port_in_var = CORBA_RTCUtil::get_port_by_name(consoleout.in(), "ConsoleOut0.in");
 
  if (CORBA::is_nil(port_in_var))
  {
    std::cout << "Could not found ConsoleOut0.in" << std::endl;
    return 1;
  }
 
  RTC::PortService_var port_out_var = CORBA_RTCUtil::get_port_by_name(consolein.in(), "ConsoleIn0.out");
 
  if (CORBA::is_nil(port_out_var))
  {
    std::cout << "Could not found ConsoleIn0.out" << std::endl;
    return 1;
  }

    port_in_var = OpenRTM_aist.CORBA_RTCUtil.get_port_by_name(
        consoleout, "ConsoleOut0.in")
    if CORBA.is_nil(port_in_var):
        print("Could not found ConsoleOut0.in")
        sys.exit(1)
 
    port_out_var = OpenRTM_aist.CORBA_RTCUtil.get_port_by_name(
        consolein, "ConsoleIn0.out")
    if CORBA.is_nil(port_out_var):
        print("Could not found ConsoleOut0.in")
        sys.exit(1)

またget_port_by_url関数を使用すると、rtcname形式、rtcloc形式の文字列からオブジェクトリファレンスを取得できます。

関数名 get_port_by_url
引数
引数名 型名 意味
port_name std::string& ポートのURI
戻り値
型名 意味
RTC::PortService_ptr ポートのオブジェクトリファレンス

  RTC::PortService_var port_in_var = CORBA_RTCUtil::get_port_by_url("rtcname://localhost:2809/*/ConsoleOut0.in");
 
  if (CORBA::is_nil(port_in_var))
  {
    std::cout << "Could not found ConsoleOut0.in" << std::endl;
    return 1;
  }
 
  RTC::PortService_var port_out_var = CORBA_RTCUtil::get_port_by_url("rtcname://localhost:2809/*/ConsoleIn0.out");
 
  if (CORBA::is_nil(port_out_var))
  {
    std::cout << "Could not found ConsoleIn0.out" << std::endl;
    return 1;
  }

    port_in_var = OpenRTM_aist.CORBA_RTCUtil.get_port_by_url(
        "rtcname://localhost:2809/*/ConsoleOut0.in")
    if CORBA.is_nil(port_in_var):
        print("Could not found ConsoleOut0.in")
        sys.exit(1)
 
    port_out_var = OpenRTM_aist.CORBA_RTCUtil.get_port_by_url(
        "rtcname://localhost:2809/*/ConsoleIn0.out")
    if CORBA.is_nil(port_out_var):
        print("Could not found ConsoleOut0.in")
        sys.exit(1)

コネクタ生成

取得したデータポートをconnect関数で接続します。

関数名 connect
引数
引数名 型名 意味
name std::string& コネクタの名前
prop coil::Properties& コネクタの設定情報
port0 RTC::PortService_ptr 接続するポート1
port1 RTC::PortService_ptr 接続するポート2
戻り値
型名 意味
RTC::ReturnCode_t

  coil::Properties prop;
  prop["dataport.dataflow_type"] = "push";
  prop["dataport.interface_type"] = "corba_cdr";
  prop["dataport.subscription_type"] = "new";
  CORBA_RTCUtil::connect("test_connector", prop, port_in_var.in(), port_out_var.in());

    prop = OpenRTM_aist.Properties()
    prop.setProperty("dataport.dataflow_type", "push")
    prop.setProperty("dataport.interface_type", "corba_cdr")
    prop.setProperty("dataport.subscription_type", "new")
    OpenRTM_aist.CORBA_RTCUtil.connect(
        "test_connector", prop, port_in_var, port_out_var)

コネクタ削除

関数名 disconnect_connector_name
引数
引数名 型名 意味
port_ref RTC::PortService_ptr 接続中のポート
conn_name std::string& コネクタの名前
戻り値
型名 意味
RTC::ReturnCode_t

コネクタ名を指定してコネクタを削除するためにはdisconnect_connector_name関数を使用します。

  CORBA_RTCUtil::disconnect_connector_name(port_in_var.in(), "test_connector");

    OpenRTM_aist.CORBA_RTCUtil.disconnect_by_portref_connector_name(
        port_in_var, "test_connector")

コネクタのURIからオブジェクトリファレンスを取得してコネクタを削除する場合はdisconnect_connector_name関数を使用します。

関数名 disconnect_connector_name
引数
引数名 型名 意味
port_name std::string& ポートのURI
conn_name std::string& コネクタの名前
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::disconnect_connector_name("rtcname://localhost:2809/*/ConsoleOut0.in", "test_connector");

    OpenRTM_aist.CORBA_RTCUtil.disconnect_by_portname_connector_name(
        "rtcname://localhost:2809/*/ConsoleOut0.in", "test_connector")

複数のポートを一括で接続

複数のポートを一度に接続するためにはconnect_multi関数を使用します。

関数名 connect_multi
引数
引数名 型名 意味
name std::string& コネクタの名前
prop coil::Properties& コネクタの設定情報
port0 RTC::PortService_ptr 接続するポート1
target_ports RTC::PortServiceList& ポート1と接続するポートのリスト
戻り値
型名 意味
RTC::ReturnCode_t

  RTC::PortServiceList target_ports;
  target_ports.length(1);
  target_ports[0] = RTC::PortService::_duplicate(port_out_var.in());
  CORBA_RTCUtil::connect_multi("test_connector", prop, port_in_var.in(), target_ports);

    OpenRTM_aist.CORBA_RTCUtil.connect_multi(
        "test_connector", prop, port_in_var, [port_out_var])

すべてのコネクタを削除

対象ポートのすべてのコネクタを削除するためにはdisconnect_all関数を使います。

関数名 disconnect_all
引数
引数名 型名 意味
port_ref RTC::PortService_ptr 接続中のポート
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::disconnect_all(port_in_var.in());

    OpenRTM_aist.CORBA_RTCUtil.disconnect_all_by_ref(port_in_var)

関数名 disconnect_all
引数
引数名 型名 意味
port_name std::string& ポートのURI
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::disconnect_all("rtcname://localhost:2809/*/ConsoleIn0.out");

    OpenRTM_aist.CORBA_RTCUtil.disconnect_all_by_name(
        "rtcname://localhost:2809/*/ConsoleIn0.out")

RTCの状態操作

アクティブ化

RTCをアクティブ化するためにはactivate関数を使用します。

関数名 activate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
戻り値
型名 意味
RTC::ReturnCode_t

RTCは状態を実行コンテキストごとに持っているため、デフォルトの実行コンテキスト(ID:0)以外で状態を変更する場合はec_idを指定します。

  CORBA_RTCUtil::activate(consolein.in(), 0);
  CORBA_RTCUtil::activate(consoleout.in(), 0);

    OpenRTM_aist.CORBA_RTCUtil.activate(consoleout, 0)
    OpenRTM_aist.CORBA_RTCUtil.activate(consolein, 0)

非アクティブ化

RTCを非アクティブ化するためにはdeactivate関数を使用します。

関数名 deactivate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::deactivate(consolein.in(), 0);
  CORBA_RTCUtil::deactivate(consoleout.in(), 0);

    OpenRTM_aist.CORBA_RTCUtil.deactivate(consoleout, 0)
    OpenRTM_aist.CORBA_RTCUtil.deactivate(consolein, 0)

リセット

RTCをリセットするためにはreset関数を使用します。

関数名 reset
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::reset(consolein.in(), 0);
  CORBA_RTCUtil::reset(consoleout.in(), 0);

    OpenRTM_aist.CORBA_RTCUtil.reset(consoleout, 0)
    OpenRTM_aist.CORBA_RTCUtil.reset(consolein, 0)

RTCの状態取得

RTCの現在の状態を取得するためにはget_state関数を使用します。

関数名 get_state
引数
引数名 型名 意味
state RTC::LifeCycleState 状態
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
戻り値
型名 意味
bool true:状態取得成功、false:状態取得失敗

  RTC::LifeCycleState state;
  CORBA_RTCUtil::get_state(state, consoleout.in(), 0);
  std::cout << state << std::endl;

    ret, state = OpenRTM_aist.CORBA_RTCUtil.get_state(consoleout, 0)
    print(state)

また、is_in_inactive関数、is_in_active関数、is_in_error関数で現在の状態が非アクティブ状態、アクティブ状態、エラー状態かを判定できます。

if (CORBA_RTCUtil::is_in_inactive(consoleout.in()))

  {
    std::cout << "Inactive State" << std::endl;
  }
  else if (CORBA_RTCUtil::is_in_active(consoleout.in()))
  {
    std::cout << "Active State" << std::endl;
  }
  else if (CORBA_RTCUtil::is_in_error(consoleout.in()))
  {
    std::cout << "Error State" << std::endl;
  }

    if OpenRTM_aist.CORBA_RTCUtil.is_in_inactive(consoleout):
        print("Inactive State")
    elif OpenRTM_aist.CORBA_RTCUtil.is_in_active(consoleout):
        print("Active State")
    elif OpenRTM_aist.CORBA_RTCUtil.is_in_error(consoleout):
        print("Error State")

実行コンテキストの操作

実行周期の操作

実行コンテキストの実行周期を変更するには、set_default_rate関数を使用します。

関数名 set_default_rate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
rate CORBA::Double 実行周期
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::set_default_rate(consoleout.in(), 20.0);

    OpenRTM_aist.CORBA_RTCUtil.set_default_rate(consoleout, 20.0)

set_default_rate関数はデフォルトの実行コンテキストの実行周期を取得しますが、指定IDの実行コンテキストから実行周期を取得するためにはset_current_rate関数を使用します。

関数名 set_current_rate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
rate CORBA::Double 実行周期
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::set_current_rate(consoleout.in(), 0, 50.0);

    OpenRTM_aist.CORBA_RTCUtil.set_current_rate(consoleout, 0, 50.0)

現在の実行周期を取得するためには、get_default_rate関数を使用します。

関数名 get_default_rate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
戻り値
型名 意味
CORBA::Double 実行周期

  std::cout << CORBA_RTCUtil::get_default_rate(consoleout.in()) << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_default_rate(consoleout))

指定IDの実行コンテキストから実行周期を取得するためにはget_current_rate関数を使用します。

関数名 get_current_rate
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
ec_id RTC::UniqueId 実行コンテキストのID
戻り値
型名 意味
CORBA::Double 実行周期

  std::cout << CORBA_RTCUtil::get_current_rate(consoleout.in(), 0) << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_current_rate(consoleout, 0))

実行コンテキストのアタッチ、デタッチ

通常はRTCが起動時に生成する実行コンテキストが関連付け(アタッチ)されていますが、、外部の実行コンテキストをRTCにアタッチすると、アタッチした実行コンテキストでRTCを駆動できるようになります。

実行コンテキストを指定のRTCにアタッチするためにはadd_rtc_to_default_ec関数を使用します。

関数名 add_rtc_to_default_ec
引数
引数名 型名 意味
localcomp RTC::RTObject_ptr アタッチする実行コンテキストをデフォルト実行コンテキストとして持つRTC
othercomp RTC::RTObject_ptr アタッチするRTC
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::add_rtc_to_default_ec(consoleout.in(), consolein.in());

    OpenRTM_aist.CORBA_RTCUtil.add_rtc_to_default_ec(consoleout, consolein)

アタッチした実行コンテキストの関連付け解除(デタッチ)するためにはremove_rtc_to_default_ec関数を使用します。

関数名 remove_rtc_to_default_ec
引数
引数名 型名 意味
localcomp RTC::RTObject_ptr デタッチする実行コンテキストをデフォルト実行コンテキストとして持つRTC
othercomp RTC::RTObject_ptr デタッチするRTC
戻り値
型名 意味
RTC::ReturnCode_t

  CORBA_RTCUtil::remove_rtc_to_default_ec(consoleout.in(), consolein.in());

    OpenRTM_aist.CORBA_RTCUtil.remove_rtc_to_default_ec(consoleout, consolein)

アタッチした外部RTCの一覧を取得するためにはget_participants_rtc関数を使用します。

関数名 get_participants_rtc
引数
引数名 型名 意味
rtc RTC::RTObject_ptr 対象の実行コンテキストをデフォルト実行コンテキストとして持つRTC
戻り値
型名 意味
RTC::RTCList

  RTC::RTCList rtclist = CORBA_RTCUtil::get_participants_rtc(consoleout.in());
  for(CORBA::ULong i=0;i < rtclist.length();i++)
  {
    
    std::cout << i << "\t" << CORBA_RTCUtil::get_component_profile(rtclist[i].in()) << std::endl;
  }

    i = 0
    for rtc in OpenRTM_aist.CORBA_RTCUtil.get_participants_rtc(consoleout):
        print(i, OpenRTM_aist.CORBA_RTCUtil.get_component_profile(rtc))
        i += 1

コンフィギュレーションパラメータの操作

コンフィギュレーションパラメータの設定をするためにはset_active_configuration関数を使用します。 この関数では現在アクティブなコンフィギュレーションセットのパラメータが設定されます。

関数名 set_active_configuration
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
value_name std::string& パラメータ名
value std::string& 設定値
戻り値
型名 意味
bool true:設定成功、false:設定失敗

  CORBA_RTCUtil::set_active_configuration(configsample.in(), "int_param1", "100");

    OpenRTM_aist.CORBA_RTCUtil.set_active_configuration(
        configsample, "int_param1", "100")

コンフィギュレーションセットを指定してパラメータを設定する場合はset_configuration関数を使用します。 この関数を実行すると、アクティブなコンフィギュレーションセットが変更されます。

関数名 set_configuration
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
confset_name std::string& コンフィギュレーションセット名
value_name std::string& パラメータ名
value std::string& 設定値
戻り値
型名 意味
bool true:設定成功、false:設定失敗

  CORBA_RTCUtil::set_configuration(configsample.in(), "mode0", "str_param1", "test");

    OpenRTM_aist.CORBA_RTCUtil.set_configuration(
        configsample, "mode0", "str_param1", "test")

現在アクティブなコンフィギュレーションセットの名前を取得するにはget_active_configuration_name関数を使用します。

関数名 get_active_configuration_name
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
戻り値
型名 意味
std::string コンフィギュレーションセット名

  std::cout << CORBA_RTCUtil::get_active_configuration_name(configsample.in()) << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_active_configuration_name(configsample))

アクティブなコンフィギュレーションセットのパラメータ一覧を取得するにはget_active_configuration関数を使用します。

関数名 get_active_configuration
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
戻り値
型名 意味
coil::Properties パラメータ一覧

  std::cout << CORBA_RTCUtil::get_active_configuration(configsample.in()) << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_active_configuration(configsample))

コンフィギュレーションセットを指定してパラメータ一覧を取得するにはget_configuration関数を使用します。

関数名 get_configuration
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
conf_name std::string& コンフィギュレーションセット名
戻り値
型名 意味
coil::Properties パラメータ一覧

  std::cout << CORBA_RTCUtil::get_configuration(configsample.in(), "mode1") << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_configuration(configsample, "mode1"))

指定のパラメータのみを取得する場合はget_parameter_by_key関数を使用します。

関数名 get_parameter_by_key
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
conf_name std::string& コンフィギュレーションセット名
value_name std::string& パラメータ名
戻り値
型名 意味
std::string パラメータの値

  std::cout << CORBA_RTCUtil::get_parameter_by_key(configsample.in(), "mode1", "int_param1") << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_parameter_by_key(
        configsample, "mode1", "int_param1"))

RTC、ポートの情報取得

RTCの情報取得

コンポーネントプロファイルを取得するにはget_component_profile関数を使用します。

関数名 get_component_profile
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
戻り値
型名 意味
coil::Properties コンポーネントプロファイルの情報

  std::cout << CORBA_RTCUtil::get_component_profile(consolein.in()) << std::endl;

    print(OpenRTM_aist.CORBA_RTCUtil.get_component_profile(consolein))

ポート名取得

指定のRTCが保持しているポートの名前一覧を取得するにはget_port_names関数を使用します。

関数名 get_port_names
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
戻り値
型名 意味
coil::vstring ポート名一覧

  coil::vstring portlist = CORBA_RTCUtil::get_port_names(consolein.in());
  for (auto& port : portlist)
  {
    std::cout << port << std::endl;
  }

    for port in OpenRTM_aist.CORBA_RTCUtil.get_port_names(consolein):
        print(port)

InPortの名前一覧を取得するにはget_inport_names関数、OutPortの名前一覧を取得するにはget_outport_names関数、サービスポートの名前一覧を取得するにはget_svcport_names関数を使用します。

  coil::vstring inportlist = CORBA_RTCUtil::get_inport_names(consoleout.in());
  for (auto& port : inportlist)
  {
    std::cout << port << std::endl;
  }

  coil::vstring outportlist = CORBA_RTCUtil::get_outport_names(consolein.in());
  for (auto& port : outportlist)
  {
    std::cout << port << std::endl;
  }
  
  coil::vstring svcportlist = CORBA_RTCUtil::get_svcport_names(myserviceprovider.in());
  for (auto& port : svcportlist)
  {
    std::cout << port << std::endl;
  }

    for port in OpenRTM_aist.CORBA_RTCUtil.get_inport_names(consoleout):
        print(port)
    for port in OpenRTM_aist.CORBA_RTCUtil.get_outport_names(consolein):
        print(port)
    for port in OpenRTM_aist.CORBA_RTCUtil.get_svcport_names(myserviceprovider):
        print(port)

コネクタの名前一覧取得

指定ポートのコネクタの名前一覧を取得するにはget_connector_names関数を使用します。

関数名 get_connector_names
引数
引数名 型名 意味
port RTC::PortService_ptr ポートのオブジェクトリファレンス
戻り値
型名 意味
coil::vstring コネクタ名一覧

  coil::vstring inconlist = CORBA_RTCUtil::get_connector_names(port_in_var.in());
  for (auto& connector : inconlist)
  {
    std::cout << connector << std::endl;
  }

    for connector in OpenRTM_aist.CORBA_RTCUtil.get_connector_names_by_portref(port_in_var):
        print(connector)

ポート名を指定してコネクタの名前一覧を取得することもできます。

関数名 get_connector_names
引数
引数名 型名 意味
rtc RTC::RTObject_ptr RTCのオブジェクトリファレンス
port_name std::string& ポート名
戻り値
型名 意味
coil::vstring コネクタ名一覧

  coil::vstring outconlist = CORBA_RTCUtil::get_connector_names(consolein.in(), "ConsoleIn0.out");
  for (auto& connector : outconlist)
  {
    std::cout << connector << std::endl;
  }

    for connector in OpenRTM_aist.CORBA_RTCUtil.get_connector_names(consolein, "ConsoleIn0.out"):
        print(connector)

データポートの独自インターフェース型の実装手順

OpenRTM-aistのデータポートは基本的にCORBAのメソッド呼び出しでデータを転送しますが、通信インターフェースのプラグインを追加することで様々な通信プロトコルを選択可能になります。


if1.png


このページでは独自通信インターフェースの追加方法を説明します。 以下の独自シリアライザ作成方法も参考にしてください。

OpenRTM-aistにはデータフロー型がPush型の通信とPull型の通信、まだ実装中ですが双方向通信のduplex型があります。 Push型通信はInPortConsumerInPortProviderで構成されており、Pull型通信はOutPortConsumerOutPortProviderで構成されています。

Push型通信ではOutPort側でPublisherがInPortConsumerのput関数を呼び出して、put関数内でInPortProviderへデータを転送します。 InPortProviderではInPortConnectorオブジェクトのwrite関数を呼んでデータを追加します。


if2.png


Pull型通信ではInPort側でOutPortConsumerのget関数を呼び出して、get関数内でOutPortProviderからデータを取得します。 OutPort側でOutPortProviderがOutPortConnectorのread関数を呼んでデータを取得してOutPortConsumerに渡します。


if3.png


このため、Push型通信のためのInPortConsumer、InPortProvider、もしくはPull型通信のためのOutPortConsumer、OutPortProviderを実装することで独自の通信インターフェースが実現できます。

以下に独自インターフェース型の実装手順を記載します。

独自インターフェース型の実装手順(C++)

このページではC++で独自インターフェースを作成する手順を説明します。

以下のソースコードのサンプルでは重要でない部分は省略しているため、詳細なソースコードは以下から取得してください。

CMakeLists.txtの作成

ビルドのために以下のCMakeLists.txtを作成してください。 OpenRTM-aistのライブラリの検出の設定が必要です。 また、生成する動的ライブラリの名前を${target}.dll${target}.soにする必要があります。 Linux環境では先頭にlibを付けるので(libTestIF.so)、以下の例では先頭のlibを削除しています。

 cmake_minimum_required(VERSION 3.1)
 
 set(target TestIF)
 project(${target} CXX)
 
 find_package(OpenRTM REQUIRED)
 
 
 
 add_definitions(${OPENRTM_CFLAGS})
 link_directories(${OPENRTM_LIBRARY_DIRS})
 
 add_library(${target} SHARED ${target}.cpp TestInPortConsumer.cpp TestInPortConsumer.h TestInPortProvider.cpp TestInPortProvider.h TestOutPortConsumer.cpp TestOutPortConsumer.h 
 TestOutPortProvider.cpp TestOutPortProvider.h)
 target_link_libraries(${target} ${OPENRTM_LIBRARIES})
 target_include_directories(${target} SYSTEM PRIVATE ${OPENRTM_INCLUDE_DIRS})
 set_target_properties(${target} PROPERTIES PREFIX "")

ただし、Push型通信を実装する場合はTestInPortConsumer、TestInPortProviderが必要で、Pull型通信を実装する場合はTestOutPortConsumer、TestOutPortConsumerが必要なため、どちらかしか実装しない場合は不要なファイルの作成は不要です。

Push型通信

Push型通信実装のためにTestInPortConsumer(InPortConsumer)、TestInPortProvider(InPortProvider)を実装します。

InPortConsumerの実装

まず以下のようなヘッダーファイル(TestInPortConsumer.h)、ソースファイル(TestInPortConsumer.cpp)を用意します。

 #ifndef TESTINPORTCONSUMER_H
 #define TESTINPORTCONSUMER_H
 
 #include <rtm/InPortConsumer.h>
 
 class TestInPortConsumer
    : public RTC::InPortConsumer
 {
 public:
   TestInPortConsumer();
   ~TestInPortConsumer() override;
   void init(coil::Properties& prop) override;
   RTC::DataPortStatus put(RTC::ByteData& data) override;
   void publishInterfaceProfile(SDOPackage::NVList& properties) override;
   bool subscribeInterface(const SDOPackage::NVList& properties) override;
   void unsubscribeInterface(const SDOPackage::NVList& properties) override;
 };
 
 #endif

 #include "TestInPortConsumer.h"
 
 TestInPortConsumer::TestInPortConsumer()
 {
 }
 
 TestInPortConsumer::~TestInPortConsumer()
 {
 }
 
 void TestInPortConsumer::init(coil::Properties& prop)
 {
 }
 
 RTC::DataPortStatus TestInPortConsumer::put(RTC::ByteData& data)
 {
    return RTC::DataPortStatus::PORT_OK;
 }
 
 void TestInPortConsumer::publishInterfaceProfile(SDOPackage::NVList& properties)
 {
 }
 
 bool TestInPortConsumer::subscribeInterface(const SDOPackage::NVList& properties)
 {
    return true;
 }
 
 void TestInPortConsumer::unsubscribeInterface(const SDOPackage::NVList& properties)
 {
 }

今回はここにファイルの読み書きでデータを転送する独自インターフェースを実装します。

まずコネクタの初期化時にinit関数が呼ばれます。 変数propにはRTSystemEditor等で設定したコネクタの接続情報が格納されています。 以下の例ではpropからtestif.filenameのパラメータを取得してファイル名に設定しています。 init関数は複数回呼ばれる可能性があるので、その点は注意する必要があります。

 void TestInPortConsumer::init(coil::Properties& prop)
 {
    if (prop.propertyNames().size() == 0)
    {
        return;
    }
 
    m_filename = prop.getProperty("testif.filename", "test.dat");
 
 }

データの書き込み時にはput関数が呼ばれます。 変数dataにはバイト列にシリアライズしたデータが格納されています。

 RTC::DataPortStatus TestInPortConsumer::put(RTC::ByteData& data)
 {
 
   std::ofstream fout;
   fout.open(m_filename, std::ios::out | std::ios::binary | std::ios::trunc);
 
   if (fout.fail())
   {
     return RTC::DataPortStatus::PORT_ERROR;
   }
   else
   {
     m_dataid += 1;
     fout.write((const char*)&m_dataid, sizeof(unsigned long));
 
     const unsigned long size = data.getDataLength();
     fout.write((const char*)&size, sizeof(unsigned long));
 
     if (size > 0)
     {
       fout.write((const char*)data.getBuffer(), size);
     }
   }
 
 
   return RTC::DataPortStatus::PORT_OK;
 }

この例ではファイルにデータのID、データサイズ、バイト列データを書き込んでいます。 変数dataのgetDataLength関数でデータサイズ、getBuffer関数でバイト列データを取得して、取得したデータを何らかの方法でInPortProviderへ送信します。 データの読み込みには他にreadData関数を使う事ができます。

その他の関数は基本的に実装の必要はありませんが、InPortProvider側で追加の情報を設定する場合はsubscribeInterface関数でその情報の取得をする必要があります。 unsubscribeInterfaceはコネクタ切断時に呼ばれるので、subscribeInterface関数での処理に関して何らかの終了処理が必要な場合は記述します。

InPortProviderの実装

まず以下のようなヘッダーファイル(TestInPortProvider.h)、ソースファイル(TestInPortProvider.cpp)を用意します。

 #ifndef TESTINPORTPROVIDER_H
 #define TESTINPORTPROVIDER_H
 
 #include <rtm/InPortProvider.h>
 #include <thread>
 
 class TestInPortProvider
    : public RTC::InPortProvider
 {
 public:
   TestInPortProvider();
   ~TestInPortProvider() override;
   void init(coil::Properties& prop) override;
   void setBuffer(RTC::BufferBase<RTC::ByteData>* buffer) override;
   void setListener(RTC::ConnectorInfo& info,
                             RTC::ConnectorListenersBase* listeners) override;
   void setConnector(RTC::InPortConnector* connector) override;
 private:
   RTC::InPortConnector* m_connector;
 };
 
 #endif

 #include "TestInPortProvider.h"
 #include <fstream>
 
 TestInPortProvider::TestInPortProvider() : m_connector(nullptr)
 {
   setInterfaceType("testif");
 }
 
 TestInPortProvider::~TestInPortProvider()
 {
 }
 
 void TestInPortProvider::init(coil::Properties& prop)
 {
 }
 
 void TestInPortProvider::setBuffer(RTC::BufferBase<RTC::ByteData>* buffer)
 {
 }
 
 void TestInPortProvider::setListener(RTC::ConnectorInfo& info,
   RTC::ConnectorListenersBase* listeners)
 {
 }
 
 void TestInPortProvider::setConnector(RTC::InPortConnector* connector)
 {
   m_connector = connector;
 }

ここに処理を追加していきます。 今回の例では、init関数で指定ファイルが変更されているかをポーリングするスレッドを作成しています。

 void TestInPortProvider::init(coil::Properties& prop)
 {
   if (prop.propertyNames().size() == 0)
   {
     return;
   }
 
   const std::string filename = prop.getProperty("testif.filename", "test.dat");
 
   if (!m_running)
   {
     m_thread = std::thread([this, filename] {
       this->m_running = true;
       unsigned long lastid = 0;
       while (this->m_running)
       {
         if (this->m_connector != nullptr)
         {
           std::ifstream fin(filename, std::ios::in | std::ios::binary);
           if (!fin.fail())
           {
             unsigned long id = 0;
             fin.read((char*)&id, sizeof(unsigned long));
 
             if (id != lastid)
             {
               lastid = id;
               unsigned long size = 0;
               fin.read((char*)&size, sizeof(unsigned long));
               if (size > 0)
               {
                 RTC::ByteData data;
                 data.setDataLength(size);
                 fin.read((char*)data.getBuffer(), size);
                 this->m_connector->write(data);
               }
             }
           }
         }
       }
       });
   }
 }

ファイルからデータを取得後に、m_connectorのwrite関数を呼び出してデータをInPortConnectorに渡しています。 InPortConsumerのデータをファイルに書き込んで、InPortProviderでファイルからデータを読み込むというデータ転送を実装できました。

Pull型通信

Pull型通信実装のためにTestInPortConsumer(OutPortConsumer)、TestInPortProvider(OutPortProvider)を実装します。 ただし、Push型通信のみを実装する場合はここは飛ばしてください。

InPortConsumerの実装

まず以下のようなヘッダーファイル(TestOutPortConsumer.h)、ソースファイル(TestOutPortConsumer.cpp)を用意します。

 #ifndef TESTOUTPORTCONSUMER_H
 #define TESTOUTPORTCONSUMER_H
 
 #include <rtm/SystemLogger.h>
 #include <rtm/OutPortConsumer.h>
 
 class TestOutPortConsumer
  : public RTC::OutPortConsumer
 {
 public:
   TestOutPortConsumer();
   ~TestOutPortConsumer() override;
   void init(coil::Properties& prop) override;
   void setBuffer(RTC::CdrBufferBase* buffer) override;
   void setListener(RTC::ConnectorInfo& info,
     RTC::ConnectorListenersBase* listeners) override;
   RTC::DataPortStatus get(RTC::ByteData& data) override;
   bool subscribeInterface(const SDOPackage::NVList& properties) override;
   void unsubscribeInterface(const SDOPackage::NVList& properties) override;
 };
 
 #endif

 #include "TestOutPortConsumer.h"
 
 
 TestOutPortConsumer::TestOutPortConsumer()
 {
 }
 
 TestOutPortConsumer::~TestOutPortConsumer()
 {
 }
 
 void TestOutPortConsumer::init(coil::Properties& prop)
 {
 }
 
 void TestOutPortConsumer::setBuffer(RTC::CdrBufferBase* buffer)
 {
 }
 
 void TestOutPortConsumer::setListener(RTC::ConnectorInfo& info,
   RTC::ConnectorListenersBase* listeners)
 {
 }
 
 RTC::DataPortStatus TestOutPortConsumer::get(RTC::ByteData& data)
 {
   return RTC::DataPortStatus::PORT_OK;
 }
 
 bool TestOutPortConsumer::subscribeInterface(const SDOPackage::NVList& properties)
 {
   return true;
 }
 
 void TestOutPortConsumer::unsubscribeInterface(const SDOPackage::NVList& properties)
 {
 }

今回の例ではinit関数で読み書きするファイル名を指定します。

 void TestOutPortConsumer::init(coil::Properties& prop)
 {
   if (prop.propertyNames().size() == 0)
   {
     return;
   }
 
   m_filename_in = prop.getProperty("testif.filename_in", "test_in.dat");
   m_filename_out = prop.getProperty("testif.filename_out", "test_out.dat");
 }

ここに処理を追加していきます。 Pull型通信ではデータ読み込み時にget関数を呼びますが、以下の例ではファイルAに呼び出しのIDを書き込みます。 次にファイルBからデータサイズとバイト列データを読み込んで変数dataに格納しています。 データサイズを設定するにはsetDataLength関数を使用します。 データの格納にはgetBuffer関数で取得したポインタのアドレスに書き込むか、writeData関数を使用します。

 RTC::DataPortStatus TestOutPortConsumer::get(RTC::ByteData& data)
 {
   std::ofstream fout;
   fout.open(m_filename_out, std::ios::out | std::ios::binary | std::ios::trunc);
 
   if (fout.fail())
   {
     return RTC::DataPortStatus::PORT_ERROR;
   }
   else
   {
     m_dataid += 1;
     fout.write((const char*)&m_dataid, sizeof(unsigned long));
     fout.close();
 
     for (int i = 0; i < 100; i++)
     {
       std::ifstream fin(m_filename_in, std::ios::in | std::ios::binary);
       if (!fin.fail())
       {
         unsigned long id = 0;
         fin.read((char*)&id, sizeof(unsigned long));
 
         if (id == m_dataid)
         {
           unsigned long size = 0;
           fin.read((char*)&size, sizeof(unsigned long));
           if (size > 0)
           {
             data.setDataLength(size);
             fin.read((char*)data.getBuffer(), size);
             return RTC::DataPortStatus::PORT_OK;
           }
 
         }
       }
     }
   }
 
   return RTC::DataPortStatus::PORT_ERROR;
 }

OutPortProviderの実装

まず以下のようなヘッダーファイル(TestOutPortProvider.h)、ソースファイル(TestOutPortProvider.cpp)を用意します。

 #ifndef TESTOUTPORTPROVIDER_H
 #define TESTOUTPORTPROVIDER_H
 
 #include <rtm/OutPortProvider.h>
 
 class TestOutPortProvider
  : public RTC::OutPortProvider
 {
 public:
   TestOutPortProvider();
   ~TestOutPortProvider() override;
   void init(coil::Properties& prop) override;
   void setBuffer(RTC::CdrBufferBase* buffer) override;
   void setListener(RTC::ConnectorInfo& info,
     RTC::ConnectorListenersBase* listeners) override;
   void setConnector(RTC::OutPortConnector* connector) override;
 private:
   RTC::OutPortConnector* m_connector;
 };
 
 #endif

 #include "TestOutPortProvider.h"
 
 
 TestOutPortProvider::TestOutPortProvider() : m_connector(nullptr)
 {
   setInterfaceType("testif");
 }
 
 TestOutPortProvider::~TestOutPortProvider()
 {
 }
 
 void TestOutPortProvider::init(coil::Properties& prop)
 {
 }
 
 void TestOutPortProvider::setBuffer(RTC::CdrBufferBase* buffer)
 {
 }
 
 void TestOutPortProvider::setListener(RTC::ConnectorInfo& info,
   RTC::ConnectorListenersBase* listeners)
 {
 }
 
 void TestOutPortProvider::setConnector(RTC::OutPortConnector* connector)
 {
   m_connector = connector;
 }

ここに処理を追加していきます。 以下の例ではinit関数でファイルが変更されたかをポーリングして、変更時に別のファイルにデータを書き込むスレッドを起動しています。

 void TestOutPortProvider::init(coil::Properties& prop)
 {
   if (prop.propertyNames().size() == 0)
   {
     return;
   }
 
   const std::string filename_in = prop.getProperty("testif.filename_in", "test_in.dat");
   const std::string filename_out = prop.getProperty("testif.filename_out", "test_out.dat");
 
   if (!m_running)
   {
     m_thread = std::thread([this, filename_in, filename_out] {
       this->m_running = true;
       unsigned long lastid = 0;
       while (this->m_running)
       {
         if (this->m_connector != nullptr)
         {
           std::ifstream fin(filename_out, std::ios::in | std::ios::binary);
           if (!fin.fail())
           {
             unsigned long id = 0;
             fin.read((char*)&id, sizeof(unsigned long));
             fin.close();
 
             if (lastid != id)
             {
               std::ofstream fout;
               fout.open(filename_in, std::ios::out | std::ios::binary | std::ios::trunc);
               if (!fout.fail())
               {
                 fout.write((const char*)&id, sizeof(unsigned long));
 
                 RTC::ByteData data;
                 m_connector->read(data);
 
                 const unsigned long size = data.getDataLength();
                 fout.write((const char*)&size, sizeof(unsigned long));
 
                 if (size > 0)
                 {
                   fout.write((const char*)data.getBuffer(), size);
                 }
               }
 
               lastid = id;
             }
           }
         }
       }
     });
   }
 }

まずm_connectorのread関数を呼んでOutPortConnectorから転送するデータを取得します。 getDataLength関数でデータサイズを取得、getBuffer関数でバイト列データを取得してファイルに書き込んでいます。

これにより、OutPortConsumerでファイルAにデータのIDを書き込み後にOutPortProviderでファイルAからIDを読み込んで前回読み込んだデータのIDと一致しているかを判定します。 新しいデータだと判定したらファイルBにデータを書き込んで、OutPortConsumerでファイルBが新しいデータかを判定してOutPortConnectorにデータを渡します。

独自インターフェースの登録

ここまでに実装した独自インターフェースを使用可能にするためファクトリに登録します。 以下の内容のTestIF.cppを作成してください。

 #include "TestInPortConsumer.h"
 #include "TestInPortProvider.h"
 #include "TestOutPortConsumer.h"
 #include "TestOutPortProvider.h"
 #include <rtm/Manager.h>
 
 extern "C"
 {
   DLL_EXPORT void TestIFInit(RTC::Manager* manager)
   {
      {
        RTC::InPortProviderFactory& factory(RTC::InPortProviderFactory::instance());
        factory.addFactory("testif",
                       ::coil::Creator< ::RTC::InPortProvider,
                                         TestInPortProvider>,
                       ::coil::Destructor< ::RTC::InPortProvider,
                                         TestInPortProvider>);
      }
 
      {
        RTC::InPortConsumerFactory& factory(RTC::InPortConsumerFactory::instance());
        factory.addFactory("testif",
                       ::coil::Creator< ::RTC::InPortConsumer,
                                         TestInPortConsumer>,
                       ::coil::Destructor< ::RTC::InPortConsumer,
                                         TestInPortConsumer>);
      }
 
      {
        RTC::OutPortProviderFactory& factory(RTC::OutPortProviderFactory::instance());
        factory.addFactory("testif",
                       ::coil::Creator< ::RTC::OutPortProvider,
                                         TestOutPortProvider>,
                       ::coil::Destructor< ::RTC::OutPortProvider,
                                         TestOutPortProvider>);
      }
 
      {
        RTC::OutPortConsumerFactory& factory(RTC::OutPortConsumerFactory::instance());
        factory.addFactory("testif",
                       ::coil::Creator< ::RTC::OutPortConsumer,
                                        TestOutPortConsumer>,
                       ::coil::Destructor< ::RTC::OutPortConsumer,
                                         TestOutPortConsumer>);
      }
   }
 }

InPortProviderFactoryInPortConsumerFactoryOutPortProviderFactoryOutPortConsumerFactoryaddFactory関数で実装した独自インターフェースを登録しています。 この例の場合、testifという名前をポート接続時に指定することで使用できます。 Push型のみ、もしくはPull型通信のみの実装の場合は、必要なモジュールだけを登録してください。 TestIFInit関数は動的ライブラリをロードする時に呼び出す関数です。〇〇.dllであれば〇〇Initというように、初期化関数は動的ライブラリの名前+Initにしてください。

動作確認

ビルドしてTestIF.dllTestIF.so生成後に、以下のrtc.confを作成してください。 ${TestIF_DIR}にはTestIF.dll、TestIF.soのフォルダのパスを指定してください。

 manager.modules.load_path: ${TestIF_DIR}
 manager.preload.modules: TestIF.dll

作成したrtc.confを指定してConsoleIn、ConsoleOutのサンプルコンポーネントを起動します。これでOpenRTM-aistがTestIF.dllをロードします。

 ConsoleIn -f rtc.conf

 ConsoleOut -f rtc.conf

RTSystemEditorでデータポートを接続しようとすると、以下のようにInterface Typeでtestifが選択可能になっています。


/ja/node/7138


Interface Typeにtestifを選択して接続すると、実装したファイル読み書きによるデータ転送ができることが確認できます。

Pull型通信を動作確認する場合について、Pull型通信ではInPortのisNew関数が使えず新規のデータが存在するかは確認できません。 このため、ConsoleOutコンポーネントのisNew関数を実行している部分をコメントアウトして再ビルドする必要があります。

   //if (m_inIn.isNew())

接続時のオプションを設定

今回の例ではtestif.filename、testif.filename_in、testif.filename_outというオプションで読み書きするファイル名を指定できるようにしましたが、これらをデータポートのプロファイルからオプションの情報を取得するように設定を追加できます。ただし、リリース版のOpenRTM-aist 2.0では使えない場合があるので、OpenRTM-aistをソースコードからビルドしてください。

 static const char* const testifpush_option[] =
 {
   "filename.__value__", "test.dat",
   "filename.__widget__", "text",
   "filename.__constraint__", "none",
   ""
 };
 
 extern "C"
 {
   DLL_EXPORT void TestIFInit(RTC::Manager* manager)
   {
      {
        coil::Properties prop(testifpush_option);
        RTC::InPortProviderFactory& factory(RTC::InPortProviderFactory::instance());
        factory.addFactory("testif",
                      ::coil::Creator< ::RTC::InPortProvider,
                                        TestInPortProvider>,
                      ::coil::Destructor< ::RTC::InPortProvider,
                                        TestInPortProvider>,
                      prop);
      }

独自インターフェース型の実装手順(Python)

このページではPythonで独自インターフェースを作成する手順を説明します。

以下のソースコードのサンプルでは重要でない部分は省略しているため、詳細なソースコードは以下から取得してください。

Push型通信

Push型通信実装のためにTestInPortConsumer(InPortConsumer)、TestInPortProvider(InPortProvider)を実装します。

InPortConsumerの実装

まず以下のようなPythonファイル(TestInPortConsumer.py)を用意します。

 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 
 import OpenRTM_aist
 
 
 class TestInPortConsumer(
        OpenRTM_aist.InPortConsumer):
    
    def __init__(self):
        pass
 
    def __del__(self):
        pass
 
    def init(self, prop):
        if not prop.propertyNames():
            return
 
 
    def put(self, data):
            return self.PORT_OK
 
    def publishInterfaceProfile(self, properties):
        pass
 
    def subscribeInterface(self, properties):
        return True
 
    def unsubscribeInterface(self, properties):
        pass
     
    
 def TestInPortConsumerInit():
    factory = OpenRTM_aist.InPortConsumerFactory.instance()
    factory.addFactory("testif",
                       TestInPortConsumer)

今回はここにファイルの読み書きでデータを転送する独自インターフェースを実装します。

まずコネクタの初期化時にinit関数が呼ばれます。 変数propにはRTSystemEditor等で設定したコネクタの接続情報が格納されています。 以下の例ではpropからtestif.filenameのパラメータを取得してファイル名に設定しています。 init関数は複数回呼ばれる可能性があるので、その点は注意する必要があります。

    def init(self, prop):
        if not prop.propertyNames():
            return
        self._filename = prop.getProperty("testif.filename", "test.dat")

データの書き込み時にはput関数が呼ばれます。 変数dataはbytes型のシリアライズしたデータが格納されています。

    def put(self, data):
        with open(self._filename, 'wb') as fout:
            self._dataid += 1
            try:
                fout.write(struct.pack('L', self._dataid))
                fout.write(struct.pack('L', len(data)))
                fout.write(data)
            except BaseException:
                return self.PORT_ERROR
            return self.PORT_OK

この例ではファイルにデータのID、データサイズ、バイト列データを書き込んでいます。 変数dataのgetDataLength関数でデータサイズ、getBuffer関数でバイト列データを取得して、取得したデータを何らかの方法でInPortProviderへ送信します。

その他の関数は基本的に実装の必要はありませんが、InPortProvider側で追加の情報を設定する場合はsubscribeInterface関数でその情報の取得をする必要があります。 unsubscribeInterfaceはコネクタ切断時に呼ばれるので、subscribeInterface関数での処理に関して何らかの終了処理が必要な場合は記述します。

InPortProviderの実装

まず以下のようなPythonファイル(TestInPortProvider.py)を用意します。

 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 
 import OpenRTM_aist
 
 
 class TestInPortProvider(OpenRTM_aist.InPortProvider):
 
    def __init__(self):
        OpenRTM_aist.InPortProvider.__init__(self)
 
        self.setInterfaceType("testif")
 
 
    def __del__(self):
        pass
 
    def exit(self):
        pass
 
    def init(self, prop):
        if not prop.propertyNames():
            return
 
    def setBuffer(self, buffer):
        pass
 
    def setListener(self, info, listeners):
        pass
 
    def setConnector(self, connector):
        self._connector = connector
 
 
 def TestInPortProviderInit():
    factory = OpenRTM_aist.InPortProviderFactory.instance()
    factory.addFactory("testif",
                       TestInPortProvider)

ここに処理を追加していきます。 今回の例では、init関数で指定ファイルが変更されているかをポーリングするスレッドを作成しています。

    def init(self, prop):
        if not prop.propertyNames():
            return
        filename = prop.getProperty("testif.filename", "test.dat")
        
        def polling():
            self._running = True
            lastid = 0
            while self._running:
                if self._connector:
                    if os.path.exists(filename):
                        with open(filename, 'rb') as fin:
                            try:
                                id = struct.unpack("L", fin.read(struct.calcsize("L")))[0]
                                if id != lastid:
                                    lastid = id
                                    size = struct.unpack("L", fin.read(struct.calcsize("L")))[0]
                                    if size > 0:
                                        data = fin.read(size)
                                        self._connector.write(data)
                            except BaseException:
                                pass
        
        self._thread = threading.Thread(target=polling)
        self._thread.start()

ファイルからデータを取得後に、m_connectorのwrite関数を呼び出してデータをInPortConnectorに渡しています。 InPortConsumerのデータをファイルに書き込んで、InPortProviderでファイルからデータを読み込むというデータ転送を実装できました。

Pull型通信

Pull型通信実装のためにTestInPortConsumer(OutPortConsumer)、TestInPortProvider(OutPortProvider)を実装します。 ただし、Push型通信のみを実装する場合はここは飛ばしてください。

InPortConsumerの実装

まず以下のようなPythonファイル(TestOutPortConsumer.py)を用意します。

 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 
 import OpenRTM_aist
 
 
 class TestOutPortConsumer(
        OpenRTM_aist.OutPortConsumer):
 
    def __init__(self):
        pass
 
    def __del__(self):
        pass
 
    def init(self, prop):
        if not prop.propertyNames():
            return
 
 
    def setBuffer(self, buffer):
        pass
 
    def setListener(self, info, listeners):
        pass
 
    def get(self):
        return self.PORT_ERROR, ""
 
    def subscribeInterface(self, properties):
        return True
 
    def unsubscribeInterface(self, properties):
        pass
 
 
 def TestOutPortConsumerInit():
    factory = OpenRTM_aist.OutPortConsumerFactory.instance()
    factory.addFactory("testif",
                       TestOutPortConsumer)
    return

今回の例ではinit関数で読み書きするファイル名を指定します。

    def init(self, prop):
        if not prop.propertyNames():
            return
        self._filename_in = prop.getProperty(
            "testif.filename_in", "test_in.dat")
        self._filename_out = prop.getProperty(
            "testif.filename_out", "test_out.dat")

ここに処理を追加していきます。 Pull型通信ではデータ読み込み時にget関数を呼びますが、以下の例ではファイルAに呼び出しのIDを書き込みます。 次にファイルBからデータサイズとバイト列データを読み込んで値を返しています。

    def get(self):
        with open(self._filename_in, 'wb') as fout:
            self._dataid += 1
            try:
                print(self._dataid)
                fout.write(struct.pack('L', self._dataid))
            except BaseException:
                return self.PORT_ERROR
        
        for i in range(100):
            if os.path.exists(self._filename_out):
                with open(self._filename_out, 'rb') as fin:
                    try:
                        id = struct.unpack("L", fin.read(struct.calcsize("L")))[0]
                        if id == self._dataid:
                            self._dataid = id
                            size = struct.unpack("L", fin.read(struct.calcsize("L")))[0]
                            if size > 0:
                                data = fin.read(size)
                                return self.PORT_OK, data
                    except BaseException:
                        pass
        
        return self.PORT_ERROR, ""

OutPortProviderの実装

まず以下のようなPythonファイル(TestOutPortProvider.py)を用意します。

 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 
 import OpenRTM_aist
 
 
 class TestOutPortProvider(OpenRTM_aist.OutPortProvider):
 
    def __init__(self):
        OpenRTM_aist.OutPortProvider.__init__(self)
        self.setInterfaceType("testif")
 
        self._thread = None
        self._running = False
        self._connector = None
 
    def __del__(self):
        pass
 
    def exit(self):
        if self._running:
            self._running = False
            self._thread.join()
 
    def init(self, prop):
        if not prop.propertyNames():
            return
 
    def setBuffer(self, buffer):
        pass
 
    def setListener(self, info, listeners):
        pass
 
    def setConnector(self, connector):
        self._connector = connector
 
 
 def TestOutPortProviderInit():
    factory = OpenRTM_aist.OutPortProviderFactory.instance()
    factory.addFactory("testif",
                       TestOutPortProvider)

ここに処理を追加していきます。 以下の例ではinit関数でファイルが変更されたかをポーリングして、変更時に別のファイルにデータを書き込むスレッドを起動しています。

    def init(self, prop):
        if not prop.propertyNames():
            return
        
        filename_in = prop.getProperty("testif.filename_in", "test_in.dat")
        filename_out = prop.getProperty("testif.filename_out", "test_out.dat")
        
        def polling():
            self._running = True
            lastid = 0
            while self._running:
                if self._connector:
                    if os.path.exists(filename_in):
                        with open(filename_in, 'rb') as fin:
                            try:
                                id = struct.unpack("L", fin.read(struct.calcsize("L")))[0]
                                if id == lastid:
                                    continue
                            except BaseException:
                                continue
                        with open(filename_out, 'wb') as fout:
                            try:
                                fout.write(struct.pack('L', id))
                                ret, data = self._connector.read()
                                fout.write(struct.pack('L', len(data)))
                                if ret == OpenRTM_aist.BufferStatus.BUFFER_OK:
                                    fout.write(data)
                                    lastid = id
                            except BaseException:
                                pass

まずm_connectorのread関数を呼んでOutPortConnectorから転送するデータを取得します。 getDataLength関数でデータサイズを取得、getBuffer関数でバイト列データを取得してファイルに書き込んでいます。

これにより、OutPortConsumerでファイルAにデータのIDを書き込み後にOutPortProviderでファイルAからIDを読み込んで前回読み込んだデータのIDと一致しているかを判定します。 新しいデータだと判定したらファイルBにデータを書き込んで、OutPortConsumerでファイルBが新しいデータかを判定してOutPortConnectorにデータを渡します。

独自インターフェースの登録

ここまでに実装した独自インターフェースを使用可能にするためファクトリに登録します。 以下の内容のTestIF.pyを作成してください。

 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 # -*- Python -*-
 
 
 import TestInPortConsumer
 import TestInPortProvider
 import TestOutPortConsumer
 import TestOutPortProvider
 
 
 def TestIFInit(mgr):
    TestInPortConsumer.TestInPortConsumerInit()
    TestInPortProvider.TestInPortProviderInit()
    TestOutPortConsumer.TestOutPortConsumerInit()
    TestOutPortProvider.TestOutPortProviderInit()

TestInPortProviderInit、TestInPortConsumerInit、TestOutPortProviderInit、TestOutPortConsumerInit関数ではInPortProviderFactoryInPortConsumerFactoryOutPortProviderFactoryOutPortConsumerFactoryaddFactory関数で実装した独自インターフェースを登録しています。 testifという名前をポート接続時に指定することで使用できます。 TestIFInit関数はPythonモジュールをロードする時に呼び出す関数です。〇〇.pyであれば〇〇Initというように、初期化関数はPythonファイルの名前+Initにしてください。 Push型のみ、もしくはPull型通信のみの実装の場合は、必要なモジュールだけを登録してください。

動作確認

以下のrtc.confを作成してください。 ${TestIF_DIR}にはTestIF.pyのフォルダのパスを指定してください。

 manager.modules.load_path: .
 manager.modules.preload: TestIF.py

作成したrtc.confを指定してConsoleIn、ConsoleOutのサンプルコンポーネントを起動します。これでOpenRTM-aistがTestIF.pyをロードします。

 python ConsoleIn.py -f rtc.conf

 python ConsoleOut.py -f rtc.conf

RTSystemEditorでデータポートを接続しようとすると、以下のようにInterface Typeでtestifが選択可能になっています。


/ja/node/7138


Interface Typeにtestifを選択して接続すると、実装したファイル読み書きによるデータ転送ができることが確認できます。

Pull型通信を動作確認する場合について、Pull型通信ではInPortのisNew関数が使えず新規のデータが存在するかは確認できません。 このため、ConsoleOutコンポーネントのisNew関数を実行している部分をコメントアウトする必要があります。

        # if self._inport.isNew():

接続時のオプションを設定

今回の例ではtestif.filename、testif.filename_in、testif.filename_outというオプションで読み書きするファイル名を指定できるようにしましたが、これらをデータポートのプロファイルからオプションの情報を取得するように設定を追加できます。ただし、リリース版のOpenRTM-aist 2.0では使えない場合があるので、OpenRTM-aistをソースコードからビルドしてください。

 testifpush_option = [
    "filename_in.__value__", "test_in.dat",
    "filename_in.__widget__", "text",
    "filename_in.__constraint__", "none",
    "filename_out.__value__", "test_out.dat",
    "filename_out.__widget__", "text",
    "filename_out.__constraint__", "none",
    ""
 ]
 
 
 def TestInPortProviderInit():
    prop = OpenRTM_aist.Properties(defaults_str=testifpush_option)
    factory = OpenRTM_aist.InPortProviderFactory.instance()
    factory.addFactory("testif",
                       TestInPortProvider,
                       prop)

独自インターフェース型の実装手順(Java)

LocalServiceの利用方法

rtcname形式、rtcloc形式でのRTCへのアクセス

概要

OpenRTM-aistにはrtcname形式、rtcloc形式という文字列からRTCへアクセスする機能が利用できます。

rtcname形式は指定のネームサーバーに登録されたRTCにアクセスする方式であり、接続するネームサーバーのアドレス、ネーミングコンテキスト、RTCのバインディング名を指定することでRTCのオブジェクトリファレンスを取得できます。

 rtcname://{ネームサーバーのIPアドレス}:{ネームサーバーのポート番号}/{ネーミングコンテキスト名(省略可)}/{RTCのバインディング名}

rtcloc形式は指定のマスターマネージャに登録されたスレーブマネージャからRTCにアクセスする方式であり、接続するマスターマネージャのアドレス、RTCのカテゴリ名、RTCのインスタンス名を指定することでRTCのオブジェクトリファレンスを取得できます。

 rtcloc://{マスターマネージャのIPアドレス}:{マスターマネージャのポート番号}/{RTCのカテゴリ名(省略可)}/{RTCのインスタンス名}

rtcname形式でのRTCへのアクセス

以下のようにrtc.confのmanager.components.preconnectmanager.components.preactivationでrtcname形式によりRTCを指定することで、外部のプロセスで起動したポートの接続やRTCのアクティブ化ができます。

 manager.components.preconnect: ConsoleIn0.out?port=rtcname://localhost:2809/test.host_cxt/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname://localhost:2809/test.host_cxt/ConsoleOut0

ただし、ネーミングコンテキスト(この例ではtest.host_cxt)は以下のように省略できます。

 manager.components.preconnect: ConsoleIn0.out?port=rtcname://localhost:2809/*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname://localhost:2809/*/ConsoleOut0

プロトコルの指定

※以下の機能はリリース版のOpenRTM-aist 2.0.0で未サポートの場合があります。機能を使う場合はソースコードからビルドする必要があります。

OpenRTM-aistはデフォルトでIIOP通信を行いますが、設定を変更することでomniORBのSSLIOP、HTTP、HTTPS、WebSocket、WebSocket over SSL/TLS通信、TAOのSSLIOP、HTIOP、SHMIOP通信で外部のRTCにアクセスすることができます。 以下のようにrtcnameの後にプロトコル名を指定することで設定できます。

 rtcname.{プロトコル名}://{ネームサーバーのIPアドレス}:{ネームサーバーのポート番号}/{ネーミングコンテキスト名(省略可)}/{RTCのバインディング名}

ただし、設定する通信プロトコルをOpenRTM-aistで使用できるように設定する必要があります。 使用例についても以下のページを参考にしてください。

rtcloc形式でのRTCへのアクセス

以下のようにrtc.confのmanager.components.preconnectmanager.components.preactivationでrtcloc形式によりRTCを指定することで、外部のプロセスで起動したポートの接続やRTCのアクティブ化ができます。 rtcloc形式を使用するためにはマネージャからRTCを取得する機能を有効にするためnaming.typeオプションにmanagerを追加します。

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc://localhost:2810/example/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc://localhost:2810/example/ConsoleOut0

ただし、ネーミングコンテキスト(この例ではtest.host_cxt)は以下のように省略できます。

 manager.components.preconnect: ConsoleIn0.out?port=rtcloc://localhost:2810/*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc://localhost:2810/*/ConsoleOut0

プロトコルの指定

rtcname形式と同じく、rtcloc形式でも通信プロトコルを指定することができます。

 rtcloc.{プロトコル名}://{マスターマネージャのIPアドレス}:{マスターマネージャのポート番号}/{RTCのカテゴリ名(省略可)}/{RTCのインスタンス名}

HTTPTransportの使用方法

omniORB 4.3ではHTTP通信機能をサポートしており、GIOPメッセージをHTTPパケットで送信する仕組みを利用することができます。 HTTP通信機能の利点として、ファイアーウォールやHTTPプロキシサーバを経由した通信が容易になる事や、リバースプロキシやロードバランサー等の既存の仕組みを流用しやすくなるという事があります。 このページではomniORBのHTTP、HTTPS、WebSocket、WSS(WebSocket over SSL/TLS)通信機能OpenRTM-aistから利用する方法を説明します。 ただし、HTTP通信機能はomniORBの独自仕様のため、TAO独自仕様のHTIOP等とは互換性はありません。

以下にomniORBのHTTPパケットの一例を掲載しておきます。TAOのHTIOPでは最初にGETメソッドを呼び出しており、動作が違う事が分かります。

 POST /call HTTP/1.1
 Host: localhost:2809
 User-Agent: omniORB
 Connection: keep-alive
 Content-Type: application/octet-stream
 Content-Length: 103
 
 GIOP\x01\x02\x01\x00[\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00NameService\x00\x06\x00\x00\x00_is_a\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00IDL:omg.org/CosNaming/NamingContextExt:1.0\x00

C++

Windows

OpenRTM-aistのビルドとインストール

まず、OpenSSLのヘッダーファイル、ライブラリを適当な場所に展開してください。

OpenRTM-aist+omniORBを以下の手順でビルド、インストールします。

ただし、CMake実行時にHTTP_ENABLEOPENSSL_ROOT_DIRのオプションを設定する必要があります。

設定項目 内容 設定例
HTTP_ENABLE HTTPTransportプラグインの生成の有無 ON
OPENSSL_ROOT_DIR OpenSSLの各種ファイルを配置したパス C:/work/OpenSSL/x64

また、CMake実行時にOpenRTM-aistのインストールフォルダは指定してそこにインストールするようにしてください。

 set OPENRTM_INSTALL_DIR=C:/work/openrtm_install
 set OMNIORB_SOURCE_DIR=C:/workspace/omniORB-4.3.0-x64-vc16-py310
 set OPENSSL_ROOT_DIR=C:/work/OpenSSL/x64
 cmake .. -DORB_ROOT=%OMNIORB_SOURCE_DIR% -DHTTP_ENABLE=ON -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT_DIR% -DCMAKE_INSTALL_PREFIX=%OPENRTM_INSTALL_DIR%
 cmake --build . --config Release
 cmake --build . --config Release --target install

Ubuntu

OpenRTM-aistのビルドとインストール

OpenSSLのヘッダとライブラリをインストールします。

 sudo apt install libssl-dev

OpenRTM-aist+omniORBを以下の手順でビルド、インストールします。

ただし、HTTP_ENABLEのオプションを設定する必要があります。

設定項目 内容 設定例
HTTP_ENABLE HTTPTransportプラグインの生成の有無 ON

 set OPENRTM_INSTALL_DIR=~/work/openrtm_install
 cmake .. -DHTTP_ENABLE=ON -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

Python

OpenRTM-aistのビルドとインストール

以下の手順でOpenRTM-aist Python版をインストールしてださい。

ただし、動作確認でOpenRTM-aist C++版付属のネームサーバーを使用するため、C++版のビルドも実行してください。

動作確認

HTTP通信

ネームサーバー起動

HTTPTransportの動作確認のためにはネームサーバーがHTTP通信に対応している必要があります。 OpenRTM-aist付属のopenrtmNamesを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%/2.0.0/ext/rtc.names.http.conf

 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.http.conf

RTC起動

以下のようなrtc.confを作成します。OpenRTM-aistをインストールしたパスは適宜変更してください。

C++では以下のファイルを作成します。

 manager.modules.load_path: C:/work/openrtm_install/2.0.0/ext/vc16/http
 manager.preload.modules: HTTPTransport.dll
 
 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:http:///call
 corba.nameservers: http://localhost:2809/call
 corba.master_manager: http:http://localhost:2810/call

Pythonでは以下のファイルを作成します。

 manager.modules.load_path: C:/Python37/Lib/site-packages/OpenRTM_aist/ext/http
 manager.preload.modules: HTTPTransport.py
 
 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:http:///call
 corba.nameservers: http://localhost:2809/call
 corba.master_manager: http:http://localhost:2810/call

各設定項目の内容は以下のようになっています。

項目名 説明
corba.args CORBAライブラリの初期化関数に渡す引数。ここでHTTP通信のエンドポイントを設定する必要がある。
corba.nameservers ネームサーバーのアドレス。ここでHTTP通信でネームサーバーに接続するように設定する。
corba.master_manager マスターマネージャのエンドポイント。マスターマネージャの場合は自身のエンドポイントを設定し、スレーブマネージャの場合は接続先のマスターマネージャのアドレスを設定する。

このrtc.confを指定してConsoleIn、ConsoleOutのRTCを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleInComp.exe -f rtc.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleInComp -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleIn.py -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleIn.py -f rtc.conf

これでネームサーバーに登録されますが、RTシステムエディタにHTTP通信機能はないため、OpenRTM-aistの機能かrtshellによりポートの接続やRTCのアクティブ化を実行する必要があります。

HTTPS通信

ネームサーバー起動

HTTPTransportの動作確認のためにはネームサーバーがHTTP通信に対応している必要があります。 OpenRTM-aist付属のopenrtmNamesを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%/2.0.0/ext/rtc.names.https.conf
 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.https.conf

rtc.names.https.confでは生成済みのルート証明書root.crtと秘密鍵とサーバー証明書を連結したファイルserver.pemを使用するため、動作確認に使用するRTCもこれらの証明書ファイルを使います。 実際にシステムを開発する際は証明書と秘密鍵を変更してください。

RTC起動

以下のようなrtc.confを作成します。OpenRTM-aistをインストールしたパスは適宜変更してください。

C++では以下のファイルを作成します。

 manager.modules.load_path: C:/work/openrtm_install/2.0.0/ext/vc16/http
 manager.preload.modules: HTTPTransport.dll
 
 corba.http.certificate_authority_file:C:/work/openrtm_install/2.0.0/ext/ssl/root.crt
 corba.http.key_file:C:/work/openrtm_install/2.0.0/ext/ssl/server.pem
 corba.http.key_file_password:password
 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:https:///call
 corba.nameservers: https://localhost:2809/call
 corba.master_manager: http:https://localhost:2810/call

Pythonでは以下のファイルを作成します。

 manager.modules.load_path: C:/Python37/Lib/site-packages/OpenRTM_aist/ext/http
 manager.preload.modules: HTTPTransport.py
 
 corba.http.certificate_authority_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/root.crt
 corba.http.key_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/server.pem
 corba.http.key_file_password:password
 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:https:///call
 corba.nameservers: https://localhost:2809/call
 corba.master_manager: http:https://localhost:2810/call

各設定項目の内容は以下のようになっています。

項目名 説明
corba.http.certificate_authority_file ルート証明書
corba.http.key_file 秘密鍵+サーバー証明書兼クライアント証明書の連結ファイル
corba.http.key_file_password 秘密鍵のパスフレーズ
corba.args CORBAライブラリの初期化関数に渡す引数。ここでHTTPS通信のエンドポイントを設定する必要がある。
corba.nameservers ネームサーバーのアドレス。ここでHTTPS通信でネームサーバーに接続するように設定する。
corba.master_manager マスターマネージャのエンドポイント。マスターマネージャの場合は自身のエンドポイントを設定し、スレーブマネージャの場合は接続先のマスターマネージャのアドレスを設定する。

このrtc.confを指定してConsoleIn、ConsoleOutのRTCを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleInComp.exe -f rtc.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleInComp -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleIn.py -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleIn.py -f rtc.conf

これでネームサーバーに登録されますが、RTシステムエディタにHTTP通信機能はないため、OpenRTM-aistの機能かrtshellによりポートの接続やRTCのアクティブ化を実行する必要があります。

WebSocket通信

ネームサーバー起動

HTTPTransportの動作確認のためにはネームサーバーがHTTP通信に対応している必要があります。 OpenRTM-aist付属のopenrtmNamesを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%/2.0.0/ext/rtc.names.ws.conf

 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.ws.conf

RTC起動

以下のようなrtc.confを作成します。OpenRTM-aistをインストールしたパスは適宜変更してください。

C++では以下のファイルを作成します。

 manager.modules.load_path: C:/work/openrtm_install/2.0.0/ext/vc16/http
 manager.preload.modules: HTTPTransport.dll
 
 corba.args:-ORBserverTransportRule "* http,tcp" -ORBclientTransportRule "* http,tcp" -ORBendPoint giop:http:ws:///ws -ORBendPoint giop:tcp::
 corba.nameservers: ws://localhost:2809/ws
 corba.master_manager: giop:http:ws://localhost:2810/ws

Pythonでは以下のファイルを作成します。

 manager.modules.load_path: C:/Python37/Lib/site-packages/OpenRTM_aist/ext/http
 manager.preload.modules: HTTPTransport.py
 
 corba.args:-ORBserverTransportRule "* http,tcp" -ORBclientTransportRule "* http,tcp" -ORBendPoint giop:http:ws:///ws -ORBendPoint giop:tcp::
 corba.nameservers: ws://localhost:2809/ws
 corba.master_manager: giop:http:ws://localhost:2810/ws

IIOP(TCP)のエンドポイントを設定していますが、これはWebSocketのアドレスだけをエンドポイントに設定した場合にCORBAオブジェクトの比較(_is_equivalent)が上手く動作しないためなので、今後omniORB側で修正されたら設定は不要です。

各設定項目の内容は以下のようになっています。

項目名 説明
corba.args CORBAライブラリの初期化関数に渡す引数。ここでHTTP通信のエンドポイントを設定する必要がある。
corba.nameservers ネームサーバーのアドレス。ここでWebSocket通信でネームサーバーに接続するように設定する。
corba.master_manager マスターマネージャのエンドポイント。マスターマネージャの場合は自身のエンドポイントを設定し、スレーブマネージャの場合は接続先のマスターマネージャのアドレスを設定する。

このrtc.confを指定してConsoleIn、ConsoleOutのRTCを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleInComp.exe -f rtc.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleInComp -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleIn.py -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleIn.py -f rtc.conf

これでネームサーバーに登録されますが、RTシステムエディタにHTTP通信機能はないため、OpenRTM-aistの機能かrtshellによりポートの接続やRTCのアクティブ化を実行する必要があります。

WebSocket over SSL/TLS通信

ネームサーバー起動

HTTPTransportの動作確認のためにはネームサーバーがHTTP通信に対応している必要があります。 OpenRTM-aist付属のopenrtmNamesを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%/2.0.0/ext/rtc.names.wss.conf

 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.https.conf

rtc.names.https.confでは生成済みのルート証明書root.crtと秘密鍵とサーバー証明書を連結したファイルserver.pemを使用するため、動作確認に使用するRTCもこれらの証明書ファイルを使います。 実際にシステムを開発する際は証明書と秘密鍵を変更してください。

RTC起動

以下のようなrtc.confを作成します。OpenRTM-aistをインストールしたパスは適宜変更してください。

C++では以下のファイルを作成します。

 manager.modules.load_path: C:/work/openrtm_install/2.0.0/ext/vc16/http
 manager.preload.modules: HTTPTransport.dll
 
 corba.http.certificate_authority_file:C:/work/openrtm_install/2.0.0/ext/ssl/root.crt
 corba.http.key_file:C:/work/openrtm_install/2.0.0/ext/ssl/server.pem
 corba.http.key_file_password:password
 corba.args:-ORBserverTransportRule "* http,tcp" -ORBclientTransportRule "* http,tcp" -ORBendPoint giop:http:wss:///ws -ORBendPoint giop:tcp::
 corba.nameservers: wss://localhost:2809/ws
 corba.master_manager: giop:http:wss://localhost:2810/ws

Pythonでは以下のファイルを作成します。

 manager.modules.load_path: C:/Python37/Lib/site-packages/OpenRTM_aist/ext/http
 manager.preload.modules: HTTPTransport.py
 
 corba.http.certificate_authority_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/root.crt
 corba.http.key_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/server.pem
 corba.http.key_file_password:password
 corba.args:-ORBserverTransportRule "* http,tcp" -ORBclientTransportRule "* http,tcp" -ORBendPoint giop:http:wss:///ws -ORBendPoint giop:tcp::
 corba.nameservers: wss://localhost:2809/ws
 corba.master_manager: giop:http:wss://localhost:2810/ws

各設定項目の内容は以下のようになっています。

項目名 説明
corba.http.certificate_authority_file ルート証明書
corba.http.key_file 秘密鍵+サーバー証明書兼クライアント証明書の連結ファイル
corba.http.key_file_password 秘密鍵のパスフレーズ
corba.args CORBAライブラリの初期化関数に渡す引数。ここでWSS通信のエンドポイントを設定する必要がある。
corba.nameservers ネームサーバーのアドレス。ここでWSS通信でネームサーバーに接続するように設定する。
corba.master_manager マスターマネージャのエンドポイント。マスターマネージャの場合は自身のエンドポイントを設定し、スレーブマネージャの場合は接続先のマスターマネージャのアドレスを設定する。

このrtc.confを指定してConsoleIn、ConsoleOutのRTCを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleInComp.exe -f rtc.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleInComp -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleIn.py -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleIn.py -f rtc.conf

これでネームサーバーに登録されますが、RTシステムエディタにHTTP通信機能はないため、OpenRTM-aistの機能かrtshellによりポートの接続やRTCのアクティブ化を実行する必要があります。

マネージャ起動時のポート接続、RTCのアクティブ化

rtc.confのmanager.components.preconnectmanager.components.preactivationでrtcname形式、rtcloc形式を指定することでポートの接続、RTCのアクティブ化ができます。 HTTP通信の場合は以下のようにプロトコルにhttphttpswswssを指定することで使用可能になります。

 manager.components.preconnect: ConsoleIn0.out?port=rtcname.http://localhost:2809/call#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname.http://localhost:2809/call#*/ConsoleOut0

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc.http://localhost:2810/call#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc.http://localhost:2810/call#*/ConsoleOut0

 manager.components.preconnect: ConsoleIn0.out?port=rtcname.https://localhost:2809/call#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname.https://localhost:2809#call/*/ConsoleOut0

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc.https://localhost:2810/call#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc.https://localhost:2810/call#*/ConsoleOut0

 manager.components.preconnect: ConsoleIn0.out?port=rtcname.ws://localhost:2809/ws#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname.ws://localhost:2809/ws#*/ConsoleOut0

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc.ws://localhost:2810/call#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc.ws://localhost:2810/call#*/ConsoleOut0

 manager.components.preconnect: ConsoleIn0.out?port=rtcname.wss://localhost:2809/ws#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname.wss://localhost:2809/ws#*/ConsoleOut0

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc.wss://localhost:2810/ws#*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc.wss://localhost:2810/ws#*/ConsoleOut0

rtshellによる操作

まず、現在インストールされるrtshellでは対応していないため、最新版のrtctree、rtshell、rtsprofileが必要です。

rtshellでHTTP通信機能を使用するためには以下の環境変数を設定する必要があります。

環境変数名 設定例 意味
RTCTREE_HTTP_ENABLE YES YES:rtctreeでHTTP通信機能を有効にする。
RTCTREE_NAMESERVERS http://localhost:2809/call 接続するネームサーバー
ORBhttpsCAFile root.crt ルート証明書
ORBhttpsKeyFile server.pem 秘密鍵+サーバー証明書兼クライアント証明書の連結ファイル
ORBhttpsKeyPassword password 秘密鍵のパスフレーズ
ORBserverTransportRule "* http" サーバー側の通信プロトコル選択のルール
ORBclientTransportRule "* http" クライアント側の通信プロトコル選択のルール
ORBendPoint giop:http:http:///call omniORBのエンドポイント

 set RTCTREE_HTTP_ENABLE=YES
 set ORBhttpsCAFile=%RTM_ROOT%/ext/ssl/root.crt
 set ORBhttpsKeyFile=%RTM_ROOT%/ext/ssl/server.pem
 set ORBhttpsKeyPassword=password
 set RTCTREE_NAMESERVERS=https://localhost:2809/call
 set ORBserverTransportRule=* http
 set ORBclientTransportRule=* http
 set ORBendPoint=giop:http:https:///call

以下のように接続するネームサーバーのアドレスの前にssliop:を付けることでSSLIOP通信でネームサーバーに接続できるようになります。

 rtcon /https:localhost:2809/call#test.host_cxt/ConsoleIn0.rtc:out /https:localhost:2809/call#est.host_cxt/ConsoleOut0.rtc:in
 rtact /https:localhost:2809/call#test.host_cxt/ConsoleIn0.rtc /https:localhost:2809/call#test.host_cxt/ConsoleOut0.rtc
 rtdeact /https:localhost:2809/call#test.host_cxt/ConsoleIn0.rtc /https:localhost:2809/call#test.host_cxt/ConsoleOut0.rtc
 rtexit /https:localhost:2809/call#test.host_cxt/ConsoleOut0.rtc
 rtcryo /https:localhost:2809/call -o sys.rtsys

プロキシサーバーの設定

プロキシサーバーを設定するには、ORBhttpProxyORBhttpProxyUsernameORBhttpProxyPasswordオプションを設定します。

 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:https:///call -ORBhttpProxy http://localhost:3128 -ORBhttpProxyUsername username -ORBhttpProxyPassword pass

corba.jsのビルドと動作確認

corba.jsはTypeScript用のCORBA実装(ORB、IDLコンパイラ)です。

現状、corba.jsはomniORBのWebsocket通信には対応していないため、当面の間はこちらで修正を加えたもので動作を確認します。

まず、node.js、npmをインストールしてください。

Ubuntu環境では以下のコマンドでインストールしてください。

 sudo apt-get install nodejs nodejs-dev node-gyp libssl1.0-dev npm
 sudo npm install -g n
 sudo n latest

現状、Linux環境でないとIDLコンパイルが実行できないようなので、corba.jsはUbuntu環境でビルドしてください。

 git clone https://github.com/Nobu19800/corba.js
 cd corba.js
 npm install
 npm run build

これ以降の作業はWindowsでも実行できます。 まず、OpenRTM-aistのテスト用のプログラム(openrtm_corbajs_test)を作成したので、これをビルドします。

 cd ..
 git clone https://github.com/Nobu19800/openrtm_corbajs_test
 cd openrtm_corbajs_test
 npm install

この時点でnode_modulesフォルダにcorba.jsも含む依存ライブラリが一式インストールされていますが、corba.jsは先ほどビルドしたものを使用するため、インストールしたcorba.jsは削除して差し替えた後にビルドします。

 rm -rf node_modules/corba.js
 cp -r ../corba.js/ node_modules/
 npm run build

Webブラウザで実行する場合

Webブラウザ上で実行する場合とnode.jsで実行する場合についてソースコードの修正が必要です。 なにも修正しない場合ブラウザで操作する形式でビルドしています。

事前準備として、Websocket通信のエンドポイントでネームサーバーとConsoleOutコンポーネントを起動してください。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%/2.0.0/ext/rtc.names.ws.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.ws.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

動作確認のためにはopenrtm_corbajs_test付属のindex.htmlをWebブラウザで開きます。

corbajstest1.png

ここでネームサーバーのアドレスとバインディング名を指定してexitボタンを押すとConsoleOutコンポーネントが終了します。

rollup.jsについて

Webブラウザ環境に対応したスクリプト生成のためにrollup.jsというツールを使用しています。Rollup、rollup.jsは複数のJavascriptファイルを一つのモジュールにするJavaScript 用のバンドラーです。

この設定のためにrollup.config.jsを作成しています。

node.js環境で実行する場合

node.jsで実行する場合、ネームサーバーのエンドポイントにlocalhostと設定すると正常に動作せず、ネームサーバーのエンドポイントに127.0.0.1のように直接IPアドレスを指定してcorba.js側でも127.0.0.1へアクセスする必要があります。

 corba.args:-ORBserverTransportRule "* http" -ORBclientTransportRule "* http" -ORBendPoint giop:http:ws://127.0.0.1:2809/ws

この変更後にネームサーバーを起動してください。

src/openrtmTest.tsを編集します。 以下の2行の1行目のコメントアウトを解除して、2行目をコメントアウトしてください。

 import { WsProtocol } from "corba.js/net/ws"
 //import { WsProtocol } from "corba.js/net/browser"

そして、以下の2行についても同様の変更をしてください。

 let print = console.log
 //let print = alert

この後、再度ビルドしてサンプルプログラムを実行します。

 npm run build
 node lib/openrtmTestMain.js

サンプルプログラム概要

サンプルプログラムのopenrtmTest.tsの概要について説明します。

まず最初にcorba.jsやRTCのスタブ、スケルトンファイルを読み込んでいます。

 import { ORB, GIOPDecoder } from 'corba.js'
 import { NamingContextExtStub } from 'corba.js'
 //import { WsProtocol } from "corba.js/net/ws"
 import { WsProtocol } from "corba.js/net/browser"
 import * as skel from "./example_echo_skel.js"
 import * as stub from "./example_echo_stub.js"
 import * as RTC_skel from "./RTC_skel.js"
 import * as RTC_stub from "./RTC_stub.js"
 import * as RTC_interface from "./RTC.js"
 import * as RTC_value from "./RTC_value.js"
 import * as RTC_valuetype from "./RTC_valuetype.js"

Webブラウザから実行しているのはexit_component関数です。

最初にスタブクラスを登録しています。実際に使用しているのは以下のRTObjectクラスだけです。

    orb.registerStubClass(RTC_stub.RTC.RTObject)

使用する通信プロトコルとしてWebSocketを追加しています。node.jsからの実行であればWebSocket over SSL/TLS通信も追加可能です。

    orb.addProtocol(new WsProtocol())

アドレスを指定してネームサーバーのオブジェクトリファレンスを取得します。

    await orb.stringToObject(address+"#NameService").then(
      (nameobject: any) => {
        let rootContext = NamingContextExtStub.narrow(nameobject)

RTCのバインディング名を指定してRTCのオブジェクトリファレンスを取得しています。 この辺の記述方法はcorba.jsの対応状況で変わる可能性があります。

        rootContext.resolve_str(rtcpath).then(
          (reference: any) => {
            orb.getConnection(reference.host, reference.port, reference.pathname).then(
              (objectConnection: any) => {
                let rtc = new RTC_stub.RTC.RTObject(objectConnection.orb, reference.objectKey, objectConnection);

RTCのオブジェクトリファレンスからexitメソッドを呼び出して終了処理を実行します。 戻り値で終了処理の成功失敗を判定しています。

                rtc.exit().then(
                  (ret: RTC_interface.RTC.ReturnCode_t) => {
                  if(ret === RTC_interface.RTC.ReturnCode_t.RTC_OK)
                  {
                    print("RTC termination process has completed successfully.")
                  }
                  else
                  {
                    print("error code:"+ret)
                  }

課題

今のところ、corba.jsの一部機能の不足や言語使用の制限などで実行できないことがいくつかあります。

  • Typescriptは多重継承をサポートしない
  • corba.jsのIDLコンパイラは他のIDLファイルのインクルードについて未対応
  • corba.jsがany型に非対応

これらの問題からOMG RTC仕様のIDLファイルはIDLコンパイルできなかったため、サンプルプログラム付属のTypeScriptソースファイルは多重継承やany型を削除したIDLファイルをIDLコンパイル後に修正しています。 一応、多重継承の問題とインクルードの問題は修正を加えることで対応可能ですが、any型についてはシリアライズ、デシリアライズ処理の変更が必要ですが、openrtm_corbajs_test付属のファイルでは対応できていません。

RTC_value.tsの以下の部分でNameValueのシリアライズ、デシリアライズについて記述があるので、ここに修正することで対応してください。

    export interface NameValue {
        name: string
        value: any
    }
    export function initNameValue(object: NameValue, init?: Partial<NameValue> | GIOPDecoder) {
        if (init instanceof GIOPDecoder) {
            const decoder = init
            object.name = decoder.string()
            object.name = decoder.any()
        } else {
            object.name = (init === undefined || init.name === undefined) ? "" : init.name
        }
    }
    export function encodeNameValue(encoder: GIOPEncoder, obj: NameValue) {
        encoder.string(obj.name)
        encoder.any(obj.name)
    }

any型などのCORBAの仕様については以下のページが参考になります。

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、HTTPTransportの簡単な動作確認用の設定ファイルがインストールされます。

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\bin\vc16\openrtmNames.exe -f %RTM_ROOT%\ext\rtc.names.http.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\http\rtc.http.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -f ${OPENRTM_INSTALL_DIR}/etc/rtc.names.http.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh 
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/http/rtc.http.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\bin\vc16\openrtmNames.exe -f %RTM_ROOT%\ext\rtc.names.https.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\http\rtc.https.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -f ${OPENRTM_INSTALL_DIR}/etc/rtc.names.https.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh 
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/http/rtc.https.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\bin\vc16\openrtmNames.exe -f %RTM_ROOT%\ext\rtc.names.ws.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\http\rtc.ws.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -f ${OPENRTM_INSTALL_DIR}/etc/rtc.names.ws.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh 
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/http/rtc.ws.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\bin\vc16\openrtmNames.exe -f %RTM_ROOT%\ext\rtc.names.wss.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\http\rtc.wss.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -f ${OPENRTM_INSTALL_DIR}/etc/rtc.names.wss.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh 
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/wss/rtc.http.conf

SSLTransportの使用方法

概要

オブジェクトのCORBA Security Service仕様のセキュリティ機能を一部使用可能になっています。 CORBA Security Serviceではセキュリティポリシーのモデル、認証、アクセス制御、メッセージ保護、委譲、監査、否認不可の機能を定義していますが、omniORBではGIOPメッセージをSSL/TLSによるサーバー・クライアント認証と暗号化で保護するSSLIOP通信をサポートしています。 このページではOpenRTM-aistでomniORBのSSLIOP通信を使用する手順を説明します。

C++

Windows

OpenRTM-aistのビルドとインストール

まず、OpenSSLのヘッダーファイル、ライブラリを適当な場所に展開してください。

OpenRTM-aist+omniORBを以下の手順でビルド、インストールします。

ただし、CMake実行時にSSL_ENABLEOPENSSL_ROOT_DIRのオプションを設定する必要があります。

設定項目 内容 設定例
SSL_ENABLE SSLTransportプラグインの生成の有無 ON
OPENSSL_ROOT_DIR OpenSSLの各種ファイルを配置したパス C:/work/OpenSSL/x64

また、CMake実行時にOpenRTM-aistのインストールフォルダは指定してそこにインストールするようにしてください。

 set OPENRTM_INSTALL_DIR=C:/work/openrtm_install
 set OMNIORB_SOURCE_DIR=C:/workspace/omniORB-4.2.5-x64-vc14-py310
 set OPENSSL_ROOT_DIR=C:/work/OpenSSL/x64
 cmake .. -DORB_ROOT=%OMNIORB_SOURCE_DIR% -DSSL_ENABLE=ON -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT_DIR% -DCMAKE_INSTALL_PREFIX=%OPENRTM_INSTALL_DIR%
 cmake --build . --config Release
 cmake --build . --config Release --target install

Ubuntu

OpenRTM-aistのビルドとインストール

OpenSSLのヘッダとライブラリをインストールします。

 sudo apt install libssl-dev

OpenRTM-aist+omniORBを以下の手順でビルド、インストールします。

ただし、SSL_ENABLEのオプションを設定する必要があります。

設定項目 内容 設定例
SSL_ENABLE SSLTransportプラグインの生成の有無 ON

 set OPENRTM_INSTALL_DIR=~/work/openrtm_install
 cmake .. -DSSL_ENABLE=ON -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

Python

OpenRTM-aistのビルドとインストール

以下の手順でOpenRTM-aist Python版をインストールしてださい。

ただし、動作確認でOpenRTM-aist C++版付属のネームサーバーを使用するため、C++版のビルドも実行してください。

動作確認

ネームサーバー起動

SSLTransportの動作確認のためにはネームサーバーがSSLIOP通信に対応している必要があります。 OpenRTM-aist付属のopenrtmNamesを起動します。

以下のコマンドを実行してください。パスは確認して変更してください。

 %OPENRTM_INSTALL_DIR%\2.0.0\bin\vc16\openrtmNames.exe -f %OPENRTM_INSTALL_DIR%\2.0.0\ext\rtc.names.ssl.conf

 $OPENRTM_INSTALL_DIR/bin/openrtmNames -f $OPENRTM_INSTALL_DIR/etc/rtc.names.ssl.conf

rtc.names.ssl.confでは生成済みのルート証明書root.crtと秘密鍵とサーバー証明書を連結したファイルserver.pemを使用するため、動作確認に使用するRTCもこれらの証明書ファイルを使います。 実際にシステムを開発する際は証明書と秘密鍵を変更してください。

RTC起動

以下のようなrtc.confを作成します。OpenRTM-aistをインストールしたパスは適宜変更してください。

C++では以下のファイルを作成します。

 manager.modules.load_path: C:/work/openrtm_install/2.0.0/ext/ssl
 manager.preload.modules: SSLTransport.dll
 
 corba.ssl.certificate_authority_file:C:/work/openrtm_install/2.0.0/ext/ssl/root.crt
 corba.ssl.key_file:C:/work/openrtm_install/2.0.0/ext/ssl/server.pem
 corba.ssl.key_file_password:password
 corba.args:-ORBserverTransportRule "* ssl" -ORBclientTransportRule "* ssl" -ORBendPoint giop:ssl::
 corba.nameservers: corbaloc:ssliop:localhost:2809
 corba.master_manager: giop:ssl:localhost:2810

Pythonでは以下のファイルを作成します。

 manager.modules.load_path: C:/Python37/Lib/site-packages/OpenRTM_aist/ext/vc16/ssl
 manager.preload.modules: SSLTransport.py
 
 corba.ssl.certificate_authority_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/root.crt
 corba.ssl.key_file:C:/Python37/Lib/site-packages/OpenRTM_aist/ext/ssl/server.pem
 corba.ssl.key_file_password:password
 corba.args:-ORBserverTransportRule "* ssl" -ORBclientTransportRule "* ssl" -ORBendPoint giop:ssl::
 corba.nameservers: corbaloc:ssliop:localhost:2809
 corba.master_manager: giop:ssl:localhost:2810

各設定項目の内容は以下のようになっています。

項目名 説明
corba.ssl.certificate_authority_file ルート証明書
corba.ssl.key_file 秘密鍵+サーバー証明書兼クライアント証明書の連結ファイル
corba.ssl.key_file_password 秘密鍵のパスフレーズ
corba.args CORBAライブラリの初期化関数に渡す引数。ここでSSLIOP通信のエンドポイントを設定する必要がある。
corba.nameservers ネームサーバーのアドレス。ここでSSLIOP通信でネームサーバーに接続するように設定する。
corba.master_manager マスターマネージャのエンドポイント。マスターマネージャの場合は自身のエンドポイントを設定し、スレーブマネージャの場合は接続先のマスターマネージャのアドレスを設定する。

このrtc.confを指定してConsoleIn、ConsoleOutのRTCを起動します。

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleInComp.exe -f rtc.conf

 %OPENRTM_INSTALL_DIR%\2.0.0\Components\C++\Examples\vc16\ConsoleOutComp.exe -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f rtc.conf

 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleInComp -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleIn.py -f rtc.conf

 python %OpenRTMPython_INSTALL_DIR%\Lib\site-packages\ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleOut.py -f rtc.conf

 python3 ${OpenRTMPython_INSTALL_DIR}/share/openrtm-2.0/components/python3/SimpleIO/ConsoleIn.py -f rtc.conf

これでネームサーバーに登録されますが、RTシステムエディタにSSLIOP通信機能はないため、OpenRTM-aistの機能かrtshellによりポートの接続やRTCのアクティブ化を実行する必要があります。

マネージャ起動時のポート接続、RTCのアクティブ化

rtc.confのmanager.components.preconnectmanager.components.preactivationでrtcname形式、rtcloc形式を指定することでポートの接続、RTCのアクティブ化ができます。 SSLIOP通信の場合は以下のようにプロトコルにssliopを指定することで使用可能になります。

 manager.components.preconnect: ConsoleIn0.out?port=rtcname.ssliop://localhost:2809/*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcname.ssliop://localhost:2809/*/ConsoleOut0

 naming.type: corba, manager
 manager.components.preconnect: ConsoleIn0.out?port=rtcloc.ssliop://localhost:2810/*/ConsoleOut0.in
 manager.components.preactivation: ConsoleIn0, rtcloc.ssliop://localhost:2810/*/ConsoleOut0

rtshellによる操作

まず、現在インストールされるrtshellでは対応していないため、最新版のrtctree、rtshell、rtsprofileが必要です。

rtshellでSSLIOP通信機能を使用するためには以下の環境変数を設定する必要があります。

環境変数名 設定例 意味
RTCTREE_SSL_ENABLE YES YES:rtctreeでSSLIOP通信機能を有効にする。
RTCTREE_NAMESERVERS ssliop:localhost:2809 接続するネームサーバー
ORBsslCAFile root.crt ルート証明書
ORBsslKeyFile server.pem 秘密鍵+サーバー証明書兼クライアント証明書の連結ファイル
ORBsslKeyPassword password 秘密鍵のパスフレーズ
ORBserverTransportRule "* ssl" サーバー側の通信プロトコル選択のルール
ORBclientTransportRule "* ssl" クライアント側の通信プロトコル選択のルール
ORBendPoint giop:ssl:: omniORBのエンドポイント

 set RTCTREE_SSL_ENABLE=YES
 set ORBsslCAFile=%RTM_ROOT%/ext/ssl/root.crt
 set ORBsslKeyFile=%RTM_ROOT%/ext/ssl/server.pem
 set ORBsslKeyPassword=password
 set RTCTREE_NAMESERVERS=ssliop:localhost:2809
 set ORBserverTransportRule=* ssl
 set ORBclientTransportRule=* ssl
 set ORBendPoint=giop:ssl::

以下のように接続するネームサーバーのアドレスの前にssliop:を付けることでSSLIOP通信でネームサーバーに接続できるようになります。

 rtcon /ssliop:localhost:2809/test.host_cxt/ConsoleIn0.rtc:out /ssliop:localhost:2809/test.host_cxt/ConsoleOut0.rtc:in
 rtact /ssliop:localhost:2809/test.host_cxt/ConsoleIn0.rtc /ssliop:localhost:2809/test.host_cxt/ConsoleOut0.rtc
 rtdeact /ssliop:localhost:2809/test.host_cxt/ConsoleIn0.rtc /ssliop:localhost:2809/test.host_cxt/ConsoleOut0.rtc
 rtexit /ssliop:localhost:2809/test.host_cxt/ConsoleOut0.rtc
 rtcryo ssliop:localhost:2809 -o sys.rtsys

秘密鍵、証明書の生成

まずは秘密鍵、証明書の生成が必要です。

証明書にはルート証明書、中間証明書、サーバー証明書、クライアント証明書があります。 以下はサーバー証明書によるサーバー認証を行う場合の概要図です。

ssl1.png

通信するサーバー、クライアントPC以外に公開鍵証明書認証局(CA、Certificate Authority)が必要です。 認証局はルート証明書と対応する秘密鍵(秘密鍵1)を持っています。 サーバーは秘密鍵を生成後、生成した秘密鍵(秘密鍵a)でCSR(Certificate Signing Request:公開鍵情報、ウェブサイトの所有者情報)を認証局に送信します。 認証局はCSRに秘密鍵1で署名したサーバー証明書を発行します。 サーバーとクライアントのSSL/TLS通信のハンドシェイク処理でサーバー証明書を送信します。この時に他にも鍵交換アルゴリズムの処理などもありますが説明は省略します。 クライアントは予め入手しておいたルート証明書の公開鍵でサーバー証明書の署名の検証を行い、証明書の検証が完了したら暗号化通信(秘密鍵aで符号化、サーバー証明書の公開鍵で復号)を開始します。

この他に中間認証局がルート認証局から中間証明書を取得し、中間認証局がサーバー証明書を発行する場合があります。 説明は以下のサイトの図が分かりやすいので参考になると思います。

ここまでの説明ではクライアント側がサーバーの認証をしていましたが、サーバーがクライアントの認証をする場合があります。 omniORBでは引数`-ORBsslVerifyMode`や環境変数`ORBsslVerifyMode`で以下のパラメータを設定することで認証方法を変更可能です。

パラメータ 意味
none サーバー証明書の検証に失敗してもハンドシェイクを継続する。クライアント証明書の要求は実行しない。
peer(デフォルト値) サーバーがクライアント証明書を要求する。サーバー認証、クライアント認証(クライアント証明書が送信されてきた場合)で失敗したらハンドシェイクを終了する。
peer, fail クライアント証明書が送信されなかったらハンドシェイクを終了する。
peer, once クライアント認証を最初のハンドシェイクでのみ実行する。
peer, fail, once 上記の組み合わせ。

omniORBはサーバー証明書、クライアント証明書のルート証明書ファイルを個別に指定できないため、どちらも`corba.ssl.certificate_authority_file`オプションで指定してください。

まとめると、OpenRTM-aistのSSL/TLS通信にはルート証明書、サーバー証明書、クライアント証明書、中間証明書、秘密鍵を以下のように配置する必要があります。

ssl2.png

以降ではOpenSSLのコマンドを使って自己認証局と自己署名証明書(いわゆるオレオレ証明書)を作成してみます。 cnfファイルは上記のリンク先のサイトのものを使用します。

まず適当な作業フォルダにroot、inter、serverフォルダを作成します。

ルート認証局の秘密鍵、ルート証明書を作成します。

 mkdir root
 cd root
 mkdir newcerts
 type nul > index.txt
 echo 01 > serial
 echo 00 > crlnumberl
 openssl genrsa -out RootCA_key.pem -passout pass:rootpass 2048
 openssl req -new -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=EXAMPLE Root CA" -out RootCA_csr.pem  -key RootCA_key.pem  -passin pass:rootpass -config ../conf/openssl_sign.cnf
 openssl ca  -batch -extensions v3_ca -out RootCA_crt.pem -in RootCA_csr.pem -selfsign -keyfile RootCA_key.pem -passin pass:rootpass -config ../conf/openssl_sign.cnf
 openssl x509 -in RootCA_crt.pem -out RootCA_crt.pem
 cd ..

次に中間認証局の秘密鍵、中間証明書のCSRを作成します。

 mkdir inter
 cd inter
 mkdir newcerts
 type nul > index.txt
 echo 01 > serial
 echo 00 > crlnumberl
 openssl genrsa -out InterCA_key.pem -passout pass:interpass 2048
 openssl req -new -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=EXAMPLE Intermediate CA" -out InterCA_csr.pem -key InterCA_key.pem -passin pass:interpass -config ../conf/openssl_sign.cnf
 cd ..

ルート認証局で中間証明書を発行します。

 cd root
 openssl ca -batch -extensions v3_ca -out ..\inter\InterCA_crt.pem -in  ..\inter\InterCA_csr.pem -cert RootCA_crt.pem -keyfile RootCA_key.pem -passin pass:interpass -config ../conf/openssl_sign.cnf
 cd ..

サーバーで秘密鍵とサーバー証明書のCSRを作成します。

 mkdir server
 cd server
 mkdir newcerts
 type nul > index.txt
 echo 01 > serial
 echo 00 > crlnumberl
 openssl genrsa -out Server_key.pem -passout pass:serverpass 2048
 openssl req -new -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=EXAMPLE Server" -out Server_csr.pem -key Server_key.pem -passin pass:serverpass -config ../conf/openssl_sign.cnf
 cd ..

中間認証局でサーバー証明書を発行します。

 cd inter
 openssl x509 -req -in ..\server\Server_csr.pem -sha256 -CA InterCA_crt.pem -CAkey InterCA_key.pem -set_serial 01 -days 730 -out ..\server\Server_crt.pem -passin pass:serverpass
 cd ..

秘密鍵、サーバー証明書、中間証明書を連結します。

 cd server
 openssl x509 -in Server_crt.pem -out Server_crt.pem
 openssl x509 -in ..\inter\InterCA_crt.pem -out InterCA_crt.pem
 copy /b Server_key.pem + Server_crt.pem + InterCA_crt.pem server.pem

今回使用するのは連結したファイル(server.pem)とルート証明書(RootCA_crt.pem)です。

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、SSLTransportの簡単な動作確認用の設定ファイルがインストールされます。

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\bin\vc16\openrtmNames.exe -f %RTM_ROOT%\ext\rtc.names.ssl.conf

 %RTM_ROOT%\ext\environment-setup.omniorb.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\ssl\rtc.ssl.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -f ${OPENRTM_INSTALL_DIR}/etc/rtc.names.ssl.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh 
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/ssl/rtc.ssl.conf

LogicalTimeTriggeredECの使用方法

FSMコンポーネント作成手順

RTCBuilderでのコード生成

まずは通常のRTC作成手順と同じくプロジェクトの作成、モジュール名の設定、言語の設定(C++)を行います。

次にFSMタブからFSMのチェックボックスをオンにします。 さらに新規作成ボタンを押してGUIエディタを起動します。

fsm1.png

起動したエディタで右クリックしてAdd nodeを選択する。

fsm2.png

作成したノードを右クリックしてEdit nodeを選択します。

fsm3.png

State Nameを適当な名前に変更します。

fsm4.png

同様の手順でノードを複数作成します。 以下の図ではToggle Initial、Toggle finalを設定しているノードがありますが、この設定により生成するコードは変化しないようです。

fsm8.png

一部のノードはOn EntryOn Exitをオンにしてください。

fsm7.png

またノードからノードへドラッグアンドドロップすることで状態遷移を定義します。

fsm8-2.png

エディタを閉じます。

fsm10.png

その後、コード生成を行います。

fsm11.png

RTCのビルド

ビルドにはOpenRTM-aist 2.0が必要です。 以下の手順でOpenRTM-aistでビルドしてください。

その後、INSTALLのプロジェクトをビルドして適当な場所にインストールしてください。 インストールする場所を変更するためにはCMAKE_INSTALL_PREFIXのオプションを変更します。

RTCのコードを生成したフォルダで以下のコマンドを実行します。

 mkdir build
 cd build
 set OPENRTM_DIR={OpenRTM-aistをインストールしたディレクトリ}\2.0.0\cmake cmake -G "Visual Studio 15 2017" -A x64 ..
 cmake --build . --config Release

コードの編集

執筆中

動作確認手順

コネクタ生成時、データ転送時にコールバック関数が呼ばれる順序について

多階層複合コンポーネントの利用方法

OpenHRPExecutionContextの使用方法

ExtTrigExecutionContextの使用方法

SimulatorExecutionContextの使用方法

独自ロガーの実装方法

OpenRTM-aistはFluent Bitプラグインのように、OpenRTM-aistデフォルトのロガー以外のロギング機能を拡張することができます。

このページでは独自ロガーの作成方法、使用手順を説明します。

今回作成したソースコードは以下から入手できます。

独自ロガーの作成方法

C++

独自ロガー作成

C++の場合はビルドのためのCMakeLists.txtを用意してください。今回はTestLoggerという名前で作成します。

 cmake_minimum_required(VERSION 3.1)
 
 set(target TestLogger)
 project(${target} CXX)
 
 find_package(OpenRTM REQUIRED)
 
 
 
 add_definitions(${OPENRTM_CFLAGS})
 link_directories(${OPENRTM_LIBRARY_DIRS})
 
 add_library(${target} SHARED ${target}.cpp ${target}.h)
 target_link_libraries(${target} ${OPENRTM_LIBRARIES})
 target_include_directories(${target} SYSTEM PRIVATE ${OPENRTM_INCLUDE_DIRS})
 set_target_properties(${target} PROPERTIES PREFIX "")

ヘッダーファイル(TestLogger.h)、ソースファイル(TestLogger.cpp)を用意します。 coil::LogStreamBufferクラスを継承したTestLoggerStreamクラス、RTC::LogstreamBaseクラスを継承したTestLoggerクラスを実装します。 TestLoggerStreamはロギングの処理を実装するクラスで、TestLoggerはTestLoggerStreamを生成して外部から取得可能にするクラスです。

 #ifndef TESTLOGGER_H
 #define TESTLOGGER_H
 
 
 #include <rtm/LogstreamBase.h>
 
 
 class TestLoggerStream
  : public coil::LogStreamBuffer
 {
 public:
   TestLoggerStream();
   ~TestLoggerStream() override;
   bool init(const coil::Properties& prop);
    void write(int level, const std::string& name, const std::string& date, const std::string& mes) override;
 private:
   std::string header;
 };
 
 class TestLogger
  : public RTC::LogstreamBase
 {
 public:
   TestLogger();
   ~TestLogger() override;
   bool init(const coil::Properties& prop) override;
   coil::LogStreamBuffer* getStreamBuffer() override;
 private:
   TestLoggerStream m_logstream;
 };
 
 extern "C"
 {
   void DLL_EXPORT TestLoggerInit();
 }
 
 #endif

 #include "TestLogger.h"
 #include <iostream>
 
 
 TestLoggerStream::TestLoggerStream()
 {
 }
 
 TestLoggerStream::~TestLoggerStream()
 {
 }
 
 bool TestLoggerStream::init(const coil::Properties& prop)
 {
   header = prop["header"];
   return true;
 }
 
 void TestLoggerStream::write(int level, const std::string& name, const std::string& date, const std::string& mes)
 {
   std::cout << header << ":" << mes << std::endl;
 }
 
 
 TestLogger::TestLogger()
 {
 }
 
 TestLogger::~TestLogger()
 {
 }
 
 bool TestLogger::init(const coil::Properties& prop)
 {
   m_logstream.init(prop);
   return true;
 }
 
 coil::LogStreamBuffer* TestLogger::getStreamBuffer()
 {
   return &m_logstream;
 }
 
 
 extern "C"
 {
   void TestLoggerInit()
   {
     ::RTC::LogstreamFactory::
       instance().addFactory("testlogger",
                            ::coil::Creator< ::RTC::LogstreamBase,
                                             TestLogger>,
                            ::coil::Destructor< ::RTC::LogstreamBase,
                                                TestLogger>);
   }
 }

TestLoggerクラスのinit関数で初期化、getStreamBuffer関数でLogStreamBufferオブジェクトを取得することができます。 TestLoggerクラスは特に理由が無ければ変更の必要はないです。

TestLoggerStreamクラスのwrite関数でログの出力を行います。 この例では、プロパティのheaderオプションに設定した文字列をログメッセージの先頭に追加して標準出力しています。

TestLoggerInit関数は動的ライブラリをロードする時に呼び出す関数です。〇〇.dllであれば〇〇Initというように、初期化関数は動的ライブラリの名前+Initにしてください。 TestLoggerInit関数内でLogstreamFactoryのaddFactory関数を呼ぶことでロガーを追加できます。

動作確認

ビルドしてTestLogger.dll、TestLogger.soを生成後に動作確認を行います。

以下のrtc.confを作成してください。

 logger.enable: YES
 logger.log_level: VERBOSE
 
 logger.plugins: TestLogger.dll
 
 logger.logstream.testlogger.enable: ON
 logger.logstream.testlogger.header: example

まずlogger.pluginsオプションを設定してTestLoggerをロードするようにします。 ただロードするだけでは有効にはならないため、logger.logstream.testlogger.enableオプションを設定します。

※OpenRTM-aistの動作としてはlogger.logstream.${モジュール名}以下のオプションが設定されている場合にロガーが有効になるため、必ずしもenableオプションである必要はありません。

logger.logstream.testlogger.headerオプションでログメッセージの先頭に追加する文字列を指定しています。

このrtc.confを指定してRTCを起動するとログが標準出力されることが確認できます。

Python

Pythonファイル(TestLogger.py)を用意します。 OpenRTM_aist.LogstreamBaseを継承したTestLoggerクラスを実装します。

 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 
 import OpenRTM_aist
 
 
 class TestLogger(OpenRTM_aist.LogstreamBase):
 
    def __init__(self):
        OpenRTM_aist.LogstreamBase.__init__(self)
        self._header = ""
 
    def __del__(self):
        pass
 
    def init(self, prop):
        self._header = prop.getProperty("header")
        return True
 
    def log(self, msg, level, name):
        print(self._header+":"+msg)
        return True
 
    def setLogLevel(self, level):
        pass
 
    def shutdown(self):
        return True
 
 
 def TestLoggerInit(mgr):
    OpenRTM_aist.LogstreamFactory.instance().addFactory("testlogger",
                                                        TestLogger)

TestLoggerクラスのinit関数で初期化、log関数でログの出力、setLogLevel関数でログレベルの設定、shutdown関数で終了処理を行います。 この例では、プロパティのheaderオプションに設定した文字列をログメッセージの先頭に追加して標準出力しています。

TestLoggerInit関数はPythonモジュールをロードする時に呼び出す関数です。〇〇.pyであれば〇〇Initというように、初期化関数はPythonファイルの名前+Initにしてください。 TestLoggerInit関数内でLogstreamFactoryのaddFactory関数を呼ぶことでロガーを追加できます。

動作確認

以下のrtc.confを作成してください。

 logger.enable: YES
 logger.log_level: VERBOSE
 
 logger.plugins: TestLogger.py
 
 logger.logstream.testlogger.enable: ON
 logger.logstream.testlogger.header: example

まずlogger.pluginsオプションを設定してTestLoggerをロードするようにします。 ただロードするだけでは有効にはならないため、logger.logstream.testlogger.enableオプションを設定します。

logger.logstream.testlogger.headerオプションでログメッセージの先頭に追加する文字列を指定しています。

このrtc.confを指定してRTCを起動するとログが標準出力されることが確認できます。

CSPポートの使用方法

コンポーネントアクションのコールバック関数の利用

マネージャアクションのコールバック関数の利用

独自シリアライザの実装手順

OpenRTM-aistのデータポートでは以下のようにデータをバイト列に変換するシリアライザ、データを送信する通信インターフェースの種類については複数の実装から選択可能です。

sirializer1-1.png

インターフェース型が選択可能のためRTC同士だけではなく、ROSのノード、あるいはROS2のようにDDSにより通信を行うプロセスとデータのやり取りが可能になります。 またシリアライザが選択可能のため、図のようにTimedLong型をTimedLong型のような別のデータ型に変換して様々なデータ型のポートと柔軟に接続することができます。

現在はC++版、Python版で使用可能です。

以下に独自シリアライザの作成手順を記載します。

独自シリアライザの実装手順(C++)

OpenRTM-aistのインストール

OpenRTM-aist 2.0以上が必要なため、以下の手順でソースコードからビルドを行う必要がある。

ビルド終了後、特定の場所にインストールする。

cmake-guiでCMAKE_INSTALL_PREFIXを設定するか、cmake実行時のコマンドで設定する。

 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc141 -G "Visual Studio 16 2019" -A x64 .. -DCMAKE_INSTALL_PREFIX=C:/workspace/openrtm_install

ビルド後に、以下のコマンドでインストールする。

 cmake --build .. --target INSTALL --config Release

Visual Studio上でINSTALLのプロジェクトをビルドしてもインストールできる。

独自シリアライザの作成

独自シリアライザの実装には以下のファイルを作成する必要がある。

  • C++ソースファイル(今回はTestSerializer.cppとする)
  • CMakeLists.txt

CMakeLists.txtの作成

CMakeLists.txtにはOpenRTM-aistのパッケージの検出、動的ライブラリを生成するようにコマンドを記述します。

 cmake_minimum_required (VERSION 3.0.2)
 
 project (TestSerializer
     VERSION 1.0
     LANGUAGES CXX)

 
 #OpenRTM-aistの検出
 find_package(OpenRTM REQUIRED)
 
 #インクルードディレクトリ、リンクディレクトリ、コンパイル時のフラグの設定
 include_directories(${PROJECT_BINARY_DIR})
 include_directories(${PROJECT_BINARY_DIR}/idl)
 include_directories(${OPENRTM_INCLUDE_DIRS})
 add_definitions(${OPENRTM_CFLAGS})
 
 link_directories(${OPENRTM_LIBRARY_DIRS})
 
 #動的リンクライブラリの生成
 add_library(${PROJECT_NAME} SHARED TestSerializer.cpp)
 #生成するライブラリ名をTestSerializer.dll(もしくは.so)に設定
 set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
 #OpenRTM-aistのライブラリとリンク
 target_link_libraries(${PROJECT_NAME} ${OPENRTM_LIBRARIES})

CPPファイルの作成

TestSerializer.cppを以下のように作成します。

 #include <rtm/ByteDataStreamBase.h>
 #include <rtm/idl/BasicDataTypeSkel.h>
 #include <coil/Factory.h>
 #include <rtm/Manager.h>
 
 //以下はシリアライザの実装
 template <class DataType>
 class TestSerializer : public RTC::ByteDataStream<DataType>
 {
 public:
     TestSerializer():m_buffer(NULL), m_length(0){};
 
     void writeData(const unsigned char* buffer, unsigned long length) override
     {
         delete m_buffer;
         m_buffer = new unsigned char[length];
         memcpy(m_buffer, buffer, length);
         m_length = length;
     }
     void readData(unsigned char* buffer, unsigned long length) const override
     {
         if (m_buffer)
         {
             memcpy(buffer, m_buffer, length);
         }
     }
     unsigned long getDataLength() const override
     {
         return m_length;
     }
     bool serialize(const DataType& data) override
     {
         delete m_buffer;
         m_buffer = new unsigned char[1];
         m_buffer[0] = static_cast<unsigned char>(data.data);
         m_length = 1;
         return true;
     }
     bool deserialize(DataType& data) override
    {
        if (m_buffer)
        {
            data.data = static_cast<long>(m_buffer[0])+1;
            return true;
        }
        return false;
    }
 private:
    unsigned char* m_buffer;
    unsigned long m_length;
 };
 
 extern "C"
 {
     //以下はモジュールロード時に呼び出される関数
     DLL_EXPORT void TestSerializerInit(RTC::Manager* manager)
     {
         //以下のファクトリはデータ型ごとに登録する必要がある
         RTC::addSerializer<RTC::TimedLong, TestSerializer<RTC::TimedLong>>("test");
     };
 }

シリアライザにはwriteData関数、readData関数、getDataLength関数、serialize関数、deserialize関数を実装する必要がある。 serialize関数はRTMのデータをunsigned char型に変換して内部のバッファに保存する。 保存したデータはreadData関数で取り出すことができる。 このため、データ送信時の処理は以下のようになっている。

sirializer2.png

writeData関数は内部のバッファにバイト列のデータを書き込む関数である。 deserialize関数は内部のバッファのデータをRTMのデータ型に変換して外部の変数に渡す。 このため、データ受信時の処理は以下のようになっている。

sirializer3.png

getDataLengthは内部で保持しているデータの長さを取得する関数である。

ビルド

OpenRTM-aistをソースコードからビルド、インストールした場合は環境変数が設定されていないためcmake実行時にOpenRTMConfig.cmakeの場所を指定する必要がある。

 cmake -G "Visual Studio 15 2017" -A x64 .. -DOpenRTM_DIR=C:/workspace/openrtm1/build/install/2.0.0/cmake

この後Visual Studio等でビルドを行う。

独自シリアライザの利用

上記の作業でTestSerializer.dllが生成されているはずのため、TestSerializer.dllをRTC実行時にロードして利用できるようにする。

rtc.confに以下のように記述することでロードできる。モジュール探索パスは適宜変更する。

 manager.modules.load_path: .
 manager.modules.preload: TestSerializer.dll

データポート接続時にmarshaling_typeのオプションでシリアライザを設定できる。

 manager.components.preconnect: ConsoleOut0.in?port=ConsoleIn0.out&marshaling_type=test

RT System Editorで設定する場合はdataport.marshaling_typeといパラメータで設定する。

sirializer4.png

これで独自シリアライザ(TestSerializer)が使用可能になったため、ConsoleInとConsoleOutで通信すると標準入力した数値に1を足した数値が表示される。

以下はConsoleInとConsoleOutのデータポートを接続してアクティベートするrtc.confの例。

 manager.modules.load_path: .
 manager.modules.preload: TestSerializer.dll, ConsoleOut.dll
 manager.components.precreate: ConsoleOut
 manager.components.preconnect: ConsoleOut0.in?port=ConsoleIn0.out&marshaling_type=test
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

独自シリアライザの実装手順(Java)

独自シリアライザの実装手順(Python)

OpenRTM-aistのインストール

OpenRTM-aist 2.0以上が必要なため、以下の手順でソースコードからビルドを行う必要がある。

独自シリアライザの作成

独自シリアライザの実装には以下のファイルを作成する必要がある。

  • Pythonソースファイル(今回はTestSerializer.pyとする)

Pythonファイルの作成

TestSerializer.pyを以下のように作成します。

 #!/usr/bin/env python
 # -*- coding: euc-jp -*-
 
 
 import OpenRTM_aist
 import RTC
 
 
 #以下はシリアライザの実装
 class TestSerializer(OpenRTM_aist.ByteDataStreamBase):
 
   def __init__(self):
     pass
 
 
   def __del__(self):
    pass
 
   def serialize(self, data):
     if data._NP_RepositoryId == RTC.TimedLong._NP_RepositoryId:
         bdata = str(data.data)
         return OpenRTM_aist.ByteDataStreamBase.SERIALIZE_OK, bdata
     else:
         return OpenRTM_aist.ByteDataStreamBase.SERIALIZE_ERROR, ""
 
 
 
   def deserialize(self, cdr, data_type):
     if data_type._NP_RepositoryId == RTC.TimedLong._NP_RepositoryId:
         data_type.data = int(cdr)+1
         return OpenRTM_aist.ByteDataStreamBase.SERIALIZE_OK, data_type
     else:
         return OpenRTM_aist.ByteDataStreamBase.SERIALIZE_ERROR, data_type
 
 
 #以下はモジュールロード時に呼び出される関数
 def TestSerializerInit(mgr):
   OpenRTM_aist.SerializerFactories.instance().addSerializer("test:RTC.TimedLong",  # addFactory関数の第1引数で登録名を設定。以下で独自シリアライザを利用するときはこの名前を使用する。
                                                              TestSerializer, RTC.TimedLong)
   #OpenRTM_aist.SerializerFactory.instance().addSerializerGlobal("test", #addSerializerGlobalを使うと特定のデータ型だけではなく、全てのデータ型でTestSerializerを使用可能にする
                                                       TestSerializer)

シリアライザにはserialize関数、deserialize関数を実装する必要がある。 serialize関数はRTMのデータをバイト列のデータ等に変換してリターンコードと変換後のデータを返す。

deserialize関数はバイト列のデータなどをRTMのデータに変換してリターンコードと変換後のデータを返す。

独自シリアライザの利用

TestSerializer.pyをRTC実行時にロードして利用できるようにする。

rtc.confに以下のように記述することでロードできる。モジュール探索パスは適宜変更する。

 manager.modules.load_path: .
 manager.modules.preload: TestSerializer.py

データポート接続時にmarshaling_typeのオプションでシリアライザを設定できる。

 manager.components.preconnect: ConsoleOut0.in?port=ConsoleIn0.out&marshaling_type=test

RT System Editorで設定する場合はdataport.marshaling_typeといパラメータで設定する。

/ja/node/6714

これで独自シリアライザ(TestSerializer)が使用可能になったため、ConsoleInとConsoleOutで通信すると標準入力した数値に1を足した数値が表示される。

以下はConsoleInとConsoleOutのデータポートを接続してアクティベートするrtc.confの例。

 manager.modules.load_path: .
 manager.modules.preload: TestSerializer.py, ConsoleOut.py
 manager.components.precreate: ConsoleOut
 manager.components.preconnect: ConsoleOut0.in?port=ConsoleIn0.out&marshaling_type=test
 manager.components.preactivation: ConsoleOut0, ConsoleIn0

独自シリアライザの実装手順(ROS、C++)

独自シリアライザの作成

CMakeLists.txtの作成

OpenRTM-aistのデータ型とROSのメッセージ型を変換するシリアライザの作成のためには、ROSTransport、ROSのヘッダーファイルのインクルード、ライブラリのリンクが必要になります。 以下のようにCMakeLists.txtでOpenRTM-aist、ROS、Boostを検出します。

 #OpenRTM-aistの検出
 find_package(OpenRTM 2.0 REQUIRED)
 find_package(ROSTransport REQUIRED)

 #ROSの検出
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(roscpp roscpp)
 
 if(NOT roscpp_FOUND)
     message(FATAL_ERROR "can not find roscpp.")
 endif()
 
 #Boostの検出
 find_package(Boost COMPONENTS chrono filesystem system)
 if(NOT Boost_FOUND)
     find_package(Boost REQUIRED COMPONENTS chrono filesystem signals system)
 endif()

以下のように動的リンクライブラリの生成、検出したライブラリのリンク、インクルードディレクトリの設定を行います。

 #インクルードディレクトリ、リンクディレクトリ、コンパイル時のフラグの設定
 include_directories(${OPENRTM_INCLUDE_DIRS})
 add_definitions(${OPENRTM_CFLAGS})
 
 link_directories(${OPENRTM_LIBRARY_DIRS})
 link_directories(${roscpp_LIBRARY_DIRS})
 
 #動的リンクライブラリの生成
 add_library(${PROJECT_NAME} SHARED TestRosSerializer.cpp)
 
 
 #生成するライブラリ名をTestRosSerializer.dll(もしくは.so)に設定
 set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
 
 #OpenRTM-aist、ROS、Boostのライブラリとリンク
 target_include_directories(${PROJECT_NAME} SYSTEM
        PRIVATE ${roscpp_INCLUDE_DIRS}
        PRIVATE ${Boost_INCLUDE_DIRS}
        PRIVATE ${ROSTRANSPORT_INCLUDE_DIRS})
 
 target_link_libraries(${PROJECT_NAME} ${OPENRTM_LIBRARIES} ${roscpp_LIBRARIES} ${Boost_LIBRARIES} ${ROSTRANSPORT_LIBRARIES})

CPPファイルの作成

ROS用シリアライザを作成する場合、CPPファイルでROSSerializer.hをインクルードします。 また、今回はROSのgeometry_msgs/TwistStamped型を使用するため、geometry_msgs/TwistStamped.hをインクルードします。このインクルードファイルは使用するメッセージ型により変更します。

 #include <rtm/ByteDataStreamBase.h>
 #include <rtm/idl/BasicDataTypeSkel.h>
 #include <rtm/idl/ExtendedDataTypesSkel.h>
 #include <coil/Factory.h>
 #include <rtm/Manager.h>
 #include <rtm/ext/ROSTransport/ROSSerializer.h>
 #include <geometry_msgs/TwistStamped.h>

ROSSerializerBaseクラスを継承したクラスを定義します。 ROSSerializerBaseクラスのテンプレート引数には使用するOpenRTM-aistのデータ型を指定します。今回はRTC::TimedVelocity3D型を使用するため、RTC::TimedVelocity3Dを指定します。

 class TestRosSerializer : public RTC::ROSSerializerBase<RTC::TimedVelocity3D>
 {
 public:
    TestRosSerializer(){};

以下のようにTestRosSerializerクラスのメンバ関数としてserialize関数を定義する。 serialize関数では、RTC::TimedVelocity3D型のデータをgeometry_msgs/TwistStamped型のデータに変換し、その後バイト列データに変換しています。

    bool serialize(const RTC::TimedVelocity3D& data) override
    {
        geometry_msgs::TwistStamped msg;
        msg.header.stamp.sec = data.tm.sec;
        msg.header.stamp.nsec = data.tm.nsec;
        msg.twist.linear.x = data.data.vx;
        msg.twist.linear.y = data.data.vy;
        msg.twist.linear.z = data.data.vz;
        msg.twist.angular.x = data.data.vr;
        msg.twist.angular.y = data.data.vp;
        msg.twist.angular.z = data.data.va;
 
        RTC::ROSSerializerBase<RTC::TimedVelocity3D>::m_message = ros::serialization::serializeMessage<geometry_msgs::TwistStamped>(msg);
        return true;
    }

次にdeserialize関数を定義します。 deserialize関数では、バイト列データをgeometry_msgs/TwistStamped型のデータに変換し、その後RTC::TimedVelocity3D型のデータに変換しています。

    bool deserialize(RTC::TimedVelocity3D& data) override
    {
        geometry_msgs::TwistStamped msg;
        ros::serialization::deserializeMessage(ROSSerializerBase<RTC::TimedVelocity3D>::m_message, msg);
        data.tm.sec = msg.header.stamp.sec;
        data.tm.nsec = msg.header.stamp.nsec;
        data.data.vx = msg.twist.linear.x;
        data.data.vy = msg.twist.linear.y;
        data.data.vz = msg.twist.linear.z;
        data.data.vr = msg.twist.angular.x;
        data.data.vp = msg.twist.angular.y;
        data.data.va = msg.twist.angular.z;
 
        return true;
    }

以下ように{ライブラリ名}Init関数を定義すると、動的リンクライブラリのロード時にこの関数が呼ばれます。 TestRosSerializerInit関数内でファクトリにシリアライザを追加することにより、RTC起動時に実装したシリアライザが使えるようにします。

 extern "C"
 {
    //以下はモジュールロード時に呼び出される関数
    DLL_EXPORT void TestRosSerializerInit(RTC::Manager* /*manager*/)
    {
        //シリアライザの登録
        RTC::addRosSerializer<RTC::TimedVelocity3D, geometry_msgs::TwistStamped, TestRosSerializer>("ros:geometry_msgs/TwistStamped");
    }
 }

動作確認

以下から作成済みのシリアライザ、動作確認用のRTCをダウンロードできます。

作成したTestRosSerializerをビルドしてください。 ビルド、実行時にはROSの環境変数が設定されている必要があるため、以下のコマンドを実行してください。

 source /opt/ros/noetic/setup.bash

rtc.confを作成します。 ROSTransport.soと、作成したシリアライザTestRosSerializer.soをロードするように設定します。 TestRosSerializer.soのパスは、ビルドしたディレクトリのパスに変更してください。

 manager.modules.load_path: /usr/lib/openrtm-2.0/transport/, ~/TestRosSerializer/build
 manager.modules.preload: ROSTransport.so, TestRosSerializer.so

以下のようにサンプルコンポーネントのtestVelocity3DInのInPort、testVelocity3DOutのOutPortでコネクションを生成します。

 manager.components.preconnect: testVelocity3DIn0.in?interface_type=ros&marshaling_type=ros:geometry_msgs/TwistStamped&ros.topic=chatter&ros.so_keepalive=NO&ros.node.name=testVelocity3DIn0, testVelocity3DOut0.out?interface_type=ros&marshaling_type=ros:geometry_msgs/TwistStamped&ros.topic=chatter&ros.node.name=testVelocity3DOut0

動作確認する場合は、testOpenRTMSerializerに含まれているtestVelocity3DIn、testVelocity3DOutのサンプルコンポーネントをビルドしてください。

以下のコマンド実行後、RTCをアクティブ化するとtestVelocity3DOutのPublisherからtestVelocity3DInのSubscriberにデータが送信されて、testVelocity3DInを起動した画面に数値が表示されます。

 testVelocity3DOutComp -f rtc.conf

 testVelocity3DInComp -f rtc.conf

今回の動作確認ではRTC同士でROSのトピック通信を実行しましたが、ROSノードと通信を確認する場合は、geometry_msgs/TwistStamped型のPublisher、Subscriberを持つROSノードを作成して試してください。

独自シリアライザの実装手順(ROS2、C++)

独自シリアライザの作成

CMakeLists.txtの作成

OpenRTM-aistのデータ型とROSのメッセージ型を変換するシリアライザの作成のためには、ROSTransport、ROS2のヘッダーファイルのインクルード、ライブラリのリンクが必要になります。 以下のようにCMakeLists.txtでOpenRTM-aist、ROS2、FastDDSを検出します。

 #OpenRTM-aistの検出
 find_package(OpenRTM 2.0 REQUIRED)
 find_package(ROS2Transport REQUIRED)
 
 #ROS2の検出
 find_package(rclcpp REQUIRED)
 find_package(std_msgs REQUIRED)
 find_package(geometry_msgs REQUIRED)
 find_package(sensor_msgs REQUIRED)
 
 #FastDDSの検出
 find_package(fastcdr REQUIRED)
 find_package(fastrtps REQUIRED)

以下のように動的リンクライブラリの生成、検出したライブラリのリンク、インクルードディレクトリの設定を行います。

 #インクルードディレクトリ、リンクディレクトリ、コンパイル時のフラグの設定
 include_directories(${OPENRTM_INCLUDE_DIRS})
 add_definitions(${OPENRTM_CFLAGS})
 
 link_directories(${OPENRTM_LIBRARY_DIRS})
 
 #動的リンクライブラリの生成
 add_library(${PROJECT_NAME} SHARED TestRos2Serializer.cpp)
 
 
 #生成するライブラリ名をTestRos2Serializer.dll(もしくは.so)に設定
 set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
 
 
 target_include_directories(${PROJECT_NAME} SYSTEM
         PUBLIC ${rclcpp_INCLUDE_DIRS}
         PUBLIC ${std_msgs_INCLUDE_DIRS}
         PUBLIC ${geometry_msgs_INCLUDE_DIRS}
         PUBLIC ${sensor_msgs_INCLUDE_DIRS}
         PUBLIC ${ROS2TRANSPORT_INCLUDE_DIRS})
 
 #OpenRTM-aistのライブラリとリンク
 target_link_libraries(${PROJECT_NAME} ${OPENRTM_LIBRARIES} ${ROS2TRANSPORT_LIBRARIES}
         ${rclcpp_LIBRARIES} ${std_msgs_LIBRARIES} ${geometry_msgs_LIBRARIES} ${sensor_msgs_LIBRARIES} 
         ${std_msgs_LIBRARIES__rosidl_typesupport_fastrtps_cpp} 
         ${geometry_msgs_LIBRARIES__rosidl_typesupport_fastrtps_cpp} 
         ${sensor_msgs_LIBRARIES__rosidl_typesupport_fastrtps_cpp}
         fastcdr fastrtps)
 
 target_compile_definitions(${PROJECT_NAME} PRIVATE STD_MSGS_VERSION_MAJOR=${std_msgs_VERSION_MAJOR} 
                                 GEOMETORY_MSGS_VERSION_MAJOR=${geometry_msgs_VERSION_MAJOR} 
                                 SENSOR_MSGS_VERSION_MAJOR=${sensor_msgs_VERSION_MAJOR} 
                                 STD_MSGS_VERSION_MINOR=${std_msgs_VERSION_MINOR} 
                                 GEOMETORY_MSGS_VERSION_MINOR=${geometry_msgs_VERSION_MINOR} 
                                 SENSOR_MSGS_VERSION_MINOR==${sensor_msgs_VERSION_MINOR})

CPPファイルの作成

ROS用シリアライザを作成する場合、CPPファイルでROS2Serializer.hをインクルードします。 また、今回はROS2のgeometry_msgs/TwistStamped型を使用するため、geometry_msgs/msg/twist_stamped.hppgeometry_msgs/msg/detail/twist_stamped__rosidl_typesupport_fastrtps_cpp.hppをインクルードします。このインクルードファイルは使用するメッセージ型により変更します。

 #include <rtm/ByteDataStreamBase.h>
 #include <rtm/idl/BasicDataTypeSkel.h>
 #include <rtm/idl/ExtendedDataTypesSkel.h>
 #include <coil/Factory.h>
 #include <rtm/Manager.h>
 #include <rtm/ext/ROS2Transport/ROS2Serializer.h>
 #include <geometry_msgs/msg/twist_stamped.hpp>
 #if (STD_MSGS_VERSION_MAJOR >= 2)
 #include <geometry_msgs/msg/detail/twist_stamped__rosidl_typesupport_fastrtps_cpp.hpp>
 #else
 #include <geometry_msgs/msg/twist_stamped__rosidl_typesupport_fastrtps_cpp.hpp>
 #endif

ROS2SerializerBaseクラスを継承したクラスを定義します。 ROS2SerializerBaseクラスのテンプレート引数には使用するOpenRTM-aistのデータ型を指定します。今回はRTC::TimedVelocity3D型を使用するため、RTC::TimedVelocity3Dを指定します。

 class TestRos2Serializer : public RTC::ROS2SerializerBase<RTC::TimedVelocity3D>
 {
 public:
    TestRos2Serializer(){};

以下のようにTestRos2Serializerクラスのメンバ関数としてserialize関数を定義する。 serialize関数では、RTC::TimedVelocity3D型のデータをgeometry_msgs/TwistStamped型のデータに変換し、その後バイト列データに変換しています。 geometry_msgs/TwistStamped型のデータからバイト列データへの変換は、geometrymsg_serialize関数を使用しています。 std_msgパッケージのメッセージ型の場合はstdmsg_serialize関数、geometry_msgsパッケージのメッセージ型の場合はgeometrymsg_serialize関数、sensor_msgパッケージのメッセージ型の場合はsensormsg_serialize関数を使用します。

    bool serialize(const RTC::TimedVelocity3D& data) override
    {
        geometry_msgs::msg::TwistStamped msg;
        msg.header.stamp.sec = data.tm.sec;
        msg.header.stamp.nanosec = data.tm.nsec;
        msg.twist.linear.x = data.data.vx;
        msg.twist.linear.y = data.data.vy;
        msg.twist.linear.z = data.data.vz;
        msg.twist.angular.x = data.data.vr;
        msg.twist.angular.y = data.data.vp;
        msg.twist.angular.z = data.data.va;
        

        return RTC::ROS2SerializerBase<RTC::TimedVelocity3D>::geometrymsg_serialize(msg);
    }

std_msg、geometry_msgs、sensor_msg以外のパッケージのメッセージ型の場合は、stdmsg_serialize関数の実装を参考にして記述してください。

次にdeserialize関数を定義します。 deserialize関数では、バイト列データをgeometry_msgs/TwistStamped型のデータに変換し、その後RTC::TimedVelocity3D型のデータに変換しています。 バイト列データからgeometry_msgs/TwistStamped型のデータへの変換は、geometrymsg_deserialize関数を使用しています。 std_msgパッケージのメッセージ型の場合はstdmsg_deserialize関数、geometry_msgsパッケージのメッセージ型の場合はgeometrymsg_deserialize関数、sensor_msgパッケージのメッセージ型の場合はsensormsg_deserialize関数を使用します。

    bool deserialize(RTC::TimedVelocity3D& data) override
    {
        geometry_msgs::msg::TwistStamped msg;
        bool ret = ROS2SerializerBase<RTC::TimedVelocity3D>::geometrymsg_deserialize(msg);
        
        data.tm.sec = msg.header.stamp.sec;
        data.tm.nsec = msg.header.stamp.nanosec;
        data.data.vx = msg.twist.linear.x;
        data.data.vy = msg.twist.linear.y;
        data.data.vz = msg.twist.linear.z;
        data.data.vr = msg.twist.angular.x;
        data.data.vp = msg.twist.angular.y;
        data.data.va = msg.twist.angular.z;
        

        return ret;
    }

std_msg、geometry_msgs、sensor_msg以外のパッケージのメッセージ型の場合は、stdmsg_deserialize関数の実装を参考にして記述してください。

以下ように{ライブラリ名}Init関数を定義すると、動的リンクライブラリのロード時にこの関数が呼ばれます。 TestRos2SerializerInit関数内でファクトリにシリアライザを追加することにより、RTC起動時に実装したシリアライザが使えるようにします。

extern "C" {

    //以下はモジュールロード時に呼び出される関数
    DLL_EXPORT void TestRos2SerializerInit(RTC::Manager* /*manager*/)
    {
        //シリアライザの登録
        RTC::addRos2Serializer<RTC::TimedVelocity3D, geometry_msgs::msg::TwistStamped, TestRos2Serializer>("ros2:geometry_msgs/TwistStamped");
    }
}

動作確認

以下から作成済みのシリアライザ、動作確認用のRTCをダウンロードできます。

作成したTestRos2Serializerをビルドしてください。 ビルド、実行時にはROS2の環境変数が設定されている必要があるため、以下のコマンドを実行してください。

 source /opt/ros/foxy/setup.bash

rtc.confを作成します。 FastRTPSTransport.soROS2Transport.soと、作成したシリアライザTestRos2Serializer.soをロードするように設定します。 TestRos2Serializer.soのパスは、ビルドしたディレクトリのパスに変更してください。

 manager.modules.load_path: /usr/lib/openrtm-2.0/transport/, ~/TestRos2Serializer/build
 manager.modules.preload: FastRTPSTransport.so, ROS2Transport.so, TestRos2Serializer.so

以下のようにサンプルコンポーネントのtestVelocity3DInのInPort、testVelocity3DOutのOutPortでコネクションを生成します。

 manager.components.preconnect: testVelocity3DIn0.in?interface_type=fast-rtps&marshaling_type=ros2:geometry_msgs/TwistStamped&fast-rtps.topic=chatter, testVelocity3DOut0.out?interface_type=fast-rtps&marshaling_type=ros2:geometry_msgs/TwistStamped&fast-rtps.topic=chatter

動作確認する場合は、testOpenRTMSerializerに含まれているtestVelocity3DIn、testVelocity3DOutのサンプルコンポーネントをビルドしてください。

以下のコマンド実行後、RTCをアクティブ化するとtestVelocity3DOutのPublisherからtestVelocity3DInのSubscriberにデータが送信されて、testVelocity3DInを起動した画面に数値が表示されます。

 testVelocity3DOutComp -f rtc.conf

 testVelocity3DInComp -f rtc.conf

今回の動作確認ではRTC同士でROS2のトピック通信を実行しましたが、ROS2ノードと通信を確認する場合は、geometry_msgs/TwistStamped型のPublisher、Subscriberを持つROS2ノードを作成して試してください。

独自シリアライザの実装手順(ROS、Python)

独自シリアライザの実装手順(ROS2、Python)

マネージャの機能

Choreonoid OpenRTMプラグインの利用方法

Choreonoidはオープンソースのロボット用シミュレーションソフトウェアです。 拡張性が高く、物理エンジン、通信機能、スクリプティング機能、制御アルゴリズム等をC++プラグインとして追加できます。

Choreonoid用OpenRTMプラグインはChoreonoid上でRTCを起動し、シミュレータ上のオブジェクトのトルクや速度、ビジョンセンサやレーザーレンジセンサ等の入出力をポートの入出力と関連付けたRTCを作成できます。 これにより外部のRTCとChoreonoidの入出力が連携し、RTCの再利用によるシミュレータ実行の効率化、シミュレータ環境から実機環境へシームレスに移行できます。

choreonoid1_1.png

このページではOpenRTMプラグインのインストール手順について説明します。

ビルド手順

OpenRTMプラグインは現在OpenRTM-aist 1.2.2以前のバージョンのサポートを終了しています。 OpenRTM-aist 2.0.0以上のバージョンのインストールが必要です。

Windows

OpenRTM-aistのビルドとインストール

OpenRTM-aist+omniORBを以下の手順でビルド、インストールしてください。 ※インストーラーでOpenRTM-aistをインストールしている場合は不要。

ただし、CMake実行時にOpenRTM-aistのインストールフォルダは指定してそこにインストールするようにしてください。

 set OPENRTM_INSTALL_DIR=C:/work/openrtm_install
 set OMNIORB_SOURCE_DIR=C:/workspace/omniORB-4.2.5-x64-vc14-py310
 cmake .. -DORB_ROOT=%OMNIORB_SOURCE_DIR% -DCMAKE_INSTALL_PREFIX=%OPENRTM_INSTALL_DIR%
 cmake --build . --config Release
 cmake --build . --config Release --target install

またOpenSSLのヘッダーファイル、ライブラリを適当な場所に展開してください。

Choreonoidのビルドとインストール

Choreonoidを以下の手順でビルド、インストールしてください。

CMake、Boost、Qtのバージョンには注意してください。

  • CMakeのバージョンが古い場合、Boostをライブラリを検出できない場合があります。できるだけ最新版をインストールしてください。
  • Boostはデフォルトの設定でC:\local\boost_1_77_0のようなフォルダにインストールされますが、CMakeはC:\local\boost_{バージョン番号}からBoostを探すため、古いバージョンがすでにC:\local\以下にインストールされている場合にそちらを検出する事があるので注意してください。

OpenRTMプラグインの使用のためにはCORBAプラグインのビルドに、ヘッダーファイルなどの各種ファイルをインストールが必要です。 また、OpenRTM Pythonプラグインの使用のためにはPythonプラグインのビルドが必要です。

設定項目 内容 設定例
ENABLE_CORBA CORBA通信機能の有効化、無効化 ON
BUILD_CORBA_PLUGIN CORBAプラグインのビルドの有無 ON
CHOREONOID_OMNIORB_DIR omniORBのインストールフォルダのパス C:/work/openrtm_install/2.0.0/omniORB/4.2.5_vc16
INSTALL_SDK ヘッダーファイルなどの各種ファイルをインストールするか ON
ENABLE_PYTHON Pythonスクリプティング機能、およびPythonプラグインのビルドの有無 ON
CMAKE_INSTALL_PREFIX Choreonoidのインストールフォルダ C:/work/choreonoid_install

CHOREONOID_OMNIORB_DIRについては環境変数OMNI_ROOTを設定していると自動でomniORBを検出しますが、Choreonoidが生成するCMakeコンフィグファイルの問題でOpenRTMプラグインのビルドでエラーが発生することがあるので必ず手動でパスを設定してください。 またPythonプラグインのビルドのため、Pythonをインストールしてください。

コマンドでは以下のように入力できます。

 set CHOREONOID_INSTALL_DIR=C:/work/choreonoid_install
 Invoke-WebRequest -Uri https://github.com/choreonoid/choreonoid/archive/refs/tags/v1.7.0.zip -OutFile choreonoid-1.7.0.zip
 Expand-Archive -Path choreonoid-1.7.0.zip -DestinationPath .
 Rename-Item choreonoid-1.7.0 choreonoid
 cd choreonoid
 mkdir build
 cd build
 cmake .. -DENABLE_CORBA=ON -DBUILD_CORBA_PLUGIN=ON -DINSTALL_SDK=ON -DCHOREONOID_OMNIORB_DIR=%OPENRTM_INSTALL_DIR%/2.0.0/omniORB/4.2.5_vc16 -DENABLE_PYTHON=ON -DCMAKE_INSTALL_PREFIX=%CHOREONOID_INSTALL_DIR%
 cmake --build . --config Release
 cmake --build . --config Release --target install

choreonoidのリポジトリのmasterブランチのソースコードに不具合があり、WindowsでのCorbaPluginのビルドでエラーが発生します。masterブランチのソースコードを使う場合、src/CorbaPlugin/CorbaPlugin.cppの以下の部分を修正してください。

 nameServerProcess.start(QString("\"") + command.c_str() + "\""); //修正前
 
 nameServerProcess.start(QString("\"") + command.c_str() + "\"", QStringList()); //修正後

※OpenRTM-aistをインストーラーでインストールした場合はCHOREONOID_OMNIORB_DIRオプションの設定は不要です。

OpenRTMプラグインのビルドとインストール

OpenRTMプラグインのソースコードは以下から入手できます。

Choreonoidと同様、CMake実行後にVisual Studioでビルドします。

CMakeでは以下の項目を設定します。

設定項目 内容 設定例
Choreonoid_DIR ChoreonoidのCMakeコンフィグファイルがインストールされたフォルダ C:/work/choreonoid_install/share/choreonoid/cmake
OpenRTM_DIR OpenRTM-aistのCMakeコンフィグファイルがインストールされたフォルダ C:/work/openrtm_install/2.0.0/cmake

以下のコマンドを実行することでビルド、インストールができます。 生成したOpenRTMプラグインはChoreonoidのインストールフォルダにコピーされます。

 git clone https://github.com/OpenRTM/choreonoid-openrtm
 cd choreonoid-openrtm
 mkdir build
 cd build
 cmake .. -DChoreonoid_DIR=%CHOREONOID_INSTALL_DIR%/share/choreonoid/cmake -DOpenRTM_DIR=%OPENRTM_INSTALL_DIR%/2.0.0/cmake
 cmake --build . --config Release
 cmake --build . --config Release --target install

※OpenRTM-aistをインストーラーでインストールした場合はOpenRTM_DIRオプションの設定は不要です。

OpenRTM Pythonプラグインのビルドとインストール

OpenRTMプラグインのソースコードは以下から入手できます。

CMakeの設定項目はOpenRTMプラグインと同じです。

以下のコマンドを実行することでビルド、インストールができます。

 git clone https://github.com/Nobu19800/OpenRTMPythonPlugin
 cd OpenRTMPythonPlugin
 mkdir build
 cd build
 cmake .. -DChoreonoid_DIR=%CHOREONOID_INSTALL_DIR%/share/choreonoid/cmake -DOpenRTM_DIR=%OPENRTM_INSTALL_DIR%/2.0.0/cmake
 cmake --build . --config Release
 cmake --build . --config Release --target install

※OpenRTM-aistをインストーラーでインストールした場合はOpenRTM_DIRオプションの設定は不要です。

必要なファイル一式をまとめる

Choreonoidをビルド、インストールすると、基本的には必要なファイルはインストール先にコピーされます。 ただし、Pythonプラグインをビルドする場合は、対応するバージョンのPythonがインストールされている必要があります。

このため、対応するバージョンのPythonがインストールされていない場合は、以下のページのように組み込み用Pythonを同梱する必要があります。

まずは、対応するバージョンのpython-3.x.y-embed-amd64をダウンロードしてください。

次に必要なライブラリをインストールします。 Choreonoidはnumpyが必要なためインストールします。

 python -m pip install numpy

また、Choreonoid Pythonプラグインのサンプルプログラムを実行するためにPySDL2が必要なためインストールします。

 python -m pip install pysdl2 pysdl2-dll

omniORB、OpenRTM-aistをインストールする必要があるため、以下のファイル、フォルダをpython-3.x.y-embed-amd64/Lib/site-packages以下のコピーしてください。

  • CosNaming
  • omniidl
  • omniidl_be
  • omniORB
  • OpenRTM_aist
  • OpenRTM-aist.pth
  • CORBA.py
  • CosNaming_idl.py
  • CosNamingPOA
  • PortableServer.py
  • PortableServerPOA.py
  • _omnicodesets.pyd
  • _omniConnMgmt.pyd
  • _omnihttpCrypto.pyd
  • _omnihttpTP.pyd
  • _omnipy.pyd
  • _omnisslTP.pyd

Ubuntu

OpenRTM-aistのビルドとインストール

OpenRTM-aist+omniORBを以下の手順でビルド、インストールしてください。

 export OPENRTM_INSTALL_PATH=~/work/openrtm_install
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build/
 git clone 
 cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_PATH
 cmake --build . --config Release
 sudo cmake --build . --config Release --target install

Choreonoidのビルドとインストール

Choreonoidを以下の手順でビルド、インストールしてください。

CMake、Boost、Qtのバージョンには注意してください。

  • CMakeのバージョンが古い場合、Boostをライブラリを検出できない場合があります。できるだけ最新版をインストールしてください。
  • Boostはデフォルトの設定でC:\local\boost_1_77_0のようなフォルダにインストールされますが、CMakeはC:\local\boost_{バージョン番号}からBoostを探すため、古いバージョンがすでにC:\local\以下にインストールされている場合にそちらを検出する事があるので注意してください。

OpenRTMプラグインの使用のためにはCORBAプラグインのビルドに、ヘッダーファイルなどの各種ファイルをインストールが必要です。 また、OpenRTM Pythonプラグインの使用のためにはPythonプラグインのビルドが必要です。

設定項目 内容 設定例
ENABLE_CORBA CORBA通信機能の有効化、無効化 ON
BUILD_CORBA_PLUGIN CORBAプラグインのビルドの有無 ON
INSTALL_SDK ヘッダーファイルなどの各種ファイルをインストールするか ON
ENABLE_PYTHON Pythonスクリプティング機能、およびPythonプラグインのビルドの有無 ON
CMAKE_INSTALL_PREFIX Choreonoidのインストールフォルダ ~/work/choreonoid_install

 export CHOREONOID_INSTALL_DIR=~/work/choreonoid_install
 git clone https://github.com/choreonoid/choreonoid
 cd choreonoid
 mkdir build
 cd build
 cmake .. -DENABLE_CORBA=ON -DBUILD_CORBA_PLUGIN=ON -DINSTALL_SDK=ON  -DENABLE_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$CHOREONOID_INSTALL_DIR
 cmake --build . --config Release
 cmake --build . --config Release --target install

OpenRTMプラグインのビルドとインストール

OpenRTMプラグインのソースコードは以下から入手できます。

CMakeでは以下の項目を設定します。

設定項目 内容 設定例
Choreonoid_DIR ChoreonoidのCMakeコンフィグファイルがインストールされたフォルダ ~/work/choreonoid_install/share/choreonoid/cmake
OpenRTM_DIR OpenRTM-aistのCMakeコンフィグファイルがインストールされたフォルダ ~/work/openrtm_install/lib/openrtm-2.0/cmake

以下のコマンドを実行することでビルド、インストールができます。 生成したOpenRTMプラグインはChoreonoidのインストールフォルダにコピーされます。

 git clone https://github.com/OpenRTM/choreonoid-openrtm
 cd choreonoid-openrtm
 mkdir build
 cd build
 cmake .. -DChoreonoid_DIR=$CHOREONOID_INSTALL_DIR/share/choreonoid/cmake -DOpenRTM_DIR=$OPENRTM_INSTALL_PATH/lib/openrtm-2.0/cmake
 cmake --build . --config Release
 cmake --build . --config Release --target install

OpenRTM Pythonプラグインのビルドとインストール

OpenRTMプラグインのソースコードは以下から入手できます。

CMakeの設定項目はOpenRTMプラグインと同じです。

以下のコマンドを実行することでビルド、インストールができます。

 git clone https://github.com/Nobu19800/OpenRTMPythonPlugin
 cd OpenRTMPythonPlugin
 mkdir build
 cd build
 cmake .. -DChoreonoid_DIR=$CHOREONOID_INSTALL_DIR/share/choreonoid/cmake -DOpenRTM_DIR=$OPENRTM_INSTALL_PATH/lib/openrtm-2.0/cmake
 cmake --build . --config Release
 cmake --build . --config Release --target install

使用方法

使用方法については以下のページを参考にしてください。

Choreonoid入門

はじめに

Choreonoidはオープンソースのロボット用シミュレーションソフトウェアです。 拡張性が高く、物理エンジン、通信機能、スクリプティング機能、制御アルゴリズム等をC++プラグインとして追加できます。

このページでは、Choreonoidシミュレータ上の移動ロボットの入出力を行うRTCの作成手順を説明します。

choreonoidtutorial1_1.png

Choreonoidの起動

講習会の実習の場合はUSBメモリ等で資料を配布しているため、USBメモリ内のchoreonoidフォルダ内のchoreonoid.batをダブルクリックして起動してください。

アイテムの追加

Choreonoid上で以下のアイテムを追加してシミュレーション環境を構築します。

 World(ワールドアイテム)
   |-AISTSimulator(AISTシミュレータ)
   |-Floor(model/misc/floor.body)
   |-RaspberryPiMouse(model/RaspberryPiMouse/RaspberryPiMouse.body)
       |-RaspberryPiMouseIo(PyRTC)
   |-RobotController(RTC)
   |-RTSystem

ワールド追加

Choreonoidで仮想世界を表現するワールドアイテムを追加します。 ボディモデル等の各アイテムはワールドアイテムと関連付けする必要があります。

「ファイル」->「新規」->「ワールド」をクリックしてWorldを追加してください。

choreonoidtutorial1_2.png

名前は変更せずに生成します。

ワールドアイテムが追加されると、アイテムビューにWorldが表示されます。

choreonoidtutorial1_3.png

シミュレータ追加

Choreonoidは複数のプラグインから使用する物理エンジンを選択することができます。 Choreonoid本体でサポートしているプラグインとしては、AISTシミュレータ、ODE, Bullet, PhysXが使用できます。

今回はAISTシミュレータを追加するため、「ファイル」->「新規」->「AISTシミュレータ」をクリックしてください。

choreonoidtutorial1_4.png

名前は変更せずに生成します。

AISTシミュレータアイテムが追加されると、アイテムビューにAISTSimulatorが表示されます。

地面追加

地面を表現するボディアイテムを追加します。 「ファイル」->「読み込み」->「ボディ」をクリックしてください。

choreonoidtutorial1_5.png

「ボディ読み込み」の画面でfloor.bodyを選択します。 左側のshareをクリックして、share/model/misc/floor.bodyのファイルを選択してください。

choreonoidtutorial1_6.png

アイテムが追加されると、アイテムビューにFloorが表示されます。

Raspberry Piマウス追加

Raspberry Piマウスを表現するボディアイテムを追加します。 先ほどと同じ手順で「ファイル」->「読み込み」->「ボディ」をクリックしてください。

「ボディ読み込み」の画面でRaspberryPiMouse.bodyを選択します。 左側のshareをクリックして、share/model/RaspberryPiMouse/RaspberryPiMouse.bodyのファイルを選択してください。

choreonoidtutorial1_7.png

アイテムが追加されると、アイテムビューにRaspberryPiMouseが表示されます。

また、シーンビューにRaspberryPiマウスの3Dモデルが表示されます。

choreonoidtutorial1_8.png

RTSystem追加

Choreonoid上でRTSystemEditorの一部機能を使用するためのRTSystemアイテムを追加します。 「ファイル」->「新規」->「RTSystem」をクリックしてください。名前の変更は不要です。

choreonoidtutorial1_9.png

アイテムが追加されると、アイテムビューにRTSystemが表示されます。

ネームサーバー、システムエディタ表示

この時点でChoreonoid上にネームサーバー、システムエディタは表示されていません。

まずネームサーバーを表示するには、「表示」->「ビューの表示」->「RTC List」をクリックします。

choreonoidtutorial1_10.png

これでプロパティ、リンクプロパティの右にRTC Listタブが表示されます。

choreonoidtutorial1_11.png

システムエディタを表示するには、「表示」->「ビューの表示」->「RTC Diagram」をクリックします。

choreonoidtutorial1_12.png

これでシーンの右にRTC Diagramタブが表示されます。

choreonoidtutorial1_13.png

RobotControllerコンポーネント追加

以下のページで作成したRobotControllerコンポーネントをシミュレータで利用可能にします。

RTCを表現するRTCアイテムを追加してください。

「ファイル」->「新規」->「RTC」をクリックします。

choreonoidtutorial1_14.png

名前をRobotControllerに変更します。

choreonoidtutorial1_15.png

アイテムが追加されると、アイテムビューにRobotControllerが表示されます。

RobotControllerコンポーネントの設定

次にRobotControllerComp.exeとRobotControllerアイテムを関連付けます。 アイテムビューからRobotControllerを選択して、プロパティからRTC moduleを設定します。

choreonoidtutorial1_16.png

「ファイルを選択」の画面でRobotControllerComp.exeを選択します。 初期の状態だと拡張子dllのファイルしか表示しないため、ファイルの種類を全てのファイル (*) に設定してからファイルを選択してください。

choreonoidtutorial1_17.png

RaspberryPiMouseIoコンポーネント追加

PythonのRTCをChoreonoid上で起動するため、PyRTCアイテムを追加します。

「ファイル」->「新規」->「PyRTC」をクリックします。

choreonoidtutorial1_18.png

名前をRaspberryPiMouseIoに変更します。

choreonoidtutorial1_19.png

アイテムが追加されると、アイテムビューにRaspberryPiMouseIoが表示されます。

RaspberryPiMouseIoコンポーネント作成

ここからはRTC Builderで作業します。

以下の仕様のRTCを作成してください。

基本
コンポーネント名 RaspberryPiMouseIo
アクティビティ
なし
データポート(OutPort)
なし
データポート(InPort)
ポート名 velocity
データ型 RTC::TimedVelocity2D
コンフィギュレーション
なし
言語・環境
言語 Python

RaspberryPiMouseIo.pyの編集

コード生成すると、RaspberryPiMouseIo.pyが作成されるのでこのファイルをVisual Studio CodeやIDLEなどで編集します。

RaspberryPiMouseIoクラスにsetBodyoutputToSimulatorinputFromSimulatorのメンバ関数を追加します。

setBody関数はRTC側でChoreonoidのボディオブジェクトを取得する関数です。 取得したBodyオブジェクトからLinkオブジェクトを取得することで、対象のJointの入出力ができます。

outputToSimulator関数は、シミュレータ上のオブジェクトから取得したデータをOutPortから出力する処理を行う関数です。

inputFromSimulator関数は、InPortの入力データをシミュレータ上のオブジェクトに入力する処理を行う関数です。

各関数は、シミュレーション実行時に以下の図のような順序で呼ばれます。

choreonoidtutorial1_20_2.png

RaspberryPiMouseIo.pyに以下のコードを追加してください。 Pythonなので、インデントには注意してください。「def ~」を「# def onRateChanged~」のインデントに合わせる必要があります。

    # def onRateChanged(self, ec_id):
    #
    #    return RTC.RTC_OK
    
    def setBody(self, body):
        self.ioBody = body
        self.wheelR = self.ioBody.link("RIGHT_WHEEL")
        self.wheelL = self.ioBody.link("LEFT_WHEEL")
    
    def outputToSimulator(self):
        pass
    
    def inputFromSimulator(self):
        if self._velocityIn.isNew():
            data = self._velocityIn.read()
            
            vx = data.data.vx
            va = data.data.va
            
            wheel_distance = 0.0425
            wheel_radius = 0.04
            rms = (vx + va*wheel_distance)/wheel_radius
            lms = (vx - va*wheel_distance)/wheel_radius
            
            self.wheelR.dq = rms
            self.wheelL.dq = lms

RaspberryPiMouseIoコンポーネントの設定

Choreonoidでの作業に戻ります。 アイテムビューからRaspberryPiMouseIoを選択して、プロパティからRTC Moduleを設定します。

choreonoidtutorial1_21.png

「ファイルを選択」の画面で先ほど編集したRaspberryPiMouseIo.pyを選択します。

choreonoidtutorial1_22.png

※RaspberryPiMouseIo.pyを更新した場合は、再度この作業を行う事で再読み込みしてください。

アイテムの位置関係を確認

アイテムビューで、全てのアイテムはワールドアイテムの子アイテムとして配置する必要があります。 また、RaspberryPiMouseIoRaspberryPiMouseの子アイテムとして配置します。

 World
     |- AISTSimulator
     |- Floor
     |- RaspberryPiMouse
     |     |- RaspberryPiMouseIo
     |- RobotController
     |- RTSystem

位置関係が違う場合はドラッグアンドドロップして移動してください。

choreonoidtutorial1_23.png

ポート接続

起動したRTCのポートを接続します。

この時点でRobotController0RaspberryPiMouseIo0が起動していますが、RTC Listに表示が無い場合は「Update」ボタンを押してください。

RTC ListからRTCをRTC Diagramにドラッグアンドドロップして、以下のポートを接続してください。

InPort OutPort
RobotController0 out RaspberryPiMouseIo0 velocity

choreonoidtutorial1_24.png

RobotControllerコンポーネントのアクティブ化

RTCアイテムにexeファイルを設定した場合はRTCを自動でアクティブ化しないため、RTC Diagram上でRobotController0を右クリックして「Activate」を選択してください。 ※RaspberryPiMouseIo0はシミュレーションを開始すると自動的にアクティブ状態になるため操作の必要はありません。

choreonoidtutorial1_25.png

シミュレーション開始

「初期位置からのシミュレーション開始」ボタンを押すとシミュレーションを開始します。

choreonoidtutorial1_26.png

シーンタブに切り替えるとシミュレーションを3DCGで表示します。

choreonoidtutorial1_27.png

コンフィギュレーションパラメータの編集

Choreonoid OpenRTMプラグインにはコンフィギュレーションパラメータ編集機能がないため、RTSystemEditorで作業します。

ネームサービスビューでRobotControllerを選択して、コンフィギュレーションビューから「編集」ボタンを押して、コンフィギュレーションパラメータを変更してみてください。

choreonoidtutorial1_28.png

Choreonoidで表示したRaspberry Piマウスが移動しているか確認すれば完了です。

ネームサービスビューにlocalhostと表示されていない場合については、以下のようにネームサービス接続ボタンを押して、localhostのネームサーバーに接続してください。

/ja/node/6550
choreonoidtutorial1_30.png

OpenRTM-aist(C++版)のCMakeによるビルド手順

Windows + omniORB

以下から OpenRTM-aist のソースコードを入手してください。

以下からビルド済みの omniORB を入手してください。

チェックアウトしたフォルダー(OpenRTM-aist)に移動して以下のコマンドを実行してください。

 mkdir build
 cd build
 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.3-win64-vc141 -G "Visual Studio 16 2019" -DCMAKE_INSTALL_PREFIX=C:/workspace/openrtminstall ..
 cmake --build . --config Release
 cmake --build . --config Release --target install

変数名 意味 設定できる値
CORBA CORBA のライブラリー omniORB

Windows + TAO

以下から OpenRTM-aist のソースコードを入手してください。

以下の手順でTAOをビルドします。

チェックアウトしたフォルダー(OpenRTM-aist)に移動して以下のコマンドを実行してください。

 mkdir build
 cd build
 cmake -DORB_ROOT=C:/workspace/ACE_wrappers -DCORBA=TAO -G "Visual Studio 16 2019" -DCMAKE_INSTALL_PREFIX=C:/workspace/openrtminstall ..
 set PATH=%PATH%;C:\workspace\ACE_wrappers\lib;
 cmake --build . --config Release
 cmake --build . --config Release --target install

Windows 10 IoT + omniORB

omniORBのWindows 10 IoT用のビルド済みバイナリファイルは現在のところ配布していないため、自力でビルドする必要があります。 Cygwinのインストールが必要です。

omniORBのソースコードを入手してください。

omniORB-4.2.2.tar.bz2を適当な場所に展開してください。

最初にARM+Windows用の修正パッチを適用します。 以下から修正パッチを入手してください。

Cygwin上で以下のコマンドを実行してください。

 patch -p1 -d omniORB-4.2.2 < omniORB-4.2.2-windows-iot.patch

omniORB-4.2.2.tar.bz2を展開したフォルダのmk/platforms/arm_win32_vs_14.mkを編集します。 使用するVisual Studioのバージョンが違う場合は合ったものを選択してください。 以下のようにPythonのディレクトリを指定します。

 PYTHON = /cygdrive/c/Python27/python

次にconfig/config.mkを編集します。 以下のように対応したmkファイルを指定します。 Visual Studioのバージョンが違う場合は適宜対応してください。

 platform = arm_win32_vs_14

クロスコンパイルを行うため、idlコンパイラなどの実行ファイルは開発環境で動作可能なものを用意します。

以下からx86用にビルドした omniORB のバイナリを入手してください。

zipファイルを展開したフォルダのbin/x86_win32の中身を、omniORB-4.2.2.tar.bz2を展開したフォルダのbin/x86_win32にコピーしてください。

omniORB-4.2.2.tar.bz2を展開したディレクトリに移動して、以下のコマンドを実行してください。

 set PATH=C:\cygwin64\bin;%PATH%;
 call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_arm
 cd src
 make export

これでbin/ARM_win32に実行ファイルが、lib/ARM_win32にライブラリが生成されます。 vcvarsall.batについてはVisual Studioのバージョンにあったものを使用してください。 Visual Studio 2017の場合はC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.batとなります。

OpenRTM-aistのビルドは通常とほとんど同じです。 cmakeのオプションとしてVisual Studio 14 2015 ARMというようにARM用のコンパイラを指定してください。

 mkdir build
 cd build
 cmake -DORB_ROOT=C:/workspace/omniORB-4.2.2 -G "Visual Studio 14 2015" -A ARM -DCMAKE_INSTALL_PREFIX=C:/workspace/openrtminstall ..
 cmake --build . --config Release
 cmake --build . --config Release --target install

Visual StudioにARM用コンパイラがインストールされていないとビルドできません。 ARM用コンパイラをインストールしていない場合は、Visual Studio Installerを起動してARM用Visual Studio C++コンパイラとライブラリ'をインストールしてください。



arm1.png


Ubuntu + omniORB

 sudo apt install libomniorb4-dev omniidl omniorb-nameserver
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build/
 cmake -DCMAKE_BUILD_TYPE=Release ..
 cmake --build . --config Release -- -j$(nproc)
 sudo cmake --build . --config Release --target install

変数名 意味 設定できる値
CORBA CORBA のライブラリー omniORB

Ubuntu + TAO

以下の手順でTAOをビルドします。

以下のコマンドでOpenRTM-aistをビルドしてください。

 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build
 cmake -DCORBA=TAO -DCMAKE_BUILD_TYPE=Release ..
 cmake --build . --config Release -- -j$(nproc)
 sudo cmake --build . --config Release --target install

VxWorks + omniORB

事前にWind River Workbenchのホームディレクトリを指定する必要があります。 Wind River WorkbenchをインストールしたディレクトリをWIND_HOMEという変数に設定してください。

 export WIND_HOME=/home/openrtm/WindRiver

OpenRTM-aistのビルドの前に、omniORBのビルドを行う必要があります。

omniORB

omniORBのソースコードを入手してください。

omniORBのVxWorks対応パッチを入手してください。

以下のコマンドでビルドを実行します。

 wget https://jaist.dl.sourceforge.net/project/omniorb/omniORB/omniORB-4.2.2/omniORB-4.2.2.tar.bz2
 tar xf omniORB-4.2.2.tar.bz2
 wget http://svn.openrtm.org/omniORB/trunk/vxworks/omniORB-4.2.2-vxworks.patch
 patch -p1 -d omniORB-4.2.2 < omniORB-4.2.2-vxworks.patch
 cd omniORB-4.2.2
 mkdir build
 cd build
 ../configure
 make
 cd ..
 sed -i '1s/^/platform = ${VXWORKS_PLATFORM}\n/' config/config.mk
 cd src
 make export

ただし、VXWORKS_PLATFORMには動作環境に合ったものを入力するようにしてください。

VXWORKS_PLATFORM CPU VxWorksのバージョン 実装方法
powerpc_vxWorks_kernel_6.6 PowerPC 6.6 カーネルモジュール
powerpc_vxWorks_RTP_6.6 PowerPC 6.6 RTP
powerpc_vxWorks_kernel_6.9 PowerPC 6.9 カーネルモジュール
powerpc_vxWorks_RTP_6.9 PowerPC 6.9 RTP
simlinux_vxWorks_kernel_6.6 Linux上のシミュレータ 6.6 カーネルモジュール
simpentium_vxWorks_RTP_6.6 Linux上のシミュレータ 6.6 RTP
simlinux_vxWorks_kernel_6.9 Linux上のシミュレータ 6.9 カーネルモジュール
simpentium_vxWorks_RTP_6.9 Linux上のシミュレータ 6.9 RTP

OpenRTM-aist

以下のコマンドを入力してください。

 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build/
 cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DVX_VERSION=${VX_VERSION} -DORB_ROOT=${ORB_ROOT} -DOMNI_VERSION=42 -DCORBA=omniORB -DVX_CPU_FAMILY=${ARCH} ..
 make

ただし、TOOLCHAIN_FILE、VX_VERSION 、ORB_ROOT、ARCHには以下の設定をしてください。

TOOLCHAIN_FILE VxWorks 6.6(カーネルモジュール、PowerPC)の場合は../Toolchain-vxworks6.6-Linux.cmake、それ以外の場合は../Toolchain-vxworks6.cmake
VX_VERSION vxworks-6.6vxworks-6.9
ORB_ROOT omniORBのディレクトリ(例:/home/openrtm/omniORB-4.2.2)
VX_CPU_FAMILY ppc(PowerPC)、simlinux(カーネルモジュール、シミュレータ)、simpentium(RTP、シミュレータ)

RTPの場合はcmakeコマンドに-DRTP=ONを追加する必要があります。

 cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DVX_VERSION=${VX_VERSION} -DORB_ROOT=${ORB_ROOT} -DOMNI_VERSION=42 -DCORBA=omniORB -DVX_CPU_FAMILY=${ARCH} -DRTP=ON ..
 cmake --build . --config Release

VxWorks + ORBexpress

※現在のところ対応環境はVxWorks 6.6、PowerPCのみです。

以下のコマンドを入力してください。

 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build/
 cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DORB_ROOT=${ORB_ROOT} -DCORBA=ORBexpress ..
 make

TOOLCHAIN_FILE、ORB_ROOTには以下の設定をしてください。

TOOLCHAIN_FILE カーネルモジュールの場合は../Toolchain-vxworks6.6-Linux.cmake、RTPの場合は../Toolchain-vxworks6.cmake
ORB_ROOT ORBexpressのディレクトリ(例:/home/openrtm/OIS/ORBexpress/RT_2.8.4_PATCH_KC1)

QNX 6.5 + omniORB

VMWare上のQNX 6.5でビルドします。 以下のページからISOイメージを入手してください。

pkgsrc

まずはパッケージ管理システムpkgsrcをインストールします。 以下のコマンドでソースコードを入手してください。

 svn checkout --username ユーザ名 --password パスワード http://community.qnx.com/svn/repos/pkgsrc/HEAD_650/pkgsrc

ユーザー名、パスワードはQNXのアカウントのメールアドレス、パスワードを設定してください。

次に以下のコマンドでインストールします。 コマンドはsuで実行してください。

 (cd pkgsrc/bootstrap && ./bootstrap)
 (cd pkgsrc/misc/figlet && ../../bootstrap/work/bin/bmake install)

環境変数PKG_PATHを設定しておいてください。

 export PKG_PATH=ftp://ftp.netbsd.org/pub/pkgsrc/packages/QNX/i386/6.5.0_head_20110826/All/

libuuid

まずはlibuuidのビルドをします。 libuuid-1.0.3.tar.gzをダウンロードしてQNXに転送してください。

ファイルを展開してください。

 tar xf libuuid-1.0.3.tar.gz

libuuidのビルドにはsys/syscall.h、bits/syscall.h、asm/unistd.h、asm/unistd_32.h(もしくはasm/unistd_64.h)が必要になります。 ファイルを入手してlibuuid-1.0.3の下にコピーしてください。

 libuuid-1.0.3
         |-sys
         |   |-syscall.h
         |-bits
         |   |-syscall.h
         |-asm
         |   |-unistd.h
         |   |-unistd_32.h(もしくはunistd_64.h)
         |-(省略)   

以下のコマンドでビルド、インストールしてください。

 cd libuuid-1.0.3
 ./configure
 make
 make install
 cd ..

omniORB

まずはomniORB-4.2.3.tar.bz2を入手してQNXに転送してください。

ファイルを展開してください。

 tar xf omniORB-4.2.3.tar.bz2

以下のファイルについて変更が必要です。

  • configure
  • /beforeauto.mk.in

まずconfigureについては2箇所の変更が必要です。 以下の*-*-nto-qnx)の行を追加してください。

 case "$host" in
   *-*-linux-*)   plat_name="Linux";    plat_def="__linux__";    os_v="2";;
   *-*-nto-qnx)   plat_name="Linux";    plat_def="__linux__";    os_v="2";;

以下のx86-pc-*)の部分を追加してください。

 case "$host" in
   i?86-*)   proc_name="x86Processor";     proc_def="__x86__";;
   x86-pc-*) proc_name="x86Processor"; proc_def="__x86__";;

mk/beforeauto.mk.inは以下の部分を変更してください。

 #OMNITHREAD_LIB += -lpthread #削除
 OMNITHREAD_LIB += -lsocket #追加

以下のコマンドでビルドします。

 ./configure
 make
 make install
 cd ..

OpenRTM-aist

OpenRTM-aistのビルドにはcmake、pkg-config、Python 2.7が必要です。

 /usr/pkg/sbin/pkg_add -v pkg-config-0.25nb1
 /usr/pkg/sbin/pkg_add -v cmake-2.8.5
 /usr/pkg/sbin/pkg_add -v python27-2.7.2

環境変数PKG_CONFIG_PATHを設定してください。

 export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

OpenRTM-aistのソースコードを入手してQNXに転送してください。

OpenRTM-aistのディレクトリに移動して以下のコマンドを実行します。

 mkdir build
 cd build/
 ln -s /usr/pkg/bin/python2.7 ./python
 export PATH=$PWD:$PATH
 cmake -DCORBA=omniORB ..
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --target install

QNX 7.0 + omniORB

Ubuntu上にQNX Software Development Platform 7.0をインストールしてビルドします。 まずはQNX Software Centerをインストールしてください。

 sudo apt-get install libgtk2.0-0:i386
 chmod a+x qnx-setup-201808201144-lin.run
 ./qnx-setup-201808201144-lin.run

QNX Software Centerを起動してAdd InstallationからQNX Software Development Platformをインストールしてください。

 /home/openrtm/qnx/qnxsoftwarecenter/qnxsoftwarecenter
qnx9.png

libuuid

まずはlibuuidのビルドをします。

 wget https://jaist.dl.sourceforge.net/project/libuuid/libuuid-1.0.3.tar.gz
 tar xf libuuid-1.0.3.tar.gz

libuuidのビルドにはsys/syscall.h、bits/syscall.h、asm/unistd.h、asm/unistd_32.h(もしくはasm/unistd_64.h)が必要になります。 ファイルを入手してlibuuid-1.0.3の下にコピーしてください。

 cd libuuid-1.0.3
 mkdir sys
 cp /usr/include/x86_64-linux-gnu/sys/syscall.h sys
 mkdir asm
 cp /usr/include/x86_64-linux-gnu/asm/unistd.h asm
 cp /usr/include/x86_64-linux-gnu/asm/unistd_64.h asm
 mkdir bits
 cp /usr/include/x86_64-linux-gnu/bits/syscall.h bits

QNXクロスコンパイル環境設定のためにスクリプトを実行します。

 source ~/qnx700/qnxsdp-env.sh

以下のコマンドでビルドします。 qnx700のパスは適宜変更してください。

 ./configure --prefix=/home/openrtm/qnx700/target/qnx7/usr/ CC="qcc -V5.4.0,gcc_ntox86_64_gpp" CXX="q++ -V5.4.0,gcc_ntox86_64_gpp" AR=ntox86_64-ar RANLIB=ntox86_64-ranlib --host=x86_64-unknown-linux-gnu
 make
 make install
 cd ..

omniORB

まずはomniORBのソースコードを入手してください。

 wget https://jaist.dl.sourceforge.net/project/omniorb/omniORB/omniORB-4.2.3/omniORB-4.2.3.tar.bz2
 tar xf omniORB-4.2.3.tar.bz2 
 cd omniORB-4.2.3

Ubuntu上でomniidlをビルドする必要があります。 qnxsdp-env.shを実行していない環境でomniORBのビルドを行いインストールしてください。

 ./configure
 make
 make install

QNXでビルドするために

 #OMNITHREAD_LIB += -lpthread
 OMNITHREAD_LIB += -lsocket

以下のコマンドでビルドしてください。

 make clean
 ./configure --prefix=/home/openrtm/qnx700/target/qnx7/usr/  CC="qcc -V5.4.0,gcc_ntox86_64_gpp" CXX="q++ -V5.4.0,gcc_ntox86_64_gpp" AR=ntox86_64-ar RANLIB=ntox86_64-ranlib --host=x86_64-unknown-linux-gnu
 make
 make install

OpenRTM-aist

omniORB、uuidをpkg-configで検出するために環境変数PKG_CONFIG_PATHを設定してください。

 export PKG_CONFIG_PATH=/home/openrtm/qnx700/target/qnx7/usr/lib/pkgconfig

以下のコマンドでビルドします。

 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist/
 mkdir build
 cd build
 cmake -DCORBA=omniORB -DCMAKE_TOOLCHAIN_FILE=../Toolchain-QNX7.cmake -DCMAKE_INSTALL_PREFIX=/home/openrtm/qnx700/target/qnx7/usr/ ..
 cmake --build . --config Release -- -j$(nproc)

VMWareイメージの入手

VMWare用のイメージを入手するためには、QNX Software Centerでファイルをダウンロードします。

qnx10.png

QNX Software Development Platform->Reference Images->QNX SDP 7.0 x86-64 virtual machine for VMWareをインストールしてください。

qnx.png

インストールしたQNX_SDP.vmxをVMwareで開くと仮想マシンが起動します。

CMakeのオプション一覧

オプション一覧

名前 説明 デフォルト
CORBA 利用するCORBAのライブラリの種類(omniORB、TAO、ORBexpress) omniORB
ORB_ROOT CORBAのライブラリをインストールした場所 設定しない場合、Ubuntu、omniORBの場合はFindPkgConfigで検索。それ以外はエラー
SSL_ENABLE SSLによるセキュアな通信を有効にするためのプラグインを生成するか
ON:生成する
OFF:生成しない
OFF
HTTP_ENABLE HTTP通信を有効にするためのプラグインを生成するか
ON:生成する
OFF:生成しない
OFF
OPENSSL_ROOT OpenSSLの各種ファイルを配置したディレクトリ。Windowsの場合は必須
OBSERVER_ENABLE コンポーネントオブザーバーを有効にするかどうか
ON:有効
OFF:無効
OFF
DOCUMENTS_ENABLE Doxygenでドキュメントを生成するかどうか
ON:生成する
OFF:生成しない
OFF
ROS_ENABLE ROS通信用シリアライザ、インターフェースを生成するか
ON:生成する
OFF:生成しない
OFF
FASTRTPS_ENABLE DDS(Fast-RTPS)通信用インターフェースを生成するか
ON:生成する
OFF:生成しない
OFF
ROS2_ENABLE ROS2通信用シリアライザを生成するか
ON:生成する
OFF:生成しない
OFF
EXAMPLES_ENABLE サンプルコンポーネントを生成するかどうか
ON:生成する
OFF:生成しない
ON
UTILS_ENABLE サンプルコンポーネントを生成するかどうか
ON:生成する
OFF:生成しない
ON
EXTLIB_ENABLE サンプルコンポーネントを生成するかどうか
ON:生成する
OFF:生成しない
ON
FLUENTBIT_ENABLE Fluent Bitロガープラグインを生成するかどうか
ON:生成する
OFF:生成しない
OFF
FLUENTBIT_ROOT Fluent Bitのソースコードのディレクトリ
OPENSPLICE_ENABLE DDS(OpenSplice)通信用インターフェースを生成するか
ON:生成する
OFF:生成しない
OFF
OPENSPLICE_DIR OpenSpliceをインストールしたディレクトリ
RAPIDXML_DIR rapidxmlを展開したディレクトリ

omniORBに関するオプション

名前 説明 デフォルト
OMNI_VERSION omniORBのメジャーバージョン。omniORBを手動でビルド、任意の場所にインストールした場合は必須 設定しなかった場合、LinuxでomniORBがpkg-configでインストールした場合は自動的に設定する。それ以外はエラー
OMNI_MINOR omniORBのマイナーバージョン。omniORBを手動でビルド、任意の場所にインストールした場合は必須 同上
OMNITHREAD_VERSION omniThreadのバージョン。omniORBを手動でビルド、任意の場所にインストールした場合は必須 同上

ビルドを選択可能なモジュールの依存関係

  • OBSERVER_ENABLE
  • DOCUMENTS_ENABLE
  • EXAMPLES_ENABLE
  • UTILS_ENABLE
  • EXTLIB_ENABLE

依存はlibcoil、libRTCのみ。

  • SSL_ENABLE
  • ROS_ENABLE
  • FASTRTPS_ENABLE

EXTLIB_ENABLEがONになっている必要がある。

  • ROS2_ENABLE

FASTRTPS_ENABLEがONになっている必要があるため、FastRTPSTransportのビルドは必須。

omniORBのビルド

Windows

omniORBのビルド

ビルドにはPython、Cygwinのインストールが必要です。

sslTp、httpTp機能を使う場合はOpenSSLのビルドが必要です。

Strawberry Perlをインストールして以下のコマンドを実行する。

 set OPENSSL_INSTALL_DIR=C:/work/openssl_install
 call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
 perl Configure VC-WIN64A --prefix=%OPENSSL_INSTALL_DIR% no-asm shared
 nmake install

omniORBのソースコードを入手します。

mk/platforms/x86_win32_vs_16.mkでPython、OpenSSLのパスを設定します。OPEN_SSL_ROOTを設定しなかった場合でもビルドは可能ですが、sslTp、httpTp機能は使えません。

 PYTHON = /cygdrive/c/Python310/python

 OPEN_SSL_ROOT = /cygdrive/c/work/openssl_install

config/config.mkでビルドする環境を指定してください。

 platform = x86_win32_vs_16

omniORBを展開したフォルダに移動して以下のコマンドを実行してください。

 set PATH=C:\cygwin64\bin;%PATH%;
 call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
 cd src
 make export

次にomniORBpyのビルドを実行します。 まずomniORBpyのソースコードを入手してください。

omniORBpyをomniORBのsrc/lib以下にコピーします。

 omniORB-4.x.y
    |--src
    |    |--lib
    |         |--omniORBpy
    |--mk
    |    |--platforms
    |            |--x86_win32_vs_16
    |--config
         |--config.mk

omniORBpyフォルダに移動してmakeコマンドを実行します。

 cd lib\omniORBpy
 make export

環境変数の設定

omniORB、omniORBpyの動作確認をするためには環境変数PATHPYTHONPATHの設定が必要です。

 set omniORB_DIR=C:/workspace/omniORB-4.3.0
 set PATH=%omniORB_DIR%\bin\x86_win32;%PATH%
 set PYTHONPATH=%omniORB_DIR%\lib\x86_win32;%omniORB_DIR%\lib\python;%PYTHONPATH%

Ubuntu

omniORBのビルド

sslTp、httpTp機能を使う場合はOpenSSLのインストールが必要です。

 sudo apt install libssl-dev

次にomniORBのソースコードを入手してビルドします。

 export PYTHON=/usr/bin/python3
 export OMNIORB_INSTALL_DIR=~/work/omniorb_install
 wget https://jaist.dl.sourceforge.net/project/omniorb/omniORB/omniORB-4.3.0/omniORB-4.3.0.tar.bz2
 tar xf omniORB-4.3.0.tar.bz2
 cd omniORB-4.3.0
 ./configure --prefix=${OMNIORB_INSTALL_DIR} --with-openssl
 make
 make install

omniORBpyのビルドを実行します。

 export PYTHON=/usr/bin/python3
 wget https://jaist.dl.sourceforge.net/project/omniorb/omniORBpy/omniORBpy-4.3.0/omniORBpy-4.3.0.tar.bz2
 tar xf omniORBpy-4.3.0.tar.bz2
 cd omniORBpy-4.3.0
 ./configure --with-omniorb=${OMNIORB_INSTALL_DIR} --prefix=${OMNIORB_INSTALL_DIR} --with-openssl
 make
 make install

環境変数の設定

omniORB、omniORBpyの動作確認をするためには環境変数PATHLD_LIBRARY_PATHPYTHONPATHの設定が必要です。

 export PATH=${OMNIORB_INSTALL_DIR}/bin:$PATH
 export LD_LIBRARY_PATH=${OMNIORB_INSTALL_DIR}/lib:${LD_LIBRARY_PATH}
 export PYTHONPATH=${OMNIORB_INSTALL_DIR}/lib/python3.6/site-packages:$PYTHONPATH

また、pkg-configでomniORBを検出するには以下のように環境変数PKG_CONFIGを設定する。

 export PKG_CONFIG_PATH=${OMNIORB_INSTALL_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH

TAOのビルド

Windows

ACE+TAOのビルド

以下から ACE+TAO.zip をダウンロードしてください。

Visual Studio で ACE と TAO のビルドをします。

ACE+TAO.zip を展開したフォルダーの ace/config-win32.hace/config.h に変更してください。

ACE_vs2019.sln (もしくは ACE_vs2017.sln)を Visual Studio で開いてビルドしてください。 64bitの場合はソリューションプラットフォームがWin32となっている部分をx64に変更してください。

次に以下の環境変数を設定した状態でTAO_vs2019.sln (もしくは TAO_vs2017.sln)を Visual Studio で開いてビルドしてください。

環境変数 内容 設定例
ACE_ROOT ACE_wrappersを展開したフォルダのパス C:/work/ACE_wrappers

 cd TAO
 set ACE_ROOT=C:/work/ACE_wrappers
 TAO_vs2019.sln

Ubuntu

ACE+TAOのビルド

ACE+TAO.tar.gzを入手して以下のコマンドでビルドします。

 export ACE_INSTALL_DIR=~/work/ace_install
 sudo apt-get install gperf
 export ACE_ROOT=${PWD}/ACE_wrappers/build/linux
 export TAO_ROOT=${ACE_ROOT}/TAO
 export LD_LIBRARY_PATH=$ACE_ROOT/ace:$ACE_ROOT/lib
 export INSTALL_PREFIX=$ACE_INSTALL_DIR
 wget https://github.com/DOCGroup/ACE_TAO/releases/download/ACE%2BTAO-7_0_6/ACE+TAO-7.0.6.tar.gz
 tar xf ACE+TAO-7.0.6.tar.gz
 cd ACE_wrappers
 mkdir -p build/linux
 ./bin/create_ace_build build/linux
 echo '#include "ace/config-linux.h"' > build/linux/ace/config.h
 echo 'include $(ACE_ROOT)/include/makeinclude/platform_linux.GNU' > build/linux/include/makeinclude/platform_macros.GNU
 cd build/linux
 make
 make install
 cd TAO
 make
 make install

SSLIOPを有効にする場合は、以下のようにsslオプションを有効にしてSSLIOPをビルドする必要があります。

 cd build/linux
 make ssl=1
 make install ssl=1
 cd TAO
 make SSLIOP ssl=1
 make install ssl=1

環境変数の設定

また、pkg-configでACE+TAOを検出するには以下のように環境変数PKG_CONFIGを設定する。

 export PKG_CONFIG_PATH=${ACE_INSTALL_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH

ネームサーバー起動手順(SSLIOP)

ネームサーバーをSSLIOP通信可能な状態で起動するためには以下のコマンドを実行する。

 ${ACE_INSTALL_DIR}bin/tao_cosnaming -ORBSvcConf server.conf -ORBEndpoint iiop://localhost:/ssl_port=2809

エンドポイントをssliop://localhost:2809のように設定するとcorbaloc形式でのアクセスが上手くいかないため、上記のようにiiop://localhost:/ssl_port=2809と指定する。

server.confは例えば以下のようなファイルを用意する。

 dynamic SSLIOP_Factory Service_Object *
         TAO_SSLIOP:_make_TAO_SSLIOP_Protocol_Factory()
         "-SSLAuthenticate SERVER_AND_CLIENT -SSLPrivateKey PEM:server_key.pem -SSLCertificate PEM:server_cert.pem -SSLCAfile PEM:cacert.pem"
 static Resource_Factory "-ORBProtocolFactory SSLIOP_Factory"

OpenRTM-aistのビルド、動作確認手順

Windows+omniORB

OpenRTM-aistのビルド、インストール

まず、以下の手順でomniORBをビルドしてください。

次にOpenRTM-aistをビルドします。

 set OpenRTM_INSTALL_DIR=C:/work/openrtm_install 
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist
 mkdir build
 cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=%OpenRTM_INSTALL_DIR% -DORB_ROOT=%omniORB_DIR%
 cmake --build . --config Release
 cmake --build . --config Release --target install

OpenRTM-aist-Pythonのビルド、インストール

まずは環境変数PATHPYTHONPATHを設定します。

 set OpenRTMPython_INSTALL_DIR=C:/work/python_install
 git clone https://github.com/OpenRTM/OpenRTM-aist-Python
 cd OpenRTM-aist-Python
 python setup.py build
 python setup.py install --prefix %OpenRTMPython_INSTALL_DIR%

rtshell、rtctree、rtsprofileのビルド、インストール

環境変数PATHPYTHONPATHを設定します。

 git clone https://github.com/OpenRTM/rtctree
 cd rtctree
 python setup.py build
 python setup.py install_lib --install-dir %OpenRTMPython_INSTALL_DIR%\Lib\site-packages

 git clone https://github.com/OpenRTM/rtsprofile
 cd rtsprofile
 python setup.py build
 python setup.py install_lib --install-dir %OpenRTMPython_INSTALL_DIR%\Lib\site-packages

 git clone https://github.com/OpenRTM/rtshell
 cd rtshell
 python setup.py build
 python setup.py install --prefix %OpenRTMPython_INSTALL_DIR%

インストールが完了したら環境変数の設定を行ってください。

Windows+TAO

OpenRTM-aistのビルド、インストール

まず、以下の手順でTAOをビルドしてください。

次にOpenRTM-aistをビルドします。

 set OpenRTM_INSTALL_DIR=C:/work/openrtm_install
 set PATH=%PATH%;%ACE_ROOT%\lib;
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist
 mkdir build
 cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=%OpenRTM_INSTALL_DIR% -DORB_ROOT=%ACE_ROOT%  -DCORBA=TAO
 cmake --build . --config Release
 cmake --build . --config Release --target install

インストールが完了したら環境変数の設定を行ってください。

OpenRTM-aist-Python、rtshell、rtctree、rtsprofileはTAOには対応していません。

Windows共通

環境変数の設定

OpenRTM-aist C++のRTC等を実行するためには環境変数%PATH%を設定する必要があります。

 set PATH=%OpenRTM_INSTALL_DIR%\2.0.0\bin\vc16;%OpenRTM_INSTALL_DIR%\2.0.0\omniORB\4.3.0_vc16\bin\x86_win32;%PATH%

OpenRTM-aist Python、rtctree、rtsprofileを使うためには環境変数PYTHONPATHを設定する必要があります。

 set PYTHONPATH=%OpenRTMPython_INSTALL_DIR%\Lib\site-packages;%OpenRTMPython_INSTALL_DIR%\Lib\site-packages\OpenRTM_aist;%OpenRTMPython_INSTALL_DIR%\Lib\site-packages\OpenRTM_aist\RTM_IDL;%PYTHONPATH%

rtshellを使うためには環境変数PATHの設定が必要です。

 set PATH=%OpenRTMPython_INSTALL_DIR%\Scripts;%PATH%

RTCのビルド

外部のRTCをビルドするためには、CMake実行時にOpenRTMConfig.cmakeをインストールしたパスを指定する必要があります。

 cmake .. -DOpenRTM_DIR=%OpenRTM_INSTALL_DIR%/2.0.0/cmake

環境変数設定スクリプト

OpenRTM-aist C++をインストールすると、環境変数を設定するバッチファイルがインストールされます。

 %OpenRTM_INSTALL_DIR%\2.0.0\ext\environment-setup.omniorb.vc16.bat

このバッチファイルを実行することで以下の環境変数が設定されます。

変数名 設定値 内容
OMNI_ROOT %RTM_ROOT%/omniORB/4.3.0_%RTM_VC_VERSION%/ omniORBをインストールしたフォルダ
OpenRTM_DIR %RTM_ROOT%/cmake OpenRTM-aistのCMake設定ファイルをインストールしたフォルダ
RTM_BASE %OpenRTM_INSTALL_DIR% OpenRTM-aistをインストールしたフォルダ
RTM_IDL_DIR %RTM_ROOT%/rtm/idl OpenRTM-aistのIDLファイルをインストールしたフォルダ
RTM_ROOT %OpenRTM_INSTALL_DIR%/2.0.0 OpenRTM-aistの2.0.0をインストールしたフォルダ
RTM_VC_VERSION vc** ビルドしたVisual Studioのバージョン
PATH %RTM_ROOT%/bin/%RTM_VC_VERSION%;%OMNI_ROOT%/bin/x86_win32;%PATH% PATHにOpenRTM-aist、omniORBの実行ファイルのパスを追加

OpenRTM-aist Python、rtshellの環境変数は設定されません。 Pythonのホームフォルダ(C:\Python37等)にインストールした場合は環境変数の設定は不要ですが、それ以外は手動で設定する必要があります。

Ubuntu+omniORB

まず、以下の手順でomniORBをビルドしてください。

以下の手順で環境変数PKG_CONFIGを設定します。

次にOpenRTM-aistをビルドします。

 export OPENRTM_INSTALL_DIR=$OMNIORB_INSTALL_DIR
 export PATH=$OMNIORB_INSTALL_DIR/bin:$PATH
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist
 mkdir build
 cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

OpenRTM-aist-Pythonのビルド、インストール

まずは環境変数PATHLD_LIBRARY_PATHPYTHONPATHを設定します。

 export OPENRTMPYTHON_INSTALL_DIR=$OMNIORB_INSTALL_DIR
 git clone https://github.com/OpenRTM/OpenRTM-aist-Python
 cd OpenRTM-aist-Python
 python3 setup.py build
 python3 setup.py install --prefix $OPENRTMPYTHON_INSTALL_DIR

rtshell、rtctree、rtsprofileのビルド、インストール

環境変数PATHLD_LIBRARY_PATHPYTHONPATHを設定します。

 git clone https://github.com/OpenRTM/rtctree
 cd rtctree
 python3 setup.py build
 python3 setup.py install_lib --install-dir $OPENRTMPYTHON_INSTALL_DIR/lib/python3.6/site-packages

 git clone https://github.com/OpenRTM/rtsprofile
 cd rtsprofile
 python3 setup.py build
 python3 setup.py install_lib --install-dir $OPENRTMPYTHON_INSTALL_DIR/lib/python3.6/site-packages

 git clone https://github.com/OpenRTM/rtshell
 cd rtshell
 python3 setup.py build
 python3 setup.py install --prefix $OPENRTMPYTHON_INSTALL_DIR

インストールが完了したら環境変数の設定を行ってください。

Ubuntu+TAO

OpenRTM-aistのビルド、インストール

まず、以下の手順でTAOをビルドしてください。

以下の手順で環境変数PKG_CONFIGを設定します。

次にOpenRTM-aistをビルドします。

 export OPENRTM_INSTALL_DIR=$ACE_INSTALL_DIR
 export LD_LIBRARY_PATH=ACE_INSTALL_DIR/lib:$LD_LIBRARY_PATH
 git clone https://github.com/OpenRTM/OpenRTM-aist
 cd OpenRTM-aist
 mkdir build
 cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=$OPENRTM_INSTALL_DIR -DCORBA=TAO
 cmake --build . --config Release -- -j$(nproc)
 cmake --build . --config Release --target install

インストールが完了したら環境変数の設定を行ってください。

OpenRTM-aist-Python、rtshell、rtctree、rtsprofileはTAOには対応していません。

Ubuntu共通

環境変数の設定

OpenRTM-aist C++のRTC等を実行するためには環境変数PATHLD_LIBRARY_PATHを設定する必要があります。

 export PATH=$OPENRTM_INSTALL_DIR/bin:$PATH
 export LD_LIBRARY_PATH=$OPENRTM_INSTALL_DIR/lib:$LD_LIBRARY_PATH

OpenRTM-aist Python、rtctree、rtsprofileを使うためには環境変数PYTHONPATHを設定する必要があります。

 export PYTHONPATH=$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages:$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages/OpenRTM_aist:$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages/OpenRTM_aist/RTM_IDL:$PYTHONPATH

rtshellを使うためには環境変数PATHの設定が必要です。

 export PATH=$OPENRTMPYTHON_INSTALL_DIR/bin:$PATH

omniORBやOpenRTM-aist等をインストールしたパスが同じ場合は以下のコマンドだけ実行します。

 export PATH=$OPENRTM_INSTALL_DIR/bin:$PATH
 export LD_LIBRARY_PATH=$OPENRTM_INSTALL_DIR/lib:$LD_LIBRARY_PATH
 export PYTHONPATH=$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages:$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages/OpenRTM_aist:$OPENRTM_INSTALL_DIR/lib/python3.6/site-packages/OpenRTM_aist/RTM_IDL:$PYTHONPATH

環境変数設定スクリプト

OpenRTM-aist C++をインストールすると、環境変数を設定するバッチファイルがインストールされます。

 source ${OpenRTM_INSTALL_DIR}/etc/environment-setup.sh

このバッチファイルを実行することで以下の環境変数が設定されます。

変数名 設定値 内容
OpenRTM_DIR ${OpenRTM_INSTALL_DIR}/lib/openrtm-2.0/cmake OpenRTM-aistのCMake設定ファイルをインストールしたフォルダ
RTM_IDL_DIR ${OpenRTM_INSTALL_DIR}/include/openrtm-2.0/rtm/idl OpenRTM-aistのIDLファイルをインストールしたフォルダ
PATH ${OpenRTM_INSTALL_DIR}/bin:$PATH PATHにOpenRTM-aist、omniORBの実行ファイルのパスを追加 ]
LD_LIBRARY_PATH ${OpenRTM_INSTALL_DIR}/lib:$LD_LIBRARY_PATH PATHにOpenRTM-aist、omniORBの実行ファイルのパスを追加

OpenRTM-aist Python、rtshellの環境変数は設定されません。 Pythonのホームフォルダ(C:\Python37等)にインストールした場合は環境変数の設定は不要ですが、それ以外は手動で設定する必要があります。

RTCのビルド

外部のRTCをビルドするためには、CMake実行時にOpenRTMConfig.cmakeをインストールしたパスを指定する必要があります。

 cmake .. -DOpenRTM_DIR=${OPENRTM_INSTALL_DIR}/lib/openrtm-2.0/cmake

TAO関連の設定

このページではOpenRTM-aistで通信ミドルウェアにTAOを使用した場合に各種通信プロトコルを使用するための設定ファイルの作成方法を説明します。 TAOではIIOP、DIOP、UIOP、HTIOP、SHMIOP、SSLIOP、SCIOP、MIOP、COIOP、ZIOP通信が使用可能です。 ただし、IIOP、SSLIOP、ZIOP通信以外は独自規格のプロトコルのため、他のCORBA実装との互換性はありません。

DIOP

DIOP(Datagram Inter-ORB Protocol)はGIOPをUDP/IP上の実装であり、IIOP(TCP/IP)と比較すると軽量ですが到達保障がない通信プロトコルです。 IIOP通信との大きな違いとしてCORBAサービスの呼び出しが一方通行であり、戻り値を取ることができません。 例えば、外部のツールからRTCのコンポーネントプロファイルを取得する場合には、DIOP通信では戻り値(コンポーネントプロファイル)を取得できないため使用できません。

OpenRTM-aistでDIOP通信を使用するために、データポートのデータ転送用に以下のoneway属性のメソッドを定義しています。

 module OpenRTM
 {
   interface InPortCdrUDP
   {
     oneway void put(in CdrData data);
   };
 };

実際に使用する場合は、以下の図のようにデータポートのデータ送信にDIOP通信を用いて、それ以外はIIOP等の別の通信で接続する必要があります。


diop.png


以下にrtc.confの設定例を記載します。 IIOPとDIOPのエンドポイントを設定します。

corba.args: -ORBEndpoint iiop://: -ORBEndpoint diop://: -ORBSvcConf svc.conf

svc.confはTAOの設定ファイルです。 svc.confという名前のファイルが実行パスに存在すれば自動的に読み込みますが、ORBSvcConfオプションで明示的に指定もできます。

以下にsvc.confでは以下のようにORBProtocolFactoryの設定を行います。

 static Advanced_Resource_Factory "-ORBProtocolFactory DIOP_Factory -ORBProtocolFactory IIOP_Factory -ORBReactorType select_st"

OpenRTM-aistでインストールされるrtc.diop.conf、svc.confを使用することもできます。

 %RTM_ROOT%Components\C++\Examples\%RTM_VC_VERSION%\ConsoleInComp.exe -f ext\tao_diop\rtc.diop.conf
 %RTM_ROOT%Components\C++\Examples\%RTM_VC_VERSION%\ConsoleOutComp.exe -f ext\tao_diop\rtc.diop.conf

ポート接続時にInterface Typeにcorba_cdr_udpを指定して接続することでDIOP通信によりデータの転送を行います。

RT System EditorではConnector Profileで設定します。


diop2.png


rtc.confではinterface_typecorba_cdr_udpに設定して事前接続設定をします。

 manager.components.preconnect: ConsoleIn0.out?port=rtcname://localhost:2809/*/ConsoleOut0.in&interface_type=corba_cdr_udp

HTIOP

HTIOP(HTTP Tunneling Inter-ORB Protocol)はGIOPメッセージをHTTPパケットで送信する通信プロトコルです。 HTIOP通信の利点としては、ファイアーウォールやHTTPプロキシサーバを経由した通信が容易になる事や、リバースプロキシやロードバランサー等の既存の仕組みを流用しやすいという事が挙げられます。

まずはネームサーバーを起動しますが、ネームサーバーにもHTIOPのエンドポイントを設定する必要があります。 以下の内容の設定ファイルsvc.names.htiop.confを作成してください。

 dynamic HTIOP_Factory Service_Object *
        TAO_HTIOP:_make_TAO_HTIOP_Protocol_Factory ()
        "-config ./HT_Config.conf"
 
 static Resource_Factory "-ORBProtocolFactory HTIOP_Factory"

TAO付属のネームサーバーtao_cosnamingを起動します。 WindowsでOpenRTM-aistをビルドした場合、${RTM_ROOT}/ACE/${RTM_VC_VERSION}/bin/tao_cosnaming.exeにコピーしています。Ubuntuの場合はTAOをインストールした時に${OPENRTM_INSTALL_DIR}/binに入っているものを使用してください。

以下のように作成したsvc.names.htiop.confを指定してtao_cosnamingを起動します。

 ACE\vc16\bin\tao_cosnaming.exe -ORBEndpoint htiop://127.0.0.1:2809 -ORBSvcConf ext/svc.names.htiop.conf

CosoleIn、ConsoleOutコンポーネントを以下の内容のrtc.confで起動します。

 corba.args: -ORBEndpoint htiop:// -ORBSvcConf ext/tao_htiop/svc.htiop.conf
 
 corba.nameservers: corbaloc:htiop:localhost:2809
 corba.master_manager: htiop://127.0.0.1:2810
 
 manager.components.preactivation: ConsoleIn0, rtcname.htiop://localhost:2809/*/ConsoleOut0
 manager.components.preconnect: ConsoleIn0.out?port=rtcname.htiop://localhost:2809/*/ConsoleOut0.in

corba.argsオプションはTAOのORB_init関数への引数を指定します。 HTIOPのエンドポイントとTAOの設定ファイル(ext/svc.htiop.conf)を設定しています。

設定ファイルsvc.htiop.confは以下の内容で作成します。

 dynamic HTIOP_Factory Service_Object *
        TAO_HTIOP:_make_TAO_HTIOP_Protocol_Factory ()
        "-config ext/tao_htiop/HT_Config.conf"
 
 static Advanced_Resource_Factory "-ORBProtocolFactory HTIOP_Factory"

また、接続するネームサーバーの設定を行います。 ネームサーバーはHTIOPのエンドポイント(htiop:localhost:2809)を指定します。

HTIOP通信を使用する場合、RT System EditorやrtshellではRTCを操作できません。 現在のところ、独自にプログラムを作成するか、マネージャ起動時の事前接続(preconnect)、事前アクティブ化(preactivation)の設定を行う必要があります。

HT_Config.confでプロキシサーバーの設定を行うことができます。

 [htbp]
 
 proxy_port=3128
 proxy_host=localhost

以下にHTIOP通信時のHTTPパケットの内容の一例を掲載します。 GETメソッド実行後にPOSTメソッドを実行します。POSTメソッドのボディにGIOPメッセージを格納して送信します。

 GET http://127.0.0.1:2809//1/request1647425846.html HTTP/1.1

 POST http://127.0.0.1:2809//1/request1647418153.html HTTP/1.1
 Content-Type: application/octet-stream
 Content-Length: 123
 
 
 GIOP\x01\x00\x01\x00o\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0c\x00\x00\x00\x01\xc0N\r\x01\x00\x01\x00\t\x01\x01\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00NameService\x00\x06\x00\x00\x00_is_a\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00IDL:omg.org/CosNaming/NamingContextExt:1.0\x00

SSLIOP

SSLIOP(Secure Sockets Layer (SSL) Inter-ORB Protocol)は、GIOPにSSL/TLSによるサーバー・クライアント認証、通信内容の暗号化を適用した通信プロトコルでセキュアな通信が可能になります。

まず、OpenRTM-aistをビルドする時にCMake実行でSSL_ENABLEオプションをオンにしてください。

 cmake .. -DSSL_ENABLE=ON

OpenRTM-aistをビルド、インストール後に、まずはネームサーバーを起動します。 ネームサーバーにはSSLIOPのエンドポイントを指定するため、以下の内容の設定ファイルsvc.names.ssliop.confを作成してください。

 dynamic SSLIOP_Factory Service_Object *
        TAO_SSLIOP:_make_TAO_SSLIOP_Protocol_Factory()
        "-SSLAuthenticate SERVER_AND_CLIENT -SSLPrivateKey PEM:./etc/ssl/server.pem -SSLCertificate PEM:./etc/ssl/root.crt -SSLPassword passward -SSLCAfile PEM:./etc/ssl/root.crt"
 static Resource_Factory "-ORBProtocolFactory SSLIOP_Factory"

SSLPrivateKeyオプションでは秘密鍵、SSLCertificateオプションではサーバー証明書、SSLCAfileではルート証明書を指定します。

TAO付属のネームサーバーtao_cosnamingを起動します。

以下のように作成したsvc.names.ssliop.confを指定してtao_cosnamingを起動します。

 tao_cosnaming -ORBEndpoint iiop://localhost:/ssl_port=2809 -ORBSvcConf etc/svc.names.ssliop.conf

CosoleIn、ConsoleOutコンポーネントを以下の内容のrtc.confで起動します。

 corba.args: -ORBEndpoint htiop:// -ORBSvcConf ./etc/tao_htiop/svc.ssliop.conf
 
 corba.nameservers: corbaloc:ssliop:127.0.0.1:2809
 corba.master_manager: ssliop://127.0.0.1:2810
 
 manager.components.preactivation: ConsoleIn0, rtcname.ssliop://localhost:2809/*/ConsoleOut0
 manager.components.preconnect: ConsoleIn0.out?port=rtcname.ssliop://localhost:2809/*/ConsoleOut0.in

corba.argsオプションはTAOのORB_init関数への引数を指定します。 SSLIOPのエンドポイントとTAOの設定ファイル(ext/svc.ssliop.conf)を設定しています。

''svc.ssliop.conf'は以下の内容で作成します。

 dynamic SSLIOP_Factory Service_Object *
        TAO_SSLIOP:_make_TAO_SSLIOP_Protocol_Factory()
        "-SSLAuthenticate SERVER_AND_CLIENT -SSLPrivateKey PEM:./etc/ssl/server.pem -SSLCertificate PEM:./etc/ssl/root.crt -SSLPassword passward -SSLCAfile PEM:./etc/ssl/root.crt"
 static Advanced_Resource_Factory "-ORBProtocolFactory SSLIOP_Factory"

また、接続するネームサーバーの設定を行います。 ネームサーバーはSSLIOPのエンドポイント(ssliop:127.0.0.1:2809)を指定します。

SSLIOP通信はOMG CORBA Security Service仕様の規格のため、omniORBやOiL等の他の実装との通信も可能です。 このため、rtshellでポートの接続、RTCのアクティブ化の操作ができます。rtshellによるSSLIOP通信の利用方法はについては以下のページを参考にしてください。

rtc.confに記述したように、マネージャ起動時の事前接続(preconnect)、事前アクティブ化(preactivation)の設定を行う事もできます。

SHMIOP

SHMIOP(Shared Memory Inter-ORB Protocol)は共有メモリでGIOPメッセージをやり取りするための通信プロトコルです。 共有メモリの読み書きでデータを転送するためTCP/IP通信での転送と比較するとパフォーマンスの向上が期待できます。 ただし、データの転送は共有メモリですが、データ書き込みの通知にTCP/IP通信を使用しています。

 corba.args: -ORBListenEndpoints shmiop:// -ORBSvcConf /home/nobu/testlib/etc/tao_shmiop/svc.shmiop.conf -ORBDebugLevel 5
 
 
 corba.nameservers: corbaloc:shmiop:1.0@2809
 corba.master_manager: shmiop://1.0@hostname:2810

 static Advanced_Resource_Factory "-ORBProtocolFactory SHMIOP_Factory -ORBProtocolFactory IIOP_Factory -ORBReactorType select_st"

簡単な動作確認

OpenRTM-aistをビルド、インストールすると、上記の通信プロトコルの簡単な動作確認用の設定ファイルがインストールされます。

DIOP

 %RTM_ROOT%\ext\environment-setup.tao.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\tao_diop\rtc.diop.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/tao_diop/rtc.diop.conf

HTIOP

 %RTM_ROOT%\ext\environment-setup.tao.vc16.bat
 %RTM_ROOT%\ACE\vc16\bin\tao_cosnaming.exe  -ORBEndpoint htiop://127.0.0.1:2809 -ORBSvcConf %RTM_ROOT%\ext\svc.names.htiop.conf

 %RTM_ROOT%\ext\environment-setup.tao.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\tao_htiop\rtc.htiop.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -ORBEndpoint htiop://127.0.0.1:2809 -ORBSvcConf  ${OPENRTM_INSTALL_DIR}/etc/svc.names.htiop.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/tao_htiop/rtc.htiop.conf

SSLIOP

 %RTM_ROOT%\ext\environment-setup.tao.vc16.bat
 %RTM_ROOT%\ACE\vc16\bin\tao_cosnaming.exe -ORBEndpoint iiop://localhost:/ssl_port=2809 -ORBSvcConf %RTM_ROOT%\ext\svc.names.ssliop.conf

 %RTM_ROOT%\ext\environment-setup.tao.vc16.bat
 %RTM_ROOT%\Components\C++\Examples\vc16\ConsoleOutComp.exe -f %RTM_ROOT%\ext\tao_ssliop\rtc.ssliop.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/bin/openrtmNames -ORBEndpoint iiop://localhost:/ssl_port=2809 -ORBSvcConf  ${OPENRTM_INSTALL_DIR}/etc/svc.names.ssliop.conf

 source ${OPENRTM_INSTALL_DIR}/etc/environment-setup.sh
 ${OPENRTM_INSTALL_DIR}/share/openrtm-2.0/components/c++/examples/ConsoleOutComp -f ${OPENRTM_INSTALL_DIR}/etc/tao_ssliop/rtc.ssliop.conf

マスターマネージャ、スレーブマネージャ

概要

マネージャ

マネージャはRTCを管理する仕組みです。 1つのプロセスに1つのマネージャが起動します。

マスターマネージャ、スレーブマネージャ

マネージャにはマスターマネージャとスレーブマネージャの2種類あります。 マスターマネージャはスレーブマネージャを管理する上位のマネージャであり、スレーブマネージャはRTCの生成、実行するためのマネージャです。

manager1.jpg

RTSystemEditor等の外部のツールからマスターマネージャのAPIを呼び出すことでRTCの生成、削除などが実行できます。 RTCはマスターマネージャ上では直接起動せずに、マスターマネージャがスレーブマネージャのAPIを呼び出してRTCを起動するように指令します。

manager2.jpg

以下はPythonでマスターマネージャにRTCの生成を指令するプログラムの例です。

 import sys
 from omniORB import CORBA
 import RTM
 
 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
 obj = orb.string_to_object("corbaloc:iiop:localhost:2810/manager")
 mgr = obj._narrow(RTM.Manager)
 
 rtc = mgr.create_component("ConsoleIn&manager_name=samplemaneger")

マスターマネージャを起動する場合はrtcdを-dオプションを付けて実行します。

 rtcd -d -f rtc.conf

rtc.confでモジュール探索パスを設定しておく必要があります。

 manager.modules.load_path: C:/Program Files/OpenRTM-aist/1.2.2/Components/C++/OpenCV/vc14

スレーブマネージャを起動する場合は特にオプションは必要ありませんが、rtc.confでマネージャ名、モジュール探索パスを設定してください。 またデフォルトの設定ではRTCが1つも実行してない場合にマネージャを自動終了する機能があるためそれをオフにしてください。

 manager.instance_name: samplemaneger
 manager.modules.load_path: C:/Program Files/OpenRTM-aist/1.2.2/Components/C++/OpenCV/vc14
 manager.shutdown_auto:NO

API

load_module

unload_module

get_loadable_modules

get_loaded_modules

get_factory_profiles

create_component

create_componentはRTCを生成するためのAPIです。 以下のように引数に起動するRTCのベンダ名、カテゴリ名、コンポーネント名、言語名、バージョン番号を入力することでRTCを生成します。

 mgr.create_component("RTC:AIST:Example:ConsoleIn:C++:1.0.0")

引数の文字列は以下のような内容で入力します。

 RTC:[vendor]:[category]:[implementation_id]:[version]

ただし、implementation_id以外は省略できるため、以下のようにRTC名だけを入力しても生成できます。

 mgr.create_component("ConsoleIn")

RTCはスレーブマネージャ上で起動しますが、RTCを起動するスレーブマネージャを指定する場合は以下のようにmanager_nameのオプションで指定します。

 mgr.create_component("ConsoleIn&manager_name=samplemaneger")

起動するスレーブマネージャをアドレスとポート番号を指定してRTCを起動する場合はmanager_addressのオプションで指定します。

 mgr.create_component("Flip&manager_address=localhost:2811")

マネージャの動作について

スレーブマネージャ名を指定した場合に指定のスレーブマネージャが起動していない場合

manager_nameオプションでスレーブマネージャ名を指定した場合に指定のスレーブマネージャが起動していない場合、マスターマネージャは指定の名前のスレーブマネージャを起動します。 例えば、以下のsamplemanegerという名前のスレーブマネージャが起動していない場合、新たにsamplemanegerという名前のスレーブマネージャを起動します。

 mgr.create_component("ConsoleIn&manager_name=samplemaneger")

スレーブマネージャ名を指定しない場合

以下のようにmanager_nameオプションを指定しない場合、manager_[プロセスID]の名前のスレーブマネージャを新たに起動します。

 mgr.create_component("ConsoleIn")

同一コンポーネント名のRTCがロード可能な場合

例えばOpenRTM-aistのサンプルコンポーネントにはC++、Python、Javaで実装したConsoleInコンポーネントの3種類が使用できます。 同一コンポーネント名のRTCを区別して起動する場合、以下のように言語名で区別することができます。

 mgr.create_component("RTC:AIST:Example:ConsoleIn:Python:1.0.0")

言語名でも区別できない場合は、予めRTCを起動するスレーブマネージャを起動しておいて、create_componentでマネージャ名を指定することで対応できます。

delete_component

get_components

get_component_profiles

get_components_by_name

get_profile

get_configuration

set_configuration

is_master

get_master_managers

add_master_manager

remove_master_manager

get_slave_managers

スレーブマネージャのAPIを直接呼び出す場合はget_slave_managersでマスターマネージャからスレーブマネージャを取得して実行します。 以下は指定の名前のスレーブマネージャでモジュールをロードしてRTCを起動する例です。

 import sys
 from omniORB import CORBA
 import RTM
 import OpenRTM_aist
 
 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
 obj = orb.string_to_object("corbaloc:iiop:localhost:2810/manager")
 mgr = obj._narrow(RTM.Manager)
 print(mgr.create_component("Flip&manager_name=samplemaneger"))
 
 
 def getSlaveManager(master, slavename):
     slavemgrs = master.get_slave_managers()
     for slavemgr in slavemgrs:
         prof = slavemgr.get_configuration()
         prop = OpenRTM_aist.Properties()
         OpenRTM_aist.NVUtil.copyToProperties(prop, prof)
         name = prop.getProperty("manager.instance_name")
         if name == slavename:
             return slavemgr
     return None
 
 
 samplemaneger = getSlaveManager(mgr, "samplemaneger")
 samplemaneger.load_module(
     "C:\\Program Files\\OpenRTM-aist\\1.2.2\\Components\\C++\\Examples\\vc14\\ConsoleIn.dll", "ConsoleInInit")
 samplemaneger.create_component("ConsoleIn")

add_slave_manager

remove_slave_manager

fork

shutdown

restart

get_service