このページではRaspberry PiマウスとLEGO Mindstorms EV3を連携したRTシステムの構築を行います。
Raspberry Piマウスをアクセスポイントとして、ノートPCとEV3をアクセスポイントに接続します。
※Raspberry Piマウスと同じ番号のEV3を使用するようにしてください。
EV3 には以下のデバイスが付属しています。
まず、EV3本体を土台に装着します。
Lモーター右 | ポート C | 25cmケーブル |
Lモーター左 | ポート B | 25cmケーブル |
他のデバイスを取り付ける場合は、チュートリアル(EV3)を参考にしてください。
第二部の、実機での動作確認まで完了してください。 この時点でノートPCとアクセスポイントのRaspberry Piが接続されているはずです。
中央のボタンを押せば電源が投入されます。
EV3 の電源を切る場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Power Off」を選択してください。
再起動する場合は最初の画面で EV3 本体の左上の戻るボタンを押して「Reboot」を選択してください。
ev3dev の起動が途中で停止する場合には、中央ボタン、戻るボタン(左上)、左ボタンを同時押ししてください。画面が消えたら戻るボタンを離すと再起動します。
EV3の電源を投入してください。
起動後にRaspberry Piに自動接続します。 自動接続できた場合は、EV3の画面左上にIPアドレスが表示されます。 IPアドレスは192.168.11.yyyが表示されます。
EV3の画面上の操作でネームサーバーとRTCを起動します。
EV3 の操作画面から「File Browser」→「scripts」を選択してください。
ネームサーバー、RTCはstart_rtcs.shのスクリプトを実行することで起動します。
------------------------------ 192.168.11.yyy ------------------------------ File Browser ------------------------------ /home/robot/scripts ------------------------------ ../ Component/ ・・ [start_rtcs.sh ] ------------------------------
RTシステムエディタから、192.168.11.yyyのネームサーバーに接続してください。
この時点でRTシステムエディタのネームサービスビューにはlocalhost、192.168.11.1、192.168.11.yyyのネームサーバーが登録されています。 192.168.11.yyyのネームサーバーに登録されているRTCの名前はEducatorVehicle1となります。
RaspberryPiMouseRTC0(192.168.11.1)とEducatorVehicle1(192.168.11.yyy)をシステムダイアグラム上で接続してください。 EducatorVehicle0の現在の速度出力をRaspberryPiMouseRTC0の目標速度入力に接続することで、EV3の動きにRaspberry Piマウスが追従するようになります。
これで実習は一通り終了ですが、時間が余っている場合は以下のような課題に挑戦してみてください。
EV3のタッチセンサーのオンオフでRaspberry Piマウスを前進後退させるRTシステムを作成します。
EV3とタッチセンサーを35cmケーブルで接続してください。
タッチセンサー右 | ポート 3 | 35cmケーブル |
タッチセンサー左 | ポート 1 | 35cmケーブル |
以下のような仕様のRTCを作成します。
コンポーネント名称 | SampleTouchSensor |
InPort | |
ポート名 | touch |
型 | TimedBooleanSeq |
説明 | タッチセンサーのオンオフ |
OutPort | |
ポート名 | target_velocity |
型 | TimedVelocity2D |
説明 | 目標速度 |
Configuration | |
パラメーター名 | speed |
型 | double |
デフォルト値 | 0.2 |
説明 | タッチセンサがオンの時の直進速度の設定 |
アクティビティでonExecuteを有効にしてください。
SampleTouchSensorのonExecute関数に以下のように記述します。
RTC::ReturnCode_t SampleTouchSensor::onExecute(RTC::UniqueId ec_id) { //新規データの確認 if (m_touchIn.isNew()) { //データの読み込み m_touchIn.read(); //配列の要素数が1以上かを確認 if (m_touch.data.length() == 2) { //0番目のデータがオンの場合は直進する指令を出力 //0番目のデータは右側のタッチセンサに対応 if (m_touch.data[0]) { //目標速度を格納 m_target_velocity.data.vx = m_speed; m_target_velocity.data.vy = 0; m_target_velocity.data.va = 0; setTimestamp(m_target_velocity); //データ出力 m_target_velocityOut.write(); } //1番目のデータがオンの場合は後退する指令を出力 //1番目のデータは左側のタッチセンサに対応 else if (m_touch.data[1]) { //目標速度を格納 m_target_velocity.data.vx = -m_speed; m_target_velocity.data.vy = 0; m_target_velocity.data.va = 0; setTimestamp(m_target_velocity); //データ出力 m_target_velocityOut.write(); } //オフの場合は停止する else { //目標速度を格納 m_target_velocity.data.vx = 0; m_target_velocity.data.vy = 0; m_target_velocity.data.va = 0; setTimestamp(m_target_velocity); //データ出力 m_target_velocityOut.write(); } } } return RTC::RTC_OK; }
データポートを以下のように接続後、タッチセンサをオンオフするとRaspberry Piが前進後退します。
以下GUIジョイスティックでRaspberry Piマウス、EV3を操作するRTシステムを作成します。
ジョイスティックコンポーネントはOpenRTM-aist Python版のサンプルにあります(TkJoyStickComp.py)。 ジョイスティックコンポーネントは、Windows 8.1の場合は「スタート」>「アプリビュー(右下矢印)」>「OpenRTM-aist 1.2.0」>「Python_Examples」をクリックして、エクスプローラーで「TkJoyStickComp.bat」をダブルクリックして起動してください。
TkJoyStickComp.pyのアウトポートのデータ型はTimedFloatSeq型であるため、TimedVelocity2D型に変換するRTCを作成する必要があります。
以下のような仕様のRTCを作成してください。
コンポーネント名称 | FloatSeqToVelocity |
InPort | |
ポート名 | in |
型 | TimedFloatSeq |
説明 | 変換前のデータ |
OutPort | |
ポート名 | out |
型 | TimedVelocity2D |
説明 | 変換後のデータ |
Configuration | |
パラメーター名 | rotation_by_position |
型 | double |
デフォルト値 | -0.02 |
説明 | ジョイスティックのX座標の位置に対する角速度の変化量 |
Configuration | |
パラメーター名 | velocity_by_position |
型 | double |
デフォルト値 | 0.002 |
説明 | ジョイステックのY座標に対する速度の変化量 |
アクティビティはonExecuteをオンにしてください。
onExecute関数を以下のように編集してください。
RTC::ReturnCode_t FloatSeqToVelocity::onExecute(RTC::UniqueId ec_id) { //新規データの確認 if (m_inIn.isNew()) { //データの読み込み m_inIn.read(); //配列のデータ数確認 if (m_in.data.length() >= 2) { //目標速度格納 m_out.data.vx = m_in.data[1] * m_velocity_by_position; m_out.data.vy = 0; m_out.data.va = m_in.data[0] * m_rotation_by_position; setTimestamp(m_out); //目標速度出力 m_outOut.write(); } } return RTC::RTC_OK; }
以下のようにデータポートを接続してください。
EducatorVehicleRTCのsoundという名前のインポートに文字列(TimedString型)を入力すると、EV3が発声します。
以下のような仕様のRTCを作成してください。
コンポーネント名称 | SpeechSample |
OutPort | |
ポート名 | out |
型 | TimedString |
説明 | 発話する文字列 |
アクティビティはonExecuteをオンにしてください。
onExecute関数を以下のように編集してください。
RTC::ReturnCode_t SpeechSample::onExecute(RTC::UniqueId ec_id) { std::cout << "Please input: "; std::string ret; //文字入力 std::cin >> ret; //データに格納 m_out.data = CORBA::string_dup(ret.c_str()); setTimestamp(m_out); //データ出力 m_outOut.write(); return RTC::RTC_OK; }
文字列(const char*)をデータポートで出力する際はCORBA::string_dup関数で文字列をコピーする必要があります。
m_out.data= CORBA::string_dup("abc");
以下のようにデータポートを接続してください。
Raspberry Piマウスを起動すると、OpenCVCameraコンポーネントとarptコンポーネントが起動します。 OpenCVCameraコンポーネントは画像を取得するコンポーネント、artpコンポーネントは画像データからマーカの位置姿勢を計算して出力するコンポーネントです。
まずはカメラをRaspberry Piマウスに装着します。
以下の土台部品をRaspberry Piマウスに取り付けていきます。
以下の仕様でRTCを作成してください。
コンポーネント名称 | testARToolKit |
InPort | |
ポート名 | marker_pos |
型 | TimedPose3D |
説明 | マーカーの位置 |
OutPort | |
ポート名 | target_vel |
型 | TimedVelocity2D |
説明 | ロボットの目標速度 |
Configuration | |
パラメーター名 | x_distance |
型 | double |
デフォルト値 | 0.5 |
説明 | マーカーまでの目標距離(X軸) |
Configuration | |
パラメーター名 | y_distance |
型 | double |
デフォルト値 | 0 |
説明 | マーカーまでの目標距離(Y軸) |
Configuration | |
パラメーター名 | x_speed |
型 | double |
デフォルト値 | 0.1 |
説明 | X軸方向移動速度 |
Configuration | |
パラメーター名 | r_speed |
型 | double |
デフォルト値 | 0.2 |
説明 | 回転方向移動速度 |
Configuration | |
パラメーター名 | error_range_x |
型 | double |
デフォルト値 | 0.1 |
説明 | X軸方向目標距離の許容範囲 |
Configuration | |
パラメーター名 | error_range_y |
型 | double |
デフォルト値 | 0.05 |
説明 | Y軸方向目標距離の許容範囲 |
アクティビティはonExecuteをONにしてください。
onExecuteを以下のように編集してください。
RTC::ReturnCode_t testARToolKit::onExecute(RTC::UniqueId ec_id) { //新規データの確認 if (m_marker_posIn.isNew()) { m_target_vel.data.vx = 0; m_target_vel.data.vy = 0; m_target_vel.data.va = 0; //データの読み込み m_marker_posIn.read(); //マーカーの位置(X軸)が目標距離(X軸)よりも大きい場合 if (m_marker_pos.data.position.x > m_x_distance + m_error_range_x/2.0) { m_target_vel.data.vx = m_x_speed; } //マーカーの位置(X軸)が目標距離(X軸)よりも小さい場合 else if (m_marker_pos.data.position.x < m_x_distance - m_error_range_x/2.0) { m_target_vel.data.vx = -m_x_speed; } //マーカーの位置(Y軸)が目標距離(Y軸)よりも大きい場合 else if (m_marker_pos.data.position.y > m_y_distance + m_error_range_y/2.0) { m_target_vel.data.va = m_r_speed; } //マーカーの位置(Y軸)が目標距離(Y軸)よりも小さい場合 else if (m_marker_pos.data.position.y < m_y_distance - m_error_range_y/2.0) { m_target_vel.data.va = -m_r_speed; } setTimestamp(m_target_vel); //データ書き込み m_target_velOut.write(); } return RTC::RTC_OK; }
データポートを以下のように接続してください。