通过ROS2获取相机传感器数据,并使用ros_bridge发布到ROS1_ros2接收相机数据
通过ROS2获取相机传感器数据,并使用ros_bridge发布到ROS1
1 ROS2下获取相机数据并查看
1.1 准备工作
安装必要软件包:
- 安装
image_tools
(自带示例摄像头发布节点)
sudo apt updatesudo apt install ros-foxy-image-tools
- 安装
v4l-utils
(用于检查摄像头设备)
sudo apt install v4l-utils
- 确认摄像头设备
运行以下命令,确认你的摄像头设备路径:
v4l2-ctl --list-devices
通常是 /dev/video0
,可以用以下命令测试是否工作:
v4l2-ctl --device=/dev/video0 --all
1.2 使用 image_tools
发布图像数据
启动摄像头发布节点
source /opt/ros/foxy/setup.bashros2 run image_tools cam2image --ros-args -r image:=/my_camera/image_raw
说明:
cam2image
是官方提供的摄像头发布示例节点;--ros-args -r image:=/my_camera/image_raw
表示将默认话题重映射到/my_camera/image_raw
。
1.3 验证图像是否发布成功
1.3.1 用 ros2 topic list
查看是否有该话题:
ros2 topic list
应看到:
/my_camera/image_raw
1.3.2 查看图像消息结构:
ros2 topic info /my_camera/image_raw
1.3.3 查看图像数据内容(压缩)
ros2 topic echo /my_camera/image_raw
1.4 用 RViz2 查看图像
1.4.1 安装 RViz 图像插件
sudo apt install ros-foxy-rviz2 ros-foxy-image-transport
1.4.2 启动 RViz2
rviz2
在 RViz2 中:
- 添加一个
Image
显示器 - 选择话题为
/my_camera/image_raw
2. 编写自定义Python图像发布节点
使用 OpenCV (cv2
) 从 /dev/video0
读取图像,并发布到 ROS 2 话题 /camera/image_raw
。
2.1 环境准备
安装依赖:
sudo apt install python3-opencv
确保你的工作区结构如下:
~/ros2_ws/ └── src/ └── camera_publisher/ ├── package.xml ├── setup.py ├── setup.cfg ├── resource/ │ └── camera_publisher └── camera_publisher/ └── cam_pub.py
其中:
resource/camera_publisher
是个空文件,其文件名必须和包名完全一致(无后缀)。- 它的作用是:在安装过程中,帮助 ROS 识别这个包是个 ROS 2 Python 包。
setup.cfg
内容如下:
[develop]script_dir=$base/lib/camera_publisher[install]install_scripts=$base/lib/camera_publisher
在 ROS 2 的 Python 包中,setup.cfg
的作用主要包括:
- 声明包的基本信息:如包名、版本、作者等。
- 指明构建系统类型:在 ROS 2 中,一般用
ament_cmake
(C++)或ament_python
(Python)。 - 配置安装行为:比如哪些模块、脚本、资源文件会被安装。
- 定义入口点(可执行脚本的别名)。
2.2 cam_pub.py
# ~/ros2_ws/src/camera_publisher/camera_publisher/cam_pub.pyimport rclpyfrom rclpy.node import Nodefrom sensor_msgs.msg import Imagefrom cv_bridge import CvBridgeimport cv2class CameraPublisher(Node): def __init__(self): super().__init__(\'camera_publisher\') self.publisher_ = self.create_publisher(Image, \'/camera/image_raw\', 10) self.timer = self.create_timer(0.1, self.timer_callback) self.cap = cv2.VideoCapture(0) # /dev/video0 self.bridge = CvBridge() self.get_logger().info(\'📷 摄像头图像发布器已启动\') def timer_callback(self): ret, frame = self.cap.read() if ret: msg = self.bridge.cv2_to_imgmsg(frame, encoding=\'bgr8\') self.publisher_.publish(msg) else: self.get_logger().warn(\'无法读取摄像头帧\')def main(args=None): rclpy.init(args=args) node = CameraPublisher() try: rclpy.spin(node) except KeyboardInterrupt: pass finally: node.cap.release() node.destroy_node() rclpy.shutdown()if __name__ == \'__main__\': main()
2.3 package.xml
<!-- ~/ros2_ws/src/camera_publisher/package.xml --><?xml version=\"1.0\"?><package format=\"2\"> <name>camera_publisher</name> <version>0.0.1</version> <description>Simple camera image publisher</description> <maintainer email=\"you@example.com\">Your Name</maintainer> <license>MIT</license> <buildtool_depend>ament_python</buildtool_depend> <exec_depend>rclpy</exec_depend> <exec_depend>sensor_msgs</exec_depend> <exec_depend>cv_bridge</exec_depend> <exec_depend>opencv-python</exec_depend> <export> <build_type>ament_python</build_type> </export></package>
2.4 setup.py
# ~/ros2_ws/src/camera_publisher/setup.pyfrom setuptools import setuppackage_name = \'camera_publisher\'setup( name=package_name, version=\'0.0.1\', packages=[package_name], install_requires=[\'setuptools\'], zip_safe=True, maintainer=\'Your Name\', maintainer_email=\'you@example.com\', description=\'Camera image publisher using OpenCV and cv_bridge\', license=\'MIT\', entry_points={ \'console_scripts\': [ \'cam_pub = camera_publisher.cam_pub:main\', ], },)
2.5 编译并运行
构建:
cd ~/ros2_wssource /opt/ros/foxy/setup.bashcolcon build
运行:
source install/setup.bashros2 run camera_publisher cam_pub
2.6 查看发布图像
你可以用以下命令查看是否有数据:
ros2 topic listros2 topic echo /camera/image_raw
或者在 RViz2 中添加 Image
类型显示器,选中 /camera/image_raw
话题。
3. 将 ROS 2 图像消息桥接到 ROS 1 并显示在 RViz 中
Step1:启动 ROS1 的 roscore
打开终端 1:
source /opt/ros/noetic/setup.bashroscore
Step2:启动 ROS2 摄像头图像发布节点
打开终端 2:
source /opt/ros/foxy/setup.bashsource ~/ros2_ws/install/setup.bash # 如果你自己写了 camera_publisher 包ros2 run camera_publisher cam_pub
确保发布到了话题 /camera/image_raw
。
Step3:启动 ros1_bridge
打开终端 3:
source /opt/ros/noetic/setup.bashsource /opt/ros/foxy/setup.bashsource ~/ros2_ws/install/setup.bashros2 run ros1_bridge dynamic_bridge --bridge-all-topics
这会自动桥接兼容话题,包括 /camera/image_raw
。
Step4:在 ROS1 中查看图像话题
打开终端 4:
source /opt/ros/noetic/setup.bashrostopic list
你应该能看到 /camera/image_raw
。
可测试订阅:
rosrun image_view image_view image:=/camera/image_raw
Step5:在 RViz 中显示图像
同样在 ROS1 终端中运行:
rviz
- 添加
Image
类型的显示插件 - 设置 topic 为
/camera/image_raw
- Transport 类型选择
raw
4. 打包成sh脚本
- 启动
roscore
(ROS1) - 启动 ROS2 摄像头图像发布节点(
camera_publisher
) - 启动
ros1_bridge
动态桥接器 - 启动 ROS1 图像查看工具
image_view
- 启动 ROS1 RViz 并设置好话题
/camera/image_raw
#!/bin/bash# =================== 配置 ====================ROS1_SETUP=\"/opt/ros/noetic/setup.bash\"ROS2_SETUP=\"/opt/ros/foxy/setup.bash\"BRIDGE_SETUP=\"$HOME/ros2_ws/install/setup.bash\"PKG_NAME=\"camera_publisher\"NODE_NAME=\"cam_pub\"TOPIC=\"/camera/image_raw\"# ============================================# 启动 roscoregnome-terminal -- bash -c \"source $ROS1_SETUP && roscore\"sleep 3 # 等 roscore 启动# 启动 ROS2 摄像头图像发布节点gnome-terminal -- bash -c \"source $ROS2_SETUP && source $BRIDGE_SETUP && ros2 run $PKG_NAME $NODE_NAME\"sleep 2# 启动 ros1_bridgegnome-terminal -- bash -c \"source $ROS1_SETUP && source $ROS2_SETUP && source $BRIDGE_SETUP && ros2 run ros1_bridge dynamic_bridge --bridge-all-topics\"sleep 2# 启动 ROS1 image_view 查看图像gnome-terminal -- bash -c \"source $ROS1_SETUP && rosrun image_view image_view image:=$TOPIC\"sleep 2# 启动 RViz(手动配置 /camera/image_raw)gnome-terminal -- bash -c \"source $ROS1_SETUP && rviz\"
使用方式:
- 将上述脚本保存为
run_image_bridge.sh
- 给它执行权限:
chmod +x run_image_bridge.sh
- 执行脚本:
./run_image_bridge.sh