Dockerコンテナ内の ROS 2 環境でRealSense D435を使用する

# はじめに

Docker 環境にubuntu22.04とROS2環境を構築し、Docker コンテナ内でRealSenseを使用する手順について解説する。
またRealSenseはロボットに搭載して使用することを考慮し以下の条件でも動くように設定する。
- RealSenseが接続された状態でPCが起動する。
- 途中でUSB接続が切れて再接続されても動作する。


Docker のROS2環境でRealSenseを使用するリポジトリとして既に以下のものが公開されており、
何も考えずに動かしたい方は以下リポジトリのDockerfileを使用してください。

https://github.com/2b-t/realsense-ros2-docker

# 動作確認環境

ホストPC

| 項目 |	値 |
|:--|:--|
| CPU | Intel® Core™ i7-12700H |
| GPU | GeForce RTX 3050 Ti Mobile |
| Ubuntu | 22.04 |
| Kernel | 6.2.0-36-generic |
| docker |  24.0.6 |
| docker compose | v2.21.0 |

Dockerコンテナ

| 項目 |	値 |
|:--|:--|
| Ubuntu | 22.04 |
| ROS2 | Humble or Iron|

使用したRealSense : 
RealSense D435 

https://www.switch-science.com/products/3633


# udev ルールの設定

docker コンテナ実行中にRealSenseが再接続されると/dev/以下の接続先が変わって動かなくなってしまうため、事前にホストPC側でudev rulesを設定する。

librealsenseのソースコードをクローンして、udev rules を適用する。
実行する際にPCからRealSenseは外しておく。


```bash
git clone https://github.com/IntelRealSense/librealsense && cd librealsense
sudo ./scripts/setup_udev_rules.sh
```

成功するとこのようなメッセージが出る。

```bash
Setting-up permissions for RealSense devices

Remove all RealSense cameras attached. Hit any key when ready

udev-rules successfully installed
```

udev rulesを削除する場合

```bash
sudo ./scripts/setup_udev_rules.sh --uninstall
```

### 接続先の確認

udev 設定後 PCを再起動し、何度かUSBを抜き差しして/dev/ 以下の接続先が変わらないことを確認

```bash
~$ v4l2-ctl --list-devices
Intel(R) RealSense(TM) Depth Ca (usb-0000:00:14.0-2):
	/dev/video4
	/dev/video5
	/dev/video6
	/dev/video7
	/dev/video8
	/dev/video9
	/dev/media2
	/dev/media3

 HD Webcam: HD Webcam (usb-0000:00:14.0-6):
	/dev/video0
	/dev/video1
	/dev/video2
	/dev/video3
	/dev/media0
	/dev/media1
```

筆者の環境の場合すでにノートPC内蔵Webカメラが/dev/video0 ~ 3, /dev/media0,1
にマウントされている。
RealSenseをつなぐと　/videoが次の番号から6つ、/mediaが次の番号から2つ追加されていた。


 


# Dockerfileとdocker-compose.ymlの作成

### Dockerfileの作成とイメージの作成

ベースとなるDocker Imageは以下リンクのDocker Hubに公開されているイメージの内、最小のROSインストールであるbaseを使用

https://hub.docker.com/r/althack/ros2

作成したDockerfile
引数でROS 2　HumbleとIronを選択できるようにした。

```Dockerfile:Dockerfile
# 引数でHumble とIronを選べるようにする
ARG ROS_DISTRO=humble
FROM althack/ros2:${ROS_DISTRO}-base

# 言語設定を聞かれないようにする
ARG DEBIAN_FRONTEND=noninteractive

# 必要なパッケージをインストール
RUN apt-get update \
 && apt-get install -y \
    build-essential \
    cmake \
    git-all \
 && rm -rf /var/lib/apt/lists/*

# librealsenseとrealsense-rosをインストール
RUN apt-get update \
 && apt-get install -y \
    ros-${ROS_DISTRO}-librealsense2* \
    ros-${ROS_DISTRO}-realsense2-camera \
 && rm -rf /var/lib/apt/lists/*

# デバッグ用のツールをインストール
RUN apt-get update \
 && apt-get install -y \
    ros-${ROS_DISTRO}-rviz2 \
    ros-${ROS_DISTRO}-rqt-image-view \
 && rm -rf /var/lib/apt/lists/*

RUN echo 'source /opt/ros/${ROS_DISTRO}/setup.bash' >> ~/.bashrc

CMD ["bash"]
```


Docker イメージのビルド

Humbleの場合

```bash
docker build --build-arg ROS_DISTRO=humble -t realsense-ros2-humble .
```

Ironの場合

```bash
docker build --build-arg ROS_DISTRO=iron -t realsense-ros2-iron .
```

イメージができているか確認

```bash
$ docker images
REPOSITORY                          TAG                IMAGE ID       CREATED          SIZE
realsense-ros2-iron                 latest             3beb6f942fee   27 seconds ago   2.26GB
realsense-ros2-humble               latest             eea22a6ed96f   4 minutes ago    2.23GB
```






