Up:Tutorial? Previous:車輪移動ロボット Next: 眼球運動
SIGVerseでは距離センサはカメラを用います。 ここではSIGViewerサービスから距離データを取得するサンプルを紹介します。
カメラから取得可能な距離データは3つあります。一つ目はカメラから視線方向にあるオブジェクトまでの点と点の距離(スカラ値)、2つ目はエージェントの視線から水平面に沿って,物体までの距離を連続的に得るベクトル値(一次元配列)、3つ目は視野全体に渡る,二次元配列の距離データです。
※このサンプルはサービスプロバイダ機能を使用するため、SSH接続の場合は追加でポートフォワーディングの設定が必要です。
distanceSensor()を使ってカメラの視線方向にあるオブジェクトまでの距離を取得するサンプルを紹介します。
まずはコントローラを作成します。
$ cd sigverse-<version>/bin/NewWorld $ emacs distanceSensor.cpp
distanceSensor.cpp
このコントローラは61行目のdistanceSensor()で距離データを取得しています。
戻り値はunsigned char型です。つまり取得できる距離データは0~255までの整数です。デフォルトでは255cmまでの距離を取得することができ、255よりも遠くにオブジェクトがある場合はすべて255が返ってきます。 引数を変えることによってこれらの距離を変更することができます。
さらに遠くの距離を取得したい場合などはdistanceSensor()の引数に取得したい距離データの範囲を指定することができます。
distanceSensor()を例えば以下のように修正します。
↓
最初2つの引数で距離センサが取得できる距離の範囲を指定します。この例ではカメラから距離が50.0~500.0(cm)までの距離データを取得できることになります。このとき戻り値は先ほどと同様0~255です。つまりカメラからの距離が50.0cm以下の場合は戻り値が0になり、500.0cm以上の場合は255となります。取得できる距離データの値と実際の距離は常に比例関係にあります。範囲を大きくすると広範囲の距離データを取得することができますが分解能が悪くなります。
最後の引数はカメラID番号です。 何も指定しない場合はカメラのID番号1から距離データを取得します。
このコントローラではロボットは向いている方向に進み、視線方向のオブジェクトまでの距離が120よりも近くなるとロボットの体全体の向きをランダムに変えます。
Makefileに作成したファイルを追加してコンパイルします。(手順省略)
次に世界ファイルを作成します。
$ cd .. $ emacs xml/distanceSensor.xml
distanceSensor.xml
それでは実行してみましょう。
$ ./sigserver.sh -p 9001 -w xml/distanceSensor.xml
#ref(): File not found: "distance_1.jpg" at page "距離センサ(v2.0系)"
シミュレーションを実行してみるとロボットが進んで、オブジェクトに近づくとロボットが方向転換しているのがわかると思います。
デフォルトでは0~255(SIGVerseの距離)までの距離データしか取得することができません。
さらにカメラが複数ある場合などは3番目の引数でカメラIDを指定します。
この後で出てくるdistanceSensor1D, distanceSensor2Dも同様の設定が可能です。
エージェントの視線の水平面に沿って距離を取得するサンプルです。水平面の距離データが配列データで一度に取得することができます。
コントローラを修正します。
$ cd NewWorld $ emacs -nw distanceSensor.cpp
distanceSensor.cpp
↓
distanceSensor1D()で視線方向の水平面に沿った1次元の深度マップが得られます。戻り値はクラスDepthImageです。 デフォルトではカメラの視野角内の幅320ピクセル(高さ1ピクセル)のデータが取得できます。(2011年9月の時点では320のみ対応)。距離データを取得するにはgetDistanceFromPixel()を使います。引数はピクセル位置を指定します。0が横方向の視野角内のいちばん左、320がいちばん右のピクセルになります。
このサンプルは水平面の距離データの最小値(いちばん近い距離)が120以下の場合に方向を変えるサンプルです。
コンパイルします。
$ make
実行してみましょう。
$ cd ../ $ ./sigserver.sh -p 9001 -w xml/distanceSensor.xml
先ほどのサンプルでは近くにオブジェクトがあっても視線方向と外れていたら向きを変えませんでしたが、 こちらのサンプルではロボットはより衝突を回避できているのがわかります。
視野全体の距離データを取得するサンプルを紹介します。
新しくコントローラを作成します。
$ cd NewWorld $ emacs distanceSensor2D.cpp
distanceSensor2D.cpp
このサンプルはcaptureViewのときと同様にエージェントに"move","rotation"等のメッセージを送信してロボットを操作します。また、"capture"を送信した場合はdistanceSensor2D()を使って視野全体の距離データ(深度画像)を取得し、その中で最も近いオブジェクトがある方向を計算し、その方向をロボットが指さします。画像中に同じ距離が複数ある場合は左上を優先して指さします。デフォルトで取得できる距離データのサイズは320×240(2011年9月の時点では320×240のみ対応)です。
また、captureViewで取得した画像と同様に
で距離データを保存し、可視化することができます。
それではMakefileを修正してコンパイルします。
$ make
次に世界ファイルを修正します。
$ cd .. $ emacs xml/distanceSensor.xml
コントローラ指定箇所を修正します。
distanceSensor.xml
↓
視線ベクトルを修正します。(※下を向いていると地面を検出してしまうので。。)
↓
それでは実行してみましょう。
$ cd ~/sigverse/bin $ ./sigserver.sh -p 9001 -w xml/distanceSensor.xml
ロボットがリビングに立っているので好きなところでメッセージ"capture"を送信して見てください。ロボットが最も近いオブジェクトの方向を指します。
#ref(): File not found: "distance_2.jpg" at page "距離センサ(v2.0系)"
次に保存した深度画像を見てみましょう。 以下のような濃淡画像が見えると思います。
#ref(): File not found: "view001.jpg" at page "距離センサ(v2.0系)"
深度画像の例
遠いオブジェクトほど色が薄くなり、近いオブジェクトほど色が濃くなっています。