ダウンロード
最新バージョン : 2.0.2-RELESE
| 2.0.2-RELESE | ダウンロードページ |
OpenRTM@Github
OpenRTM-aist GitHubサイト
ROS
Robot Operating System
Choreonoid
モーションエディタ/シミュレータ
DAQ-Middleware
ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク
産総研が提供するRTC集
東京オープンソースロボティクス協会
| 2.0.2-RELESE | ダウンロードページ |
OpenRTM-aist GitHubサイト
Robot Operating System
モーションエディタ/シミュレータ
ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク
産総研が提供するRTC集
東京オープンソースロボティクス協会
データポートのあるコンポーネント
ここでは、データポートのあるコンポーネントを二つ作成し、二つのコンポーネント間でデータの送受信を行ってみます。 作成するコンポーネントの仕様は以下の通りです。
rtc-template によるソース生成
上記の仕様を持つコンポーネントを作成する為に以下のようなシェルスクリプトを gen.sh という名前で用意します。
最初の rtc-template の実行でコンポーネント1:ConsoleInComp、次の rtc-template の実行でコンポーネント2:ConsoleOutComp が作成されます。
ConsoleIn の実装
生成されたソースを編集して、ConsoleIn コンポーネントを実装していきます。
ConsoleIn.h
このコンポーネントはアクティブ化されたときに、入力待ちを行い入力された値を OutPort から出力するコンポーネントです。 従って、アクティブ状態の時にループ実行される onExecute メンバ関数のみ実装すればよいので、生成された ConsoleIn.h を以下のようにコメントアウトされている onExecute 関数のコメントをはずします。
:略 // The execution action that is invoked periodically // former rtc_active_do() virtual RTC::ReturnCode_t onExecute(RTC::UniqueId ec_id); :略また、ConsoleIn.h の下の方に、rtc-template で指定した OutPort の変数宣言があります。
TimedLong m_out と宣言されているのが、OutPort にバインドされる変数。
OutPort<TimedLong> m_outOut と宣言されているのが、OutPort のインスタンスです。
ConsoleIn.cpp
ConsoleInの 実装は簡単です。 コメントアウトされている onExecute のコメントをはずし、以下のように実装します。
RTC::ReturnCode_t ConsoleIn::onExecute(RTC::UniqueId ec_id) { std::cout << "Please input number: "; std::cin >> m_out.data; std::cout << "Sending to subscriber: " << m_out.data << std::endl; m_outOut.write(); return RTC::RTC_OK; }ConsoleOut の実装
ConsoleOut コンポーネントは少し複雑です。 InPort に入ってきたデータにコンフィギュレーションパラメーター multiply を掛けた値を格納しなければなりません。 これは、InPort にコールバックオブジェクトをセットするという方法で実現できます。
コールバックオブジェクト
コールバックオブジェクトとは、InPort や OutPort のバッファにあるイベントが発生したときに呼ばれるoperator()が定義されたオブジェクトです。 今回は、InPort のバッファに書き込まれるときに値を変換する為のコールバック OnWriteConvert を使用します。
RTC::OnWriteConvert を継承して以下のようなクラスを定義します。
class Multiply : public RTC::OnWriteConvert<RTC::TimedLong> { int& m_mul; public: Multiply(int& multiply) : m_mul(multiply) {}; RTC::TimedLong operator()(const RTC::TimedLong& value) { RTC::TimedLong ret(value); ret.data = value.data * m_mul; return ret; }; };ConsoleOut.h
上記のコールバッククラスを ConsoleOut.h の include の行の直後に挿入します。 さらに、このコールバッククラスのインスタンスを ConsoleOut クラスのメンバ変数として宣言します。 場所は、private のすぐ下辺りでよいでしょう。
このコンポーネントはアクティブ化されたときに、InPort からデータを読み込み標準出力にデータを表示するコンポーネントです。 従って、アクティブ状態の時にループ実行される onExecute メンバ関数のみ実装すればよいので、生成された ConsoleOut.h を以下のようにコメントアウトされている onExecute 関数のコメントをはずします。
:略 // The execution action that is invoked periodically // former rtc_active_do() virtual RTC::ReturnCode_t onExecute(RTC::UniqueId ec_id); :略また、ConsoleOut.h の下の方に、rtc-template で指定したコンフィギュレーション変数の宣言と InPort の変数宣言があります。
ConsoleOut では InPort のバッファとして RingBuffer を使用するので、RingBuffer.h をインクルードする必要があります。 ConsoleOut.h の先頭部分をで以下のように RingBuffer.h をインクルードしてください。
また、InPort の宣言部分でデフォルトでは InPort<TimedLong> m_inIn となっているところを InPort<TimedLong, RTC::RingBuffer> m_inIn のように書き換えて、InPort が RingBuffer を使用するように変更してください。
:略 // Configuration variable declaration // <rtc-template block="config_declare"> int m_multiply; // </rtc-template> // DataInPort declaration // <rtc-template block="inport_declare"> TimedLong m_in; InPort<TimedLong, RTC::RingBuffer> m_inIn;int m_multiplyと宣言されているのが、コンフィギュレーション「multiply」にバインドされる変数。
TimedLong m_in と宣言されているのが、InPort にバインドされる変数。
InPort<TimedLong> m_inIn と宣言されているのが、InPort のインスタンスです。ConsoleOut.cpp
ConsoleOutクラスのコンストラクタで、先ほど定義した Multiply のインスタンスの初期化を追加します。
ConsoleOut::ConsoleOut(RTC::Manager* manager) : RTC::DataFlowComponentBase(manager), // <rtc-template block="initializer"> m_inIn("in", m_in), // </rtc-template> m_owc(m_multiply), dummy(0)「m_owc(m_multiply),dummy(0)」 の部分を追加するだけでなく、「m_inIn("in", m_in)」を「m_inIn("in", m_in),」と変更することも忘れずに(カンマ「,」の追加もれに注意)。
さらに、コールバックオブジェクトを InPort に追加する為、コンストラクタ内で以下のように記述します。
m_inIn.setOnWriteConvert(&m_owc); //これを追加 // Registration: InPort/OutPort/Service // <rtc-template block="registration"> // Set InPort buffers registerInPort("in", m_inIn);コメントアウトされている onExecute のコメントをはずし、以下のように実装します。
RTC::ReturnCode_t ConsoleOut::onExecute(RTC::UniqueId ec_id) { if (m_inIn.isNew()) { m_inIn.read(); std::cout << "Received: " << m_in.data << std::endl; std::cout << "TimeStamp: " << m_in.tm.sec << "[s] "; std::cout << m_in.tm.nsec << "[ns]" << std::endl; } usleep(1000); return RTC::RTC_OK; }コンパイル
実装が終わったら以下のようにソースをコンパイルします。
コンパイルエラーが出た場合はスペルミスなどがないかどうかチェックして再度コンパイルを行ってください。
実行
* 適切な rtc.conf とは… 次に一例をしめします。
ConsoleIn を実行したターミナルで、入力を促す Please input number: という表示が出るので、適当な数字を入力します。
ConsoleOut を実行したターミナルでは、以下のように表示されるはずです。
次に RtcLink のコンフィギュレーションビューで multiply の値を10に変更してみましょう。すると、ConsoleIn から上記のように入力すると、以下のようにそれぞれ10倍された値が出力されるはずです。