ROS1 升级到 ROS2 的一个小例子

本文详细比较了ROS1和ROS2的代码差异,重点讲解了从ROS1到ROS2迁移时涉及的头文件修改、节点创建、消息类型、订阅发布机制以及调度方式的变化。同时提到了在迁移过程中可能出现的错误和解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一 ROS 1 源代码

二 迁移到 ROS2 后的代码

三 ROS1 迁移到 ROS2 的修改的内容

   3.1  头文件

   3.2  节点

   3.3  周期

   3.4  消息类型

   3.5  订阅消息

   3.6  发布消息

   3.7  调度(处理)

           3.8  时间(now)


 一、ROS 1 源代码 :

#include <sstream>
#include <ros/ros.h>
#include <std_msgs/String.h>

static void OnChatSub(const std_msgs::String::ConstPtr& msg) {
   ROS_INFO("%s", msg->data.c_str());
}

int main(int argc, char **argv) {
   ros::init(argc, argv, "talker");

   ros::NodeHandle n;
   ros::Rate loop_rate(10);
   ros::Publisher pub = n.advertise<std_msgs::String>("/chat/pub", 1000);
   ros::Subscriber sub = nh.subscribe("/chat/sub", 10, OnChatSub);

   int count = 0;
   std_msgs::String msg;
   while (ros::ok()) {
      std::stringstream ss; {
         ss << "hello world " << count++;
         msg.data = ss.str();
         ROS_INFO("%s", msg.data.c_str());
      } 

      pub.publish(msg);
      ros::spinOnce();
      loop_rate.sleep();
   }

   return 0;
}

  二、迁移到 ROS2 后的代码:

#include <sstream>
#include <rclcpp/rclcpp.hpp>        // <----- #include <ros/ros.h>
#include <std_msgs/msg/string.hpp>  // <----- #include <std_msgs/String.h>


int main(int argc, char **argv) {
   rclcpp::init(argc, argv);
   auto talker_node = rclcpp::Node::make_shared("talker");
                                    // <---- ros::init(argc, argv, "talcker");

   rclcpp::Rate loop_rate(10);      // <---- ros::Rate loop_rate(10);

   rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub;    // <---- ros::Publisher pub;
   rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub; // <---- ros::Subscriber sub;

        // <---- ros::NodeHandle nh;
        // <---- pub = nh.advertise<std_msgs::String>("/chat/pub", 1000);
        // <---- sub = nh.subscribe("/chat/sub", 10, OnChatSub);

   pub = talker_node->create_publisher<std_msgs::msg::String>("/chat/pub", 1000);
   sub = talker_node->create_subscription<std_msgs::msg::String>("/chat/sub", 10, 
       [this](const std_msgs::msg::String& msg) {
           ROS_INFO("%s", msg.data.c_str());
       }
   );

   int count = 0;
   std_msgs::msg::String msg;       // <---- std_msgs::String msg;
   while (rclcpp::ok()) {           // <---- ros::ok()
      std::stringstream ss; {
         ss << "hello world " << count++;
         msg.data = ss.str();
         ROS_INFO("%s", msg.data.c_str());
      } 

      pub->publish(msg);
      rclcpp::spin_some(talker_node);  // <---- ros::spinOnce();
      loop_rate.sleep();
   }

   return 0;
}

 三、ROS1 迁移到 ROS2 代码中 需要修改的内容:

  3.1  头文件
// #include <ros/ros.h>
   ----> #include <rclcpp/rclcpp.hpp>

// #include <std_msgs/String.h>
   ----> #include <std_msgs/msg/string.hpp>

// #include <geometry_msgs/Twist.h>
   ----> #include <geometry_msgs/msg/twist.hpp>

  3.2 节点

// ros::init(argc, argv, "talcker");
   ---->
        // 一行代码变成两行代码
        rclcpp::init(argc, argv);
        auto talker_node = rclcpp::Node::make_shared("talker");

  3.3 周期

// ros::Rate loop_rate(10);
   ----> rclcpp::Rate loop_rate(10);

// ros::NodeHandle nh;
// nh.shutdown();
   ----> rclcpp::shutdown();

 3.4 消息类型

// std_msgs::String msg;
   ----> std_msgs::msg::String msg;
         // 消息都要加 msg 命名空间
         // 消息的头文件从 .h 改成了 .hpp

 3.5 订阅消息

// ros::Subscriber sub;
   ----> rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub;

// ros::NodeHandle nh;
// sub = nh.subscribe("/chat/sub", 10, OnChatSub);
   ----> sub = talker_node->create_subscription<std_msgs::msg::String>("/chat/sub", 10, 
            [this](const std_msgs::msg::String& msg) {
                      ROS_INFO("%s", msg.data.c_str());
            }
               );

 3.6 发布消息

// ros::Publisher pub;
   ----> rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub;

// ros::NodeHandle nh;
// pub = nh.advertise<std_msgs::String>("/chat/pub", 1000);
   ----> pub = talker_node->create_publisher<std_msgs::msg::String>("/chat/pub", 1000);

  3.7 调度(处理)

1. 单次调用(非阻塞)
   // ros::spinOnce();
      ----> rclcpp::spin_some(talker_node);

2. 死循环调用(阻塞)
   // ros::spin();
      ----> rclcpp::spin(talker_node);   

  3.8 时间(now)

// ros::Time::now();
   ----> rclcpp::Clock().now();

// 时间差
auto start = std::chrono::system_clock::now();
// do something
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> sec = end - start;
printf("diff: %.2f", sec.count());

四 错误处理

  1. this specialization of rclcpp::get_message_type_support_handle() should never be called

ros2 run app_z1 app_z1
terminate called after throwing an instance of 'std::runtime_error'
  what():  this specialization of rclcpp::get_message_type_support_handle() should never be called
[ros2run]: Aborted
-----------------------------------------------------------------------
解决方法:检查回调参数的定义

ROS (Robot Operating System) 系统经历了从版本1ROS 1)向版本2ROS 2)的重大迁移,这是两个完全不同的架构。以下是关于升级的一些关键点: 1. **分层设计**:ROS 2采用了微服务架构,将系统划分为独立、松散耦合的服务,这提高了系统的可靠性和灵活性,而ROS 1一个基于发布/订阅的消息传递模型。 2. **安全性增强**:ROS 2引入了DDS (Data Distribution Service),这是一个更安全的数据通信协议,支持安全性和数据完整性保障,而在ROS 1中,这些问题需要用户自定义解决方案。 3. **API的变化**:API设计有所调整,包括新的包管理工具(ament),以及C++标准库作为默认语言,取代了Python的地位。 4. **多进程通信**:ROS 2倾向于在进程间通信,而不是节点之间共享内存,这增加了跨平台兼容性。 5. **生命周期管理**:ROS 2引入了更好的资源管理和生命周期管理机制,帮助开发者更好地控制节点的启动、运行和停止过程。 6. **社区支持**:尽管ROS 1仍然有活跃的用户和支持,但是许多新开发的项目和研究都已经转向ROS 2,因为它被认为是未来的发展方向。 如果你想要从ROS 1升级ROS 2,可能需要对代码进行重构,特别是处理消息传递和依赖部分,并学习新的工具链和技术。对于现有的ROS 1项目,通常建议先做评估并制定迁移计划,因为不是所有的软件都能无缝迁移到ROS 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值