2010年11月10日水曜日

ROSのwikiにページできてた

今日気づいたのですが、いつのまにかROSのwikiにotl-ros-pkgのページが自動で生成されていました。

http://www.ros.org/wiki/otl-ros-pkg


本名ダダ漏れになっていますが、どうしよう。。。。

とりあえず、せっかくなのでこの前@nao_sodyさんに作ってもらったロゴを付けておきました。



2010年11月7日日曜日

OTLマーカー

こんにちは。

OTLのARマーカーが出来ました。
デザインは某デザイン工房にてお願いしました。
うーん、これはいいな。
ちゃんと認識もできました。


mk_pattというコマンドでパターンファイル(ARToolKitが認識するために必要なデータファイル)を作るのですが、これがROSのものだと動きません。(ARToolKitがVideo4Linux2未対応なため)
そこで結局以前いれたVideo4Linux2対応版(aistのパッチを当てたもの)を利用してパターンファイルを作りました。

2010年11月6日土曜日

camera_calibration(USBカメラのキャリブレーション)

今日はカメラのキャリブレーションをやります。

http://www.ros.org/wiki/camera_calibration/Tutorials/MonocularCalibration


1.チェックボードの印刷
研究等でカメラをやる人にはおなじみなのですが、F1のチェッカーフラッグのような
画像を見せてカメラのキャリブレーションをします。

このチュートリアルにある↓のファイルを印刷してもいいですし、
他のチェッカーでもサイズが分かっていればいいと思います。
そしてこれはそのままだと大きすぎて印刷大変でしょうから、僕はA4サイズでやりました。

チェックボードもPTAMで印刷したものがあったので、それでやっちゃいました。



2.キャリブレーションの実行

まず以下のようにして、camera_calibrationが使えるようにしましょう。
$ rosmake camera_calibration --rosdep-install

そしたら、チェッカーボードのサイズにあわせて以下のようにしてキャリブレーションプログラムを走らせます。
$ rosrun camera_calibration cameracalibrator.py --size 8x6 --square 0.108 image:=/usb_cam/image_raw

私はPTAMのcalib_pattern.pdfを使ったので、
$ rosrun camera_calibration cameracalibrator.py --size 11x7 --square 0.02 image:=/usb_cam/image_raw
でやりました。

原文にあるように最後にcamera:=/usb_camなどを付けると/usb_cam/set_camera_infoサービスを呼ぼうとするので失敗するので付けないでください。


すると↑のような画面が表示されるので、
グリグリと、いろんな方向からこのチェッカーボードをカメラで見せてください。
しばらくやっているとCALIBRATEボタンが有効になるので、これをクリックー>SAVEボタンをクリックしてください。

3.データの確認
すると
/tmp/calibrationdata.tar.gz
にキャリブレーションに使った画像ファイルとデータが保存されます。

$ tar zxvf /tmp/calibrationdata.tar.gz
すると、
left-0000.png
left-0001.png
left-0002.png
left-0003.png
left-0004.png
left-0005.png
left-0006.png
left-0007.png
left-0008.png
left-0009.png
left-0010.png
left-0011.png
left-0012.png
left-0013.png
left-0014.png
left-0015.png
left-0016.png
left-0017.png
left-0018.png
left-0019.png
left-0020.png
left-0021.png
left-0022.png
left-0023.png
left-0024.png
left-0025.png
left-0026.png
left-0027.png
left-0028.png
ost.txt

と、いろいろ出てきます。
重要なのは最後のost.txtです。

このファイルの中身は以下のようになっています。

# oST version 5.0 parameters


[image]

width
640

height
480

[narrow_stereo/left]

camera matrix
849.555669 0.000000 310.565257
0.000000 850.171143 237.409081
0.000000 0.000000 1.000000

distortion
0.270500 -1.345412 -0.000040 -0.001902 0.0000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
849.555669 0.000000 310.565257 0.000000
0.000000 850.171143 237.409081 0.000000
0.000000 0.000000 1.000000 0.000000

これがカメラのパラメータになります。


以上でキャリブレーションは終わりです。
前回の続きで、ar_poseにこの結果を利用してみます。

ar_poseの実行

$ roscd ar_pose
$ cd launch
して、
以下をar_pose_single.launchのパラメータを書き換えます。

