🐷

ROS2 galacticでMIPIカメラから画像を取る

2022/02/11に公開

まえがき

ROS2 galacticで独立差動二輪ロボットを自作しています。今回は自作ロボットに搭載しているラズパイ4にMIPIカメラを取り付け、ROS2のノードで画像を取ってみました。

環境

  • ラズパイ4(Ubuntu 20.04LTS) & ROS2 galactic(インストール済みの前提です)
  • MIPIカメラ(ArduCamのOV5647を使ったものを使いましたがラズパイ4でサポートしていれば何でもいいんじゃないでしょうか)

手順

MIPIカメラの取り付け

FFCケーブルの表裏を注意して取り付けます。

Ubuntu20.04にMIPIカメラを有効にする設定を追加

kernelがカメラを認識しているかを確認する

v4l-ctlコマンドを使います。v4l-ctlはv4l-utilsパッケージに入っているようですのでインストールします。

$ sudo apt install v4l-utils

コマンドを実行します。

$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
	/dev/video10
	/dev/video11
	/dev/video12
	/dev/media1

bcm2835-isp (platform:bcm2835-isp):
	/dev/video13
	/dev/video14
	/dev/video15
	/dev/video16
	/dev/media0

Cannot open device /dev/video0, exiting.

/dev/video0が有効になっていれば認識されているらしいです。Cannot open ...となっており認識されていないようです。

/boot/firmware/config.txtに以下を追加します。

start_x=1
gpu_mem=128

以下の行より上に記載したほうが良いらしいです。

include syscfg.txt
include usercfg.txt

OSを再起動します。

もう一度v4l2-ctl --list-devicesで確認します。

$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
	/dev/video10
	/dev/video11
	/dev/video12
	/dev/media1

bcm2835-isp (platform:bcm2835-isp):
	/dev/video13
	/dev/video14
	/dev/video15
	/dev/video16
	/dev/media0

mmal service 16.1 (platform:bcm2835-v4l2):
	/dev/video0

今度はCannot open ...ではなくmmal service ...のようになっており、認識されていることがわかります。

v4l2-cameraパッケージの追加

以下を実行してv4l2-cameraパッケージをインストールします。

$ sudo apt install ros-galactic-v4l2-camera

v4l2-cameraノードの実行

以下を実行してv4l2-cameraノードを実行します。

$ ros2 run v4l2_camera v4l2_camera_node 

カメラのキャリブレーションファイルが無いのでワーニング・エラーがたくさん出ますが、とりあえず立ち上がります。

ノード名・トピック名の確認

どんなノード・トピックがあるか見てみます。

$ ros2 node list
/v4l2_camera
$ ros2 node info /v4l2_camera 
/v4l2_camera
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /camera_info: sensor_msgs/msg/CameraInfo
    /image_raw: sensor_msgs/msg/Image
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
  Service Servers:
    /set_camera_info: sensor_msgs/srv/SetCameraInfo
    /v4l2_camera/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /v4l2_camera/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /v4l2_camera/get_parameters: rcl_interfaces/srv/GetParameters
    /v4l2_camera/list_parameters: rcl_interfaces/srv/ListParameters
    /v4l2_camera/set_parameters: rcl_interfaces/srv/SetParameters
    /v4l2_camera/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:

  Action Clients:

$ ros2 topic list
/camera_info
/image_raw
/parameter_events
/rosout

ノード名はv4l2_camera、トピック名は/camera_infoと/image_rawがあるようです。

画像が送られていることを確認

$ ros2 run rqt_image_view rqt_image_view

圧縮した画像データをpublishできる?

生(raw)のデータはトピックとしてpublishしていますが、圧縮したデータはpublishできるのでしょうか?
ROSのドキュメントで確認したところ、image_transportという別のノードを使うようです。

https://index.ros.org/r/v4l2_camera/

image-transportパッケージの追加

以下を実行してimage-transportパッケージをインストールします。

$ sudo apt install ros-galactic-image-transport

image-transportノードの実行

以下を実行してimage-transportノードを実行します。

$ ros2 run image_transport republish raw

ノード名・トピック名の確認

どんなノード・トピックがあるか見てみます。

$ ros2 node list
/image_republisher
/v4l2_camera
$ ros2 node info /image_republisher 
/image_republisher
  Subscribers:
    /in: sensor_msgs/msg/Image
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /out: sensor_msgs/msg/Image
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
  Service Servers:
    /image_republisher/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /image_republisher/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /image_republisher/get_parameters: rcl_interfaces/srv/GetParameters
    /image_republisher/list_parameters: rcl_interfaces/srv/ListParameters
    /image_republisher/set_parameters: rcl_interfaces/srv/SetParameters
    /image_republisher/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:

  Action Clients:

/image_republisherノードは、/inをsubscribeして/outをpublishしているようです。
トピック/inをv4l2_cameraに合わせてremapします。ついでに/outもremapします。

$ ros2 run image_transport republish raw --ros-args --remap in:=/image_raw --remap out:=/image_raw/compressed

画像が送られていることを確認

$ ros2 run rqt_image_view rqt_image_view

ということで、image-transportを使うことで圧縮画像をpublishすることができました。

launchファイルにまとめる

今回やったことを一つのlaunchファイルにまとめました。

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    v4l2_node = Node(
        package='v4l2_camera',
        executable='v4l2_camera_node',
        output='screen'
    )

    image_transport = Node(
        package='image_transport',
        executable='republish',
        arguments=["raw"],
        remappings=[('in', '/image_raw'),
                    ('out', '/image_raw/compressed')
                   ]
    )

    return LaunchDescription([
        v4l2_node,
        image_transport
    ])

最後に

カメラのキャリブレーションをしたらv4l2のメッセージが消えるかは今後試してみます。

Discussion