RTCを組み合わせてロボットを作ろう
イベントハンドラの実装
使用するイベントハンドラはonExecuteのみです。スケルトンコードからonExecute部分のコメントをはずしてください。
まず、画像処理RTCからの入力があった場合、画像中の物体のx位置座標(水平方向)が正しい値(0~320)であるか確認し、正しい値であった場合は物体が認識できた、として以下の処理をします。
・それまで物体が認識できていなかった場合は、新たにカメラ前に物体が現れたとし、音声合成RTCに「こんにちは」というせりふを送信する
・物体が認識できている場合は、物体の重心位置と、画像中の中心位置とのずれをモータへの角度指令に換算し、物体の方向にカメラを向ける
・物体が認識できない場合は、モータの角度を0度の位置に向ける
サンプルコードはこちらからダウンロードしてください。
RTC::ReturnCode_t RobotMain::onExecute(RTC::UniqueId ec_id) { if(m_inIn.isNew()) { // もし画像処理結果を受け取ったら m_inIn.read(); if(m_in.data.length() == 2) { double x = m_in.data[0]; // xは横[0, 320] double y = m_in.data[1]; // yは縦[0, 240],ただし原点は画像左上 static int inSightFlag; // 物体が見えている状態フラグ static float motor_target_radian; // モータの目標位置 if(x >= 0 && x // 画像内に明るい物体がある if(!inSightFlag) { // 今までは見えていなかったら const char* str = "こんにちわ"; // 台詞を送信 m_stringOut.data = str; m_stringOutOut.write(); inSightFlag = 1; } float pos_x = (float)(x - 160.0); // 物体のx方向位置 motor_target_radian += 0.10f * pos_x / 160; // モータ目標値計算 m_motorOut.data = motor_target_radian; // モータ目標値送信 m_motorOutOut.write(); } else { // 見えなくなったら inSightFlag = 0; // フラグOFF motor_target_radian *= 0.8f; // モータ目標値がゼロに近づく m_motorOut.data = motor_target_radian; // モータ目標値送信 m_motorOutOut.write(); } } } return RTC::RTC_OK; } |
図2-1:イベントハンドラの実装
-------------------------------------------
図2-2:今回作成したロボットの動作
RTシステムの動作
まず、これまでの記事で開発したRTCの実行ファイルとrtc.conf、および使用するライブラリ群 (rtc.zip:RTCs.zip) をダウンロードしてください。
ロボットは前回(http://thinkit.jp/article/963/1/) 作成したRCサーボ制御のテスト機を使います。RCサーボのサーボホーンの上に両面テープなどでカメラを設置してください。
RCサーボをお持ちでない方も、カメラおよび音声合成の部分のみで動作確認ができます。
いつもどおり、ネームサーバーを起動し、RT System Editorを起動したのち、「USBCameraAcquire(OpenRTM-aistのサンプル)」「BinarizeComp(第2回で作 成)」「AquesTalkVoiceComp(第3回で作成)」「iMCs04ControlComp(第4回で作成)」を実行し、今回の RobotMainCompを実行します。
RT System EditorでRTCを接続し、すべてのRTCをActivateします。ロボットの動作は図2-2の動画を見てください。
場合によっては、カメラの画角が狭く動作がぎこちなく感じることがあると思います。お使いのカメラやサーボにあわせてモータへの指令値を調整するとよい でしょう。係数をコンフィグレーションとするとよいかもしれません。
また第2回で開発した画像処理RTCにコンフィグレーションを追加し、2値化処理のしきい値を変更できるようにすると効果的です。