### docker-compose.ymlの作成

作成したDockerイメージからコンテナを起動するためのdocker compose ymlファイル。
起動するとrealsense2_cameraのlaunchファイルが実行される。
Ironの場合humbleの箇所をironにしてください。

```yml:docker-compose.yml
version: '3.8'

services:
  realsense_ros_docker:
    image: realsense-ros2-humble:latest
    environment:
      - DISPLAY=${DISPLAY}
      - QT_X11_NO_MITSHM=1
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
    command: /bin/bash -c "source /opt/ros/humble/setup.bash && ros2 launch realsense2_camera rs_launch.py"
    #privileged: true
    devices:
      - /dev/video0:/dev/video0
      - /dev/video1:/dev/video1
      - /dev/video2:/dev/video2
      - /dev/video3:/dev/video3
      - /dev/video4:/dev/video4
      - /dev/video5:/dev/video5
      - /dev/video6:/dev/video6
      - /dev/video7:/dev/video7
      - /dev/video8:/dev/video8
      - /dev/video9:/dev/video9
      - /dev/media2:/dev/media0
      - /dev/media3:/dev/media1
      - /dev/media2:/dev/media2
      - /dev/media3:/dev/media3
    device_cgroup_rules:
      - 'c 81:* rmw'
      - 'c 189:* rmw'
```

RealSenseを接続した状態で実行　

```bash
docker compose up
```

```bash
[+] Running 2/2
 ✔ Network realsense_docker_test_default                   Created                                                                                                                                     0.1s 
 ✔ Container realsense_docker_test-realsense_ros_docker-1  Created                                                                                                                                     0.0s 
Attaching to realsense_docker_test-realsense_ros_docker-1
realsense_docker_test-realsense_ros_docker-1  | [INFO] [launch]: All log files can be found below /root/.ros/log/2023-11-01-10-16-30-585387-115173531dc5-1
realsense_docker_test-realsense_ros_docker-1  | [INFO] [launch]: Default logging verbosity is set to INFO
realsense_docker_test-realsense_ros_docker-1  | [INFO] [realsense2_camera_node-1]: process started with pid [14]
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.873154053] [camera.camera]: RealSense ROS v4.54.1
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.873229609] [camera.camera]: Built with LibRealSense v2.54.1
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.873235242] [camera.camera]: Running with LibRealSense v2.54.1
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.882924014] [camera.camera]: Device with serial number 241222074061 was found.
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] 
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.882945705] [camera.camera]: Device with physical ID /sys/devices/pci0000:00/0000:00:14.0/usb4/4-2/4-2:1.0/video4linux/video0 was found.
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.882950586] [camera.camera]: Device with name Intel RealSense D435 was found.
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883079531] [camera.camera]: Device with port number 4-2 was found.
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883084556] [camera.camera]: Device USB type: 3.2
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883477568] [camera.camera]: getParameters...
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883575261] [camera.camera]: JSON file is not provided
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883580332] [camera.camera]: Device Name: Intel RealSense D435
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883584101] [camera.camera]: Device Serial No: 241222074061
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883587438] [camera.camera]: Device physical port: /sys/devices/pci0000:00/0000:00:14.0/usb4/4-2/4-2:1.0/video4linux/video0
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883591278] [camera.camera]: Device FW version: 5.15.1
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883594850] [camera.camera]: Device Product ID: 0x0B07
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.883598217] [camera.camera]: Sync Mode: Off
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.893652603] [camera.camera]: Set ROS param depth_module.profile to default: 848x480x30
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.899207398] [camera.camera]: Set ROS param rgb_camera.profile to default: 640x480x30
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.903732976] [camera.camera]: Stopping Sensor: Depth Module
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.905105019] [camera.camera]: Starting Sensor: Depth Module
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.913908076] [camera.camera]: Open profile: stream_type: Depth(0), Format: Z16, Width: 848, Height: 480, FPS: 30
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.914036523] [camera.camera]: Stopping Sensor: RGB Camera
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.924960705] [camera.camera]: Starting Sensor: RGB Camera
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.927715218] [camera.camera]: Open profile: stream_type: Color(0), Format: RGB8, Width: 640, Height: 480, FPS: 30
realsense_docker_test-realsense_ros_docker-1  | [realsense2_camera_node-1] [INFO] [1698833790.928721350] [camera.camera]: RealSense Node Is Up!
```



# 参考

https://qiita.com/srs/items/9677f4128215c9021571


https://qiita.com/t_kumazawa/items/eb3a60f0ca1fbca70bee

https://github.com/2b-t/realsense-ros2-docker

https://developer.nvidia.com/ja-jp/blog/create-cost-maps-with-isaac-ros-nvblox-realsense/


https://github.com/IntelRealSense/librealsense/blob/master/scripts/Docker/readme.md