D: ost.txtのdistortion
K: ost.txtのcamera matrix
R: ost.txtのrectification
P: ost.txtのprojection

になるようにします。


<launch>
  <param name="use_sim_time" value="false"/>
  
  <node pkg="rviz" type="rviz" name="rviz" 
        args="-d $(find ar_pose)/demo/demo_single.vcg"/>
  
  <node pkg="tf" type="static_transform_publisher" name="world_to_cam" 
        args="1 1 0.3 0 0 0 world ar_marker 10" />
  
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" respawn="false" output="log">
    <param name="video_device" type="string" value="/dev/video0"/>
    <param name="camera_frame_id" type="string" value="usb_cam"/>
    <param name="io_method" type="string" value="mmap"/>
    <param name="image_width" type="int" value="640"/>
    <param name="image_height" type="int" value="480"/>
    <param name="pixel_format" type="string" value="yuyv"/>
    <rosparam param="D">[0.270500, -1.345412, -0.000040, -0.001902, 0.0000]</rosparam>
    <rosparam param="K">[849.555669, 0.000000, 310.565257, 0.000000, 850.171143, 237.409081, 0.000000, 0.000000, 1.000000]</rosparam>
    <rosparam param="R">[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]</rosparam>
    <rosparam param="P">[849.555669, 0.000000, 310.565257, 0.000000, 0.000000, 850.171143, 237.409081, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000]</rosparam>
  </node>
  
  <node name="ar_pose" pkg="ar_pose" type="ar_single" respawn="false" output="screen">
    <param name="marker_pattern" type="string" value="data/patt.hiro"/>
    <param name="marker_width" type="double" value="80.0"/>
    <param name="marker_center_x" type="double" value="0.0"/>
    <param name="marker_center_y" type="double" value="0.0"/>
    <param name="marker_frame" type="string" value="ar_marker"/>
    <param name="threshold" type="int" value="100"/>
    <param name="use_history" type="bool" value="true"/>
  </node>
</launch>


$ roslaunch ar_pose_single.launch
すると、USBカメラ位置がrviz上でマーカーからの相対で表示されます。
少しは精度よくなったのかな?


以上です。

ar_pose (ARToolKitのマーカー認識 in ROS)パッケージを使ってみる

ar_poseパッケージはARToolKitの機能のうち、マーカーの位置姿勢を認識する機能だけを取り出して、TFメッセージを書き出すようにしたCCNY(City University of New York)のパッケージです。

前回はインストールまでやりました。

前回の記事でusb_camパッケージはcamera_infoトピックを発行しないのでどうしよう?
ということを書きましたが、これは古いusb_camパッケージを使っていたからで、
最新のboschのusb_camパッケージではちゃんと対応していました。

http://www.ros.org/wiki/bosch-ros-pkg#bosch_drivers

$ svn export http://bosch-ros-pkg.svn.sourceforge.net/svnroot/bosch-ros-pkg/trunk/stacks/bosch_drivers

のようにしてソフトをダウンロードし、
$ rosmake usb_cam
とすればOKですね。

ar_pose/launch/ar_pose_single.launch
を覗いてみたら、ちゃんとこのusb_camパッケージを使っていましたので、
USBカメラで簡単に試せるようになっています。

1.USBカメラの動作確認

まずはカメラをPCに差してusb_camノードを立ち上げます。
以下のようなusb.launchを用意して、

<launch>
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="640" />
    <param name="image_height" value="480" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap" />
  </node>
</launch>


$ roslaunch usb.launch
するとキャプチャ開始されると思います。

$ rosrun image_view image_view image:=/usb_cam/image_raw
とすると表示されます。されなければ、上記usb.launchの各種設定を見直してください。
確認が終わったらimage_viewは落しちゃっていいです。

動作確認が終わったらusb.launchのほうも一旦落としてください。



2.パターンの印刷
ではまず、
$ roscd artoolkit
して、
build/artoolkit-svn/patterns/pattHiro.pdf
を印刷してください。
↓です。


3.ar_poseの実行

$ roscd ar_pose
launch/ar_pose_single.launch
のusb_camノードの必要なパラメータ(pixel_formatなど)だけ書き換えて、
$ roslaunch ar_pose ar_pose_single.launch
してみましょう。

ほら、簡単でしょう?



