ros2双目摄像头驱动

流程:

  • 从 USB 摄像头采集视频数据

  • 对采集到的合成图像进行拆分,提取左右视图

  • 将左右图像分别发布到 ROS2 话题

 设备:

  • 树莓派5(ubuntu24.04系统)

  • 支持usb的双目摄像头

节点代码 stereo_camera_node.py:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2

class StereoCameraPublisher(Node):
    def __init__(self):
        super().__init__('stereo_camera_publisher')
        self.get_logger().info("Initializing Stereo Camera Publisher Node")

        # 创建发布者:分别发布左图和右图
        self.left_pub = self.create_publisher(Image, 'left/image_raw', 10)
        self.right_pub = self.create_publisher(Image, 'right/image_raw', 10)
        self.bridge = CvBridge()

        # 仅打开 /dev/video0,因为该设备输出的是合成图像(左右并排)
        self.cap = cv2.VideoCapture(0, cv2.CAP_V4L2)

        if not self.cap.isOpened():
            self.get_logger().error("无法打开 /dev/video0")
        
        # 可选:设置摄像头分辨率(根据实际情况修改)
        # 例如:假设合成图像分辨率为 3840x1080,左右各 1920x1080
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

        # 设置定时器,每 0.1 秒读取一次图像(约 10Hz)
        self.timer = self.create_timer(0.1, self.timer_callback)

    def timer_callback(self):
        ret, frame = self.cap.read()
        if ret:
            height, width, _ = frame.shape
            # 假设左右图像水平并排,宽度各占总宽度的一半
            half_width = width // 2
            left_frame = frame[:, :half_width]
            right_frame = frame[:, half_width:]

            # 将 OpenCV 图像转换为 ROS2 Image 消息
            img_msg_left = self.bridge.cv2_to_imgmsg(left_frame, encoding="bgr8")
            img_msg_right = self.bridge.cv2_to_imgmsg(right_frame, encoding="bgr8")
            current_time = self.get_clock().now().to_msg()
            img_msg_left.header.stamp = current_time
            img_msg_right.header.stamp = current_time

            self.left_pub.publish(img_msg_left)
            self.right_pub.publish(img_msg_right)
        else:
            self.get_logger().warn("读取 /dev/video0 图像失败")

    def destroy_node(self):
        # 释放摄像头资源
        self.cap.release()
        super().destroy_node()

def main(args=None):
    rclpy.init(args=args)
    node = StereoCameraPublisher()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('Keyboard Interrupt (SIGINT)')
    finally:
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()

通过usb传输的图像走的是一个通道(在我的设备里是dev/video0),需要自行分割左右摄像头图像, 做这一步需要查询摄像头支持的分辨率和格式,使用以下命令:

v4l2-ctl --device=/dev/video0 --list-formats-ext

这个命令会列出该摄像头支持的所有像素格式、对应的分辨率以及每种分辨率下的帧率选项。

得到支持分辨率后在设置宽度高度的部分进行修改,宽度需要乘2,比如需要的是640*480的视频,就设置成1280*480,这样在左右分割后刚好是我们需要的分辨率。

最后编译运行节点后,就可以通过rqt_image_view包中的同名节点分别查看左右摄像头的画面了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值