UEC Tokyo
Dept. of Mechanical Engineering and Intelligent Systems
OpenRTMを使ってみよう!
-
基本編-
電気通信大学情報理工学研究科
知能機械工学専攻
長井隆行、中村友昭
RTMとは
R
obot
T
echnology
M
iddleware
コンポーネント(モジュール)を動かす実行環境のこと
ミドルウェア上で動作するコンポーネントであればOS・言語等
に関係なく通信が可能
DiGORO ⇨ ClientNet+サーバー(DiGORO Net)に相当
RTM上で動くものであれば、他の人が作成したコンポー
ネントを使用できる(再利用性が高い)
RTミドルウェア チャット コンポーネント1 チャット コンポーネント2 Windows, C# Linux, C++ カメラ 音声 アーム 台車 RTミドルウェア RTMよるロボットの構成OpenRTM
RTMの実装の1つ
DiGORO Net, ROS, OpenRTM等がある
DiGORO Net : 長井研ローカル、再利用性低い
ROS : Windowsのサポートがいまいち
OpenRTM : 国産、様々なOSに対応、資料が日本語
OpenRTMとDiGOROの違い
DiGORO
単純なデータの送信のみをサポート
OpenRTM
データだけでなく機能を変更するようなクラスも送受信可能 その他いろんな機能があるみたい 開発言語
OpenRTM-aist
オリジナルのOpenRTMで産総研が開発 C++, Python, Javaに対応 なんか使いづらい
OpenRTM.Net, PyRTSeam
株式会社セックが改良 (http://www.sec.co.jp/robot/) C#, C++/CLI, Python 非常に使いやすいが、C++が使えない
とりあえず
C++/CLI ⇨ C++と互換性ありOpenRTM.NETのC++/CLIで作ってみよう!
C++/CLI
C++ / Common Language Interface
C++と.Net(MSが作った言語)が同時に使用可能
.Netの概要
関数は存在せず全てクラスになっている
int, float, double等数値(数値型)以外は全てクラス(参照クラス)
int, float, double等数値型も実はクラス(ボックス化)
.Netのクラスの宣言には^を付ける
(参照クラス=高機能ポインタ)
C++ : Class c;
.Net : Class ^c;
.Netのクラスはgcnew(garbage collection new)しなければならない (ポインタと同じなので生成が必要)
Class ^c = gcnew Class();
C++/CLI
例:C++と.Netを同時使用した例
int arr1[10]; // C++配列の宣言
array<int> ^arr2 = gcnew array<int>(10); // .Netの配列クラスの宣言
// 代入
for(int i=0 ; i<10 ; i++ ){ arr1[i] = i; arr2[i] = i; }
// 表示
for(int i=0 ; i<10 ; i++ ){
printf("%d %d¥n" , arr1[i] , arr2[i] ); }
インストール
以下の2つを順にインストール
¥¥Mammoth¥AtHome¥OpenRTM¥OpenRTM-aist-1.1.0-RC3_vc9.msi
¥¥Mammoth¥AtHome¥OpenRTM¥OpenRTM.NET-1.3.0.msi
Javaを最新版にする
http://www.java.com/ja/
実験PCはインストール済みなので必要ない
サンプルの起動
ネーミングサービスの開始 [スタータ]→[プログラム]→[OpenRTM.Net]→[ツール] →[ネーミングサービスの開始] コンポーネント起動 [スタータ]→[プログラム]→[OpenRTM.Net]→[サンプル]→[バイナリ] SimpleIO¥ConsoleIn¥ConsoleIn.Exe SimpleIO¥ConsoleOut¥ConsoleOut.Exe コンポーネント接続プログラムを起動 [スタータ]→[プログラム]→[OpenRTM-aist 1.1]→[C++]→[tools] →[RTSystemEditor]RT System Editor
コンポーネント同士を接続するためのGUIプログラム
ONにする 現在起動 中のコン ポーネント 2つのコンポネントを ドラッグアンドドロップコンポーネントの接続
コンポーネント同士の入力ピンと出力ピンの接続
一方のピンをドラッグし、 もう一方のピンへドロップ 出力ピン 入力ピン 右クリック ⇓ All Activateコンポーネントの通信
I/F name: ConsoleIn0.out
I/F type: IDL:RTC/TimedLong:1.0 Polarity: PROVIDED
I/F name: ConsoleIn0.out
I/F type: OpenRTM.Core.TimedLong Polarity: PROVIDED
Properties
port.port_type: DataOutPort
dataport.data_type: IDL:RTC/TimedLong:1.0 dataport.dataflow_type: push, pull
dataport.subscription_type: flush, new, periodic dataport.interface_type: corba_cdr, local
Please Input Number> 10 Please Input Number>
ConsoleIn
I/F name: ConsoleOut0.in
I/F type: IDL:RTC/TimedLong:1.0 Polarity: REQUIRED
I/F name: ConsoleOut0.in
I/F type: OpenRTM.Core.TimedLong Polarity: REQUIRED
Properties
port.port_type: DataInPort
dataport.data_type: IDL:RTC/TimedLong:1.0 dataport.dataflow_type: push, pull
dataport.subscription_type: any
dataport.interface_type: corba_cdr, local time = 2012/03/12 9:07:25
data = 10
ConsoleOut
コンポーネントの作り方
ダイアログのテンプレートから作成 DiGOROClientRTC_MFC ver0.7 送受信できる型(すべて.Netのクラス) TimedLong :整数型 TimedString :文字列型 TimedDouble :少数型 TimedLongSeq :整数配列 TimedStringSeq :文字列配列 TimedDoubleSeq : 少数配列 これ以外にも、Float, Short, ULong等一般的な型が存在
タイムスタンプとデータから構成
TimedLong ^data = gcnew TimedLong();
data->Data = 10; // Data : 整数型
ロボット向け拡張データ型
TimedVelocity2D
data ⇒ Data ⇒
double VelocityX, double VelocityY, double VelocityYaw
data ⇒ Time
例)
double velYaw = 0.0;
TimedVelocity2D ^data = gcnew TimedVelocity2D(); //ロボットの移動 pThis->m_component->GetInData( data ) //データの受信 velYaw = data->Data->VelocityYaw;
送受信するデータの定義
「PortDefine.h」で定義
#define MODULE_NAME "DiGOROTest"
// 入力ポートの定義 // INPORT( type , name ) // type : 送信するデータ型 // name : 名前
INPORT( TimedLong , InData )
// 出力ポートの定義
// OUTPORT( type , name ) // type : 送信するデータ型 // name : 名前
OUTPORT( TimedLong , OutData )
入力ポート(受信するデータ)の定義 TimedLong(整数型)を受信
出力ポート(送信するデータ)の定義 TimedLong(整数型)を送信
INPORT( TimedString , InData2)
複数個宣言することも可能
送信方法
例:DiGOROClientRTCDlg.cpp
void CDiGOROClientRTCDlg::OnBnClickedButton1() {
// .Netのクラスなので、とりあえず^を付けてgcnew
TimedLong ^data = gcnew TimedLong(); // 送信したいデータを代入 data->Data = 10; // 現在時刻を代入 TimeExtension::SetCurrentTime( data->Time ); // 送信 // 送信用の関数名は、Send + [変数名] m_component->SendOutData( data ); }
受信方法
例:MyThread.cpp
// .Netのクラスなのでとりあえず^をつける TimedLong ^data; // 受信用関数名は Get + [変数名]if( pThis->m_component->GetInData( data ) ) // データがあれば戻り値がtrue
{ CString str; // 整数型を文字列に変換 str.Format( "%d" , data->Data ); // メッセージボックスへ表示 AfxMessageBox( str ); // さらにデータを足して、他のコンポネントへ送信 data->Data += 100; pThis->m_component->SendOutData( data );