ちなみに私の環境ではar_pose_single.launchは以下のような感じです。



<launch>
  <param name="use_sim_time" value="false"/>

        <node pkg="rviz" type="rviz" name="rviz"
          args="-d $(find ar_pose)/launch/live_single.vcg"/>
                  
   <node pkg="tf" type="static_transform_publisher" name="world_to_cam"
     args="1 1 0.3 0 0 0 world ar_marker 10" />

        <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" respawn="false" output="log">
                <param name="video_device" type="string" value="/dev/video0"/>
                <param name="camera_frame_id" type="string" value="usb_cam"/>
                <param name="io_method" type="string" value="mmap"/>
                <param name="image_width" type="int" value="640"/>
                <param name="image_height" type="int" value="480"/>
                <param name="pixel_format" type="string" value="yuyv"/>
                <rosparam param="D">[0.025751483065329935, -0.10530741936574876,-0.0024821434601277623, -0.0031632353637182972, 0.0000]</rosparam>
                <rosparam param="K">[558.70655574536931, 0.0, 316.68428342491319, 0.0, 553.44501004322387, 238.23867473419315, 0.0, 0.0, 1.0]</rosparam>
                <rosparam param="R">[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]</rosparam>
                <rosparam param="P">[558.70655574536931, 0.0, 316.68428342491319, 0.0, 0.0, 553.44501004322387, 238.23867473419315, 0.0, 0.0, 0.0, 1.0, 0.0]</rosparam>
   </node>
      
        <node name="ar_pose" pkg="ar_pose" type="ar_single" respawn="false" output="screen">
                <param name="marker_pattern" type="string" value="data/patt.hiro"/>
                <param name="marker_width" type="double" value="80.0"/>
                <param name="marker_center_x" type="double" value="0.0"/>
                <param name="marker_center_y" type="double" value="0.0"/>
                <param name="threshold" type="int" value="100"/>
                <param name="use_history" type="bool" value="true"/>
        </node>
</launch>


以上です。あとはTFになっているんで、焼くなり煮るなりなんとでも。。。
カメラパラメータが適当なので、それなりに表示はされていますが、位置はずれていると思います。

次回はキャリブレーションをやってみます。

2010年11月4日木曜日

ARToolKitをccny_visionを使ってインストール

以前ARToolKitをインストールして、試すところまではやりましたが
ROSとつなげる前に挫折しました。

そしたらすでにやってくれている人がいましたので、こちらを利用してみます。

http://www.ros.org/wiki/ccny_vision

まず以下のようにしてコードをコピーします。


$ cd ~/ros/stacks
$ git clone http://robotics.ccny.cuny.edu/git/ccny-ros-pkg.git

で、次にccny_visionスタックをmakeします。

$ cd ~/ros/stacks/ccny-ros-pkg
$ rosmake ccny_vision --rosdep-install


rosmakeに--rosdep-installを付けると必要なソフトを自動でインストールまでやってくれます。

とりあえずこれでインストールは終了です。
すごく簡単ですね。

実際に使うにはカメラのキャリブレーションをしないといけないです。
ARToolKitのキャリブレーションではなくROSのカメラパラメータ(camera_infoトピック)が必要で、
usb_camノードはこのcamera_infoトピックがありません。
さあ、どうしましょう。

OpenCVのカメラキャリブレーションを使ってできそうな気がするので
また時間ができたらトライしてみたいと思います。

http://www.ros.org/wiki/camera_calibration

rosbuild Tipsその1(rosbuild_add_gtest)

ROSで単体テストをgtestで書いた場合、CMakeLists.txtに以下のように書くと

rosbuild_add_gtest(test/test_matrix test/test_matrix.cpp)

$ make test
としたときだけmakeされ、さらに実行、結果をxmlに保存、までやってくれます。

楽です。

2010年10月28日木曜日

rvizを使う

今回はrvizを使ってみます。
今までにも何度かrvizはでてきました。
主に自律移動の可視化(センサ情報、自己位置など)に利用してきました。

今回は自分のオリジナルデータを表示する方法をやります。

以下のチュートリアルをやります。
http://www.ros.org/wiki/rviz/Tutorials/Markers:%20Basic%20Shapes

visualization_msgs/Marker というメッセージを利用して表示する方法です。

規定のshapeから選択して表示する方法になります。
以下のような矢印、キューブ、線などから選択することになります。




以下では1つのオブジェクトを表示して、それが1秒毎に形状の種類を変化させるサンプルをつくります。

それではいつも通りパッケージを作りましょう。


$ roscreate-pkg using_markers roscpp visualization_msgs

で、いつものように以下のコードをsrc/basic_shapes.cppとして保存してください。

#include <ros/ros.h>
#include <visualization_msgs/Marker.h>

int main( int argc, char** argv )
{
  ros::init(argc, argv, "basic_shapes");
  ros::NodeHandle n;
  ros::Rate r(1);
  ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 1);

  // Set our initial shape type to be a cube
  uint32_t shape = visualization_msgs::Marker::CUBE;

  while (ros::ok())
  {
    visualization_msgs::Marker marker;
    // Set the frame ID and timestamp.  See the TF tutorials for information on these.
    marker.header.frame_id = "/my_frame";
    marker.header.stamp = ros::Time::now();

    // Set the namespace and id for this marker.  This serves to create a unique ID
    // Any marker sent with the same namespace and id will overwrite the old one
    marker.ns = "basic_shapes";
    marker.id = 0;

    // Set the marker type.  Initially this is CUBE, and cycles between that and SPHERE, ARROW, and CYLINDER
    marker.type = shape;

    // Set the marker action.  Options are ADD and DELETE
    marker.action = visualization_msgs::Marker::ADD;

    // Set the pose of the marker.  This is a full 6DOF pose relative to the frame/time specified in the header
    marker.pose.position.x = 0;
    marker.pose.position.y = 0;
    marker.pose.position.z = 0;
    marker.pose.orientation.x = 0.0;
    marker.pose.orientation.y = 0.0;
    marker.pose.orientation.z = 0.0;
    marker.pose.orientation.w = 1.0;

    // Set the scale of the marker -- 1x1x1 here means 1m on a side
    marker.scale.x = 1.0;
    marker.scale.y = 1.0;
    marker.scale.z = 1.0;

    // Set the color -- be sure to set alpha to something non-zero!
    marker.color.r = 0.0f;
    marker.color.g = 1.0f;
    marker.color.b = 0.0f;
    marker.color.a = 1.0;

    marker.lifetime = ros::Duration();

    // Publish the marker
    marker_pub.publish(marker);

    // Cycle between different shapes
    switch (shape)
    {
    case visualization_msgs::Marker::CUBE:
      shape = visualization_msgs::Marker::SPHERE;
      break;
    case visualization_msgs::Marker::SPHERE:
      shape = visualization_msgs::Marker::ARROW;
      break;
    case visualization_msgs::Marker::ARROW:
      shape = visualization_msgs::Marker::CYLINDER;
      break;
    case visualization_msgs::Marker::CYLINDER:
      shape = visualization_msgs::Marker::CUBE;
      break;
    }

    r.sleep();
  }
}


ざっと、上から眺めていくと大体わかると思いますが、

  uint32_t shape = visualization_msgs::Marker::CUBE;
や
marker.action = visualization_msgs::Marker::ADD;

のところでメッセージの定数が利用されていますね。
これまであまり使ってきませんでした。

http://www.ros.org/wiki/msg
の2.2にあるように.msgファイルで

constanttype1 CONSTANTNAME1=constantvalue1
constanttype2 CONSTANTNAME2=constantvalue2

のようにすると定数が使えます。

あとは気になったのは↓でした。

    marker.lifetime = ros::Duration();

lifetimeを設定すると自動でその時間経過すると削除されるようです。
ros::Duration() (つまり0秒)にすると自動で削除されません。

あとはここまで勉強してきた人ならさらっと理解できると思います。

そしたらCMakeList.txtに以下を追記して、


rosbuild_add_executable(basic_shapes src/basic_shapes.cpp)


$ rosmake
で依存関係を考慮してmakeしましょう。

そうしたら
$ roscore
$ rosrun rviz rviz
でrvizを立ち上げます。

.Global Optionsの
Fixed FrameとTarget Frameを/my_frameにして、
Addボタンを押してMarkerを追加します。

すると、Marker Topic はvisualization_marker
になっているので、このサンプルと同じです。

なのでこれだけで表示されます。

という感じで次々変わっていきます。

点群や、線などもpointsを使えば書けそうです。