ubuntu20使用ros2发布图像话题使用ros1接收图像话题实践

发布于:2025-06-25 ⋅ 阅读:(15) ⋅ 点赞:(0)

1.同时安装ros1和ros2并验证

(1)ubuntu20安装好后ros1版本为noetic,ros2版本为
通过环境命令来查看当前控制台使用的ros版本

printenv | grep ROS

默认.bashrc 中注释掉

#source /opt/ros/noetic/setup.bash
#source /opt/ros/foxy/setup.bash

(2)验证ros2方法

在控制台中启用ros2环境

打开第一个终端:

source /opt/ros/foxy/setup.bash
ros2 run turtlesim turtlesim_node

打开第二个终端:

source /opt/ros/foxy/setup.bash
ros2 run turtlesim turtle_teleop_key

能看到小海龟并能用键盘控制。

(3)验证ros1方法
ros1需要启动roscore,然后启动小乌龟,其他类似。

2.验证ros1和ros2桥接

下面是验证在ros1中控制ros2中的小乌龟,在ros1中启动小乌龟,在ros2中发布控制命令控制ros1中小乌龟。

(1)启动roscore

source /opt/ros/noetic/setup.bash
roscore

(2)启动ros1中的小乌龟并查看是否有小乌龟话题

source /opt/ros/noetic/setup.bash
rosrun turtlesim turtlesim_node
rostopic list

注意,控制小乌龟是通过/turtle1/cmd_vel来接收命令的。
(3)使用ros2打开桥接,使ros1能够得到ros2发布的话题

#注意,同时启用ros2环境和ros1环境后再运行bridge
source /opt/ros/foxy/setup.bash
source /opt/ros/noetic/setup.bash
ros2 run ros1_bridge dynamic_bridge --bridge-all-topics

运行结果如下

created 1to2 bridge for topic '/rosout_agg' with ROS 1 type 'rosgraph_msgs/Log' and ROS 2 type 'rcl_interfaces/msg/Log'
created 2to1 bridge for topic '/rosout' with ROS 2 type 'rcl_interfaces/msg/Log' and ROS 1 type 'rosgraph_msgs/Log'

发现没有启动控制命令只桥接了基础话题/rosout_agg和/rosout

注意:如果没有安装ros-foxy-ros1-bridge,使用下面命令安装

sudo apt install ros-foxy-ros1-bridge

(4)在ros2中启动乌龟控制器

source /opt/ros/foxy/setup.bash
ros2 run turtlesim turtle_teleop_key

发现ros1_bridge新增打印如下
[INFO] [1750386004.061122908] [ros_bridge]: Passing message from ROS 1 rosgraph_msgs/Log to ROS 2 rcl_interfaces/msg/Log (showing msg only once per type)

然后按箭头控制发现可以控制小乌龟了。

3.验证ros2发布图像,ros1工程接收图像

3.1 ros2工程发布图像

image_publisher.cpp

#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>

using namespace std::chrono_literals;

class ImagePublisher : public rclcpp::Node {
public:
    ImagePublisher() : Node("image_publisher") {
        publisher_ = this->create_publisher<sensor_msgs::msg::Image>("image_raw", 10);
        timer_ = this->create_wall_timer(
            100ms, std::bind(&ImagePublisher::timer_callback, this));
        
        cap_.open(0); // 使用摄像头
        if (!cap_.isOpened()) {
            RCLCPP_ERROR(this->get_logger(), "无法打开摄像头");
            throw std::runtime_error("无法打开视频源");
        }
    }

private:
    void timer_callback() {
        cv::Mat frame;
        cap_ >> frame;
        if (!frame.empty()) {
            auto message = cv_bridge::CvImage(
                std_msgs::msg::Header(), "bgr8", frame).toImageMsg();
            message->header.stamp = this->now();
            message->header.frame_id = "camera_frame";
            publisher_->publish(*message);
            RCLCPP_INFO(this->get_logger(), "发布图像");
        } else {
            RCLCPP_ERROR(this->get_logger(), "无法读取视频帧");
        }
    }

    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr publisher_;
    cv::VideoCapture cap_;
};

int main(int argc, char * argv[]) {
    rclcpp::init(argc, argv);
    auto node = std::make_shared<ImagePublisher>();
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

修改CMakeLists.txt

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(cv_bridge REQUIRED)
find_package(OpenCV REQUIRED)

add_executable(image_publisher src/image_publisher.cpp)
ament_target_dependencies(image_publisher rclcpp sensor_msgs cv_bridge OpenCV)

install(TARGETS image_publisher
  DESTINATION lib/${PROJECT_NAME})

编译运行后用ros2中的rviz2打开可以发现有图像实时显示。

source /opt/ros/foxy/setup.bash
ros2 run image_publisher_cpp image_publisher
ros2 run rviz2 rviz2

3.1 ros1中使用rviz显示图像

(1)启动话题转换节点

source /opt/ros/foxy/setup.bash
ros2 run ros1_bridge dynamic_bridge --bridge-all-topics

(2)启动ros2的图像发布工程
发现转换节点输出

created 2to1 bridge for topic '/image_raw' with ROS 2 type 'sensor_msgs/msg/Image' and ROS 1 type 'sensor_msgs/Image'

说明转换成功
(3)使用ros1中的rviz显示图像

source /opt/ros/noetic/setup.bash
rostopic list
rviz

成功看到图像


网站公告

今日签到

点亮在社区的每一天
去签到