二、ROS2完成Docker容器和宿主机通信,使用ros2 topic list看到,但是无法echo
文章目录
- 1. 问题描述
- 2. 问题分析:权限不一致
- 3. 解决方法
- 3.1 方法1:修改docker容器用户权限(推荐)
- 3.2 方法2:修改宿主机权限
- 4. 参考资料
1. 问题描述
我使用docker创建了一个容器,运行命令如下:
docker run -it --rm --net=host --ipc=host --pid=host -v /dev:/dev -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -v /etc/localtime:/etc/localtime:ro --name ros2_jazzy_dev srb:v1.1
在容器中运行:
ros2 run demo_nodes_cpp talker
在宿主机中运行:
ros2 run demo_nodes_cpp listener
运行之后,可以在宿主机使用ros2 topic list
命令查询到相关话题,但是使用ros2 topic echo /chatter
没有输出。
2. 问题分析:权限不一致
在运行的过程中,ROS2使用了共享内存机制,会共享内存 dev/shm(共享内存目录) ,如果容器和主机权限不一致,则会导致无法通信(我的代码中,docker容器是root,宿主机是普通用户),虽然可以查询到相关话题,但是订阅后没有消息输出。比如,docker容器创建了一个共享内存,其所有者为docker容器用户root,当宿主机去访问的时候,由于用户不同,没有权限访问,也就无法进行信息传递。所以,如果想要容器和宿主机正确通信,需要设置相同的权限。
- 判断ros2是否使用了共享内存
ls /dev/shm
lsof | grep /dev/shm
3. 解决方法
3.1 方法1:修改docker容器用户权限(推荐)
加入--user $(id -u):$(id -g)
命令,使容器和宿主机是同一个用户
docker run -it \--rm \--net=host \--ipc=host \--pid=host \--privileged \-v /dev:/dev \-v /tmp/.X11-unix:/tmp/.X11-unix \-e DISPLAY=$DISPLAY \-v /etc/localtime:/etc/localtime:ro \-v ~/your_ws:/home/ros2_ws \--user $(id -u):$(id -g) \--name ros2_jazzy_dev \your_ros2_jazzy_image:latest
注意:
运行之后,宿主机和容器可能用户名不同,这是因为--user $(id -u):$(id -g)
命令保证了容器中使用宿主机的UID和GID,但没有指定容器中使用哪个用户名,Docker默认不会自动创建和绑定用户名,只会绑定UID和GID,我们只要保证UID和GID一致即可,验证命令如下:
id -u
id -un
查询用户名命令:
whoami
3.2 方法2:修改宿主机权限
(1) 直接切换到root:
宿主机运行su root
,切换到root用户,然后运行:
ros2 run demo_nodes_cpp listener
容器运行:
ros2 run demo_nodes_cpp talker
即可完成通信
(2) 临时修改共享内存区域:
cd /dev/shm
sudo chmod 777 -R .
该方法只是临时修改共享内存的权限,每次运行完,需要重新运行上述命令,才可以进行通信
4. 参考资料
参考1