マーカー認識

ArUcoを用いてマーカーを認識します.

目的

ロボットが外界の環境を感知するためには,センシング技術が必要不可欠です. しかしながら,刻々と変化する環境を観測したセンサから得られる情報は膨大ですので, 意味のある情報を解析することは簡単ではありません. 今回はARマーカー(QRコードと似ている2次元バーコード)を認識するためのライブラリとしてArUcoを試します. このライブラリを利用することで,マーカーが付与された物体の位置・姿勢を簡単に推定することができるようになります.

インストール手順

幾つかのパッケージが必要となりますのでインストールしましょう. また,前回の講義にてUSBカメラ(ノートPCに搭載されたカメラを含む)を使用するためのパッケージをインストールしました. 今回も使用するので,インストールできてい人は忘れずに入れてください.

1
2
3
4
$ sudo apt install ros-humble-image-transport ros-humble-image-transport-plugins
$ sudo apt install ros-humble-camera-calibration
$ sudo apt install ros-humble-aruco
$ sudo apt install ros-humble-tf-transformations

前回の講義と同様に,ROS2でカメラから画像トピックを得るためにv4l2_cameraを使用します.

1
$ ros2 run v4l2_camera v4l2_camera_node

画像トピックが配信されているかを確認しましょう.

1
$ ros2 run rqt_image_view rqt_image_view

上記のコマンドを実行後,左上のトピック選択欄から画像トピックを選びます. 画像トピックとして選択可能な/image_rawは未圧縮画像, /image_raw/compressed/image_raw/theoraは圧縮された画像です. 圧縮された画像トピックが2つありますが,この2つは圧縮方式が異なります. 画像は多くのデータ量によって表現されるため,画像を通信しようとすると膨大なデータ通信量となります. ある環境下でtopic bwtopic hzコマンドを用いてデータ通信量とフレームレートを測定すると下記のような結果が得られました.

トピック名 通信量 [MB/s] フレームレート[fps]
/image_raw 19.7 21.2
/image_raw/compressed 1.92 23.1
/image_raw/theora 0.0108 23.2

圧縮したい画像トピックを通信しようとすると,1秒間で19.7[MB]ものデータ通信量が発生します. ネットワークによってはリアルタイムでの送受信が難しくなりますので, 環境によっては圧縮した画像トピックを使用することをお勧めします. (今回はローカルマシン内の処理に留まるため,圧縮していない画像トピックを使用します.)

カメラキャリブレーション

実世界とカメラモデルを対応づけるために,カメラのパラメータを求めるカメラキャリブレーション(カメラ校正)という作業が必要です. カメラキャリブレーションの詳しい説明や方法については省略します. ROS2では,カメラキャリブレーションを行うcamera_calibrationというパッケージが用意されています.こちらのパッケージを使用してカメラキャリブレーションを行いましょう.

キャリブレーションを行う前に,キャリブレーションシートを用意します. こちらのキャリブレーションシートをA4サイズで印刷し,剛体の板に貼ります. 本講義では高い精度を求めないので下敷き等でも構いませんが,精度が必要となる場合には力を加えると変形するような素材は避けた方が良いです.

カメラキャリブレーションを行うためのノードを立ち上げます.

1
$ ros2 run camera_calibration cameracalibrator --size 8x6 --square 0.0245 --ros-args --remap image:=/image_raw

引数の–-sizeは白黒のマス目が交わる点の数(横x縦),-–squareはマス目の長さ[m]です. こちらのノードは/imageというトピック名で画像を購読するため,v4l2_cameraが配信する画像データのトピック名を変更する必要があります.

正常に起動できた場合には,カメラから取得できた画像が表示されます. 用意したキャリブレーションシートを撮影しましょう. シート全体を撮影すると,白黒のマス目が交わる交点に色付きの円が表示されます. この状態の画像が保存され,実空間のシートの交点の位置と,その交点に対応する画像座標を用いてカメラキャリブレーションを行います. 精度の良いカメラキャリブレーションを行うためには,シートの位置や姿勢を変えた時の実空間と画像の対応点が多く必要です. シートを左右に動かすとXのバーが赤色から緑色になります. 同様に,シートを上下に動かすとYのバーが緑色に,シートを前後に動かすとSizeのバーが緑色に,シートを傾けるとSkewのバーが緑色になります. 下記の動画は,カメラキャリブレーションを行った例です.

全ての項目が緑色もしくは緑色になると、CALIBRATEというボタンが淡い緑色になりますのでクリックしてください. 暫くするとカメラキャリブレーションが完了します. SAVEボタンが緑色になりますのでクリックすると/tmp/calibrationdata.tar.gzに圧縮したファイルが保存されます. ホームディレクトリにcalibrationdataというディレクトリを作成し,そのディレクトリに展開します.

1
2
3
4
$ mkdir ~/calibrationdata
$ mv /tmp/calibrationdata.tar.gz ~/calibrationdata
$ cd calibrationdata
$ tar xzvf calibrationdata.tar.gz

カメラキャリブレーション時に使用した画像,及びカメラキャリブレーションによって作成したファイル(ost.txtost.yaml)が展開されます. カメラキャリブレーションによって作成したファイルをcatコマンドで中身を確認すると,幾つかのパラメータが記述されています. 詳しい説明は省略しますが,このパラメータを用いて画像の座標と実空間の3次元座標の対応を求めることができます.

起動中のv4l2_camera_nodeを終了し,改めて起動し直します. カメラキャリブレーションによって得られたパラメータを用いてカメラから画像トピックを得るためには下記のコマンドを実行します.

1
$ ros2 run v4l2_camera v4l2_camera_node --ros-args --param camera_info_url:=file:///home/yuu/calibrationdata/ost.yaml

camera_info_urlには,先ほど展開したost.yamlファイルの絶対パスを指定してください. (上記のコマンドをコピー&ペーストするだけでは正しく実行できないので注意してください.)

ArUcoを使用するための準備

ArUcoを使用するために下記をインストールしてください.

1
2
3
$ sudo apt install python3-pip
$ pip3 install opencv-contrib-python transforms3d
$ pip install opencv-contrib-python==4.5.5.64

次にArUcoパッケージをクローンしてビルドします.

1
2
3
4
5
$ mkdir -p colcon_ws/src
$ cd colcon_ws/src
$ git clone https://github.com/JMU-ROBOTICS-VIVA/ros2_aruco.git
$ cd ..
$ colcon build

マーカー生成

認識したいマーカーを生成します. ヘルプからどのようなマーカーを生成できるか確認しましょう.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ ros2 run ros2_aruco aruco_generate_marker -h
usage: aruco_generate_marker [-h] [--id ID] [--size SIZE] [--dictionary]

Generate a .png image of a specified maker.

options:
  -h, --help     show this help message and exit
  --id ID        Marker id to generate (default: 1)
  --size SIZE    Side length in pixels (default: 200)
  --dictionary   Dictionary to use. Valid options include: DICT_4X4_100,
                 DICT_4X4_1000, DICT_4X4_250, DICT_4X4_50, DICT_5X5_100,
                 DICT_5X5_1000, DICT_5X5_250, DICT_5X5_50, DICT_6X6_100,
                 DICT_6X6_1000, DICT_6X6_250, DICT_6X6_50, DICT_7X7_100,
                 DICT_7X7_1000, DICT_7X7_250, DICT_7X7_50, DICT_APRILTAG_16H5,
                 DICT_APRILTAG_16h5, DICT_APRILTAG_25H9, DICT_APRILTAG_25h9,
                 DICT_APRILTAG_36H10, DICT_APRILTAG_36H11,
                 DICT_APRILTAG_36h10, DICT_APRILTAG_36h11, DICT_ARUCO_ORIGINAL
                 (default: DICT_5X5_250)

--idはインデックス番号,--sizeは大きさ(画素),--dictionaryはマーカーの種類を表します. 下記はインデックス番号0,一辺が200画素,マーカーの種類としてDICT_4X4_100を指定してマーカーを生成するコマンドの実行例です.

1
$ ros2 run ros2_aruco aruco_generate_marker --id 0 --size 200 --dictionary DICT_4X4_100

実行するとpng形式で出力された画像ファイルが生成されます. 生成された画像ファイルをプリンタで印刷します. 講義ではこちらの9つのマーカーを並べた用紙を配布します.

マーカー認識

マーカー認識を行う前に,どのようなマーカーを認識するかの設定が必要です. 下記のファイルをエディタで開きましょう.

1
$ vim ~/colcon_ws/src/ros2_aruco/ros2_aruco/config/aruco_parameters.yaml

パラメータ等を編集します. marker_sizeは印刷したマーカーの一辺のサイズ(単位は[m]です), aruco_dictionary_idはマーカーの種類(マーカー生成時に指定したものと同じ物を使用), image_topicには画像トピックを指定します.

1
2
3
4
5
6
/aruco_node:
  ros__parameters:
    marker_size: 0.05
    aruco_dictionary_id: DICT_4X4_100
    image_topic: /image_raw
    camera_info_topic: /camera_info

これで準備が整いました. 先ほど起動したカメラから画像トピックを得るノードを終了してしまった場合には,下記のコマンドを改めて実行してください.

1
$ ros2 run v4l2_camera v4l2_camera_node --ros-args --param camera_info_url:=file:///home/yuu/calibrationdata/ost.yaml

camera_info_urlには,先ほど展開したost.yamlファイルの絶対パスを指定してください.

先ほどダウンロードしたパッケージに含まれているマーカーを認識するノードを起動します.

1
$ ros2 launch ros2_aruco aruco_recognition.launch.py

次に静的にフレームを配信するコマンドを実行します. カメラを原点としたフレームを作成し,ワールド座標系を表すmapと繋ぎます.

1
$ ros2 run tf2_ros static_transform_publisher --x 0 --y 0 --z 0 --roll 0 --pitch 0 --yaw 0 --frame-id map  --child-frame-id usb_cam

最後にデータ可視化ツールrviz2を実行します.

1
$ rviz2

rviz2を実行するとウィンドウが起動します. ウィンドウの左下にあるAddボタンを左クリックし,可視化したいデータを選択します. PoseArrayを選択してOKをクリックすると,DisplaysPoseArrayの項目が追加されます. PoseArrayをダブルクリックしてパラメータを設定します. 空欄になっているTopicをクリックしてaruco_posesを選びます. 印刷したARマーカをカメラで撮影するとマーカーの3次元位置・姿勢が描画されます.

マーカーを認識した例1 マーカーを認識した例2