【ROS2快速学习】

ROS2

去中心化master
不重复造轮子,更换为DDS

工具:

1. 常用指令

功能ROS1ROS2
录制话题rosbag record xxxros2 bag record xxx
播放话题rosbag play xxx.bagros2 bag play xxx
查看数据包内容Rosbag info xxx.bagRos2 bag info xxx.db3
查看话题列表rostopic listRos2 topic list
查看话题列表,
增加消息类型
ros2 topic list -t
输出话题内容Rostopic echo xxxRos2 topic echo xxx
查看某话题rostopic info xxxros2 topic info xxx
查看msg 内容rosmsg show xxxros2 interface show xxx
话题发布rostopic pub xxxros2 topic pub xxx

2. 数据包转换

# 安装 工具
pip3 install rosbags
# 更新
pip3 install --upgrade rosbags
# 下载慢,指定下载源 
pip3 install rosbags -i https://pypi.tuna.tsinghua.edu.cn/simple
# 使用方法  目标文件夹路径: 转换后的数据包存放的文件夹和转换后数据包的名称
rosbags-convert <源文件路径> --dst <目标文件夹路径>
# ros2 -> ros1 
rosbags-convert <your-ros2-bag>
# ros1 -> ros2 
rosbags-convert <your-ros1-bag>

3. 具体区别

消息订阅

ROS1

void chatterCallback(const std_msgs::String::ConstPtr& msg) {
    ROS_INFO("ROS 1 Heard: [%s]", msg->data.c_str());
}
int main(int argc, char** argv) {
    ros::init(argc, argv, "ros1_subscriber");
    ros::NodeHandle nh;
    // 创建订阅者
    ros::Subscriber sub = nh.subscribe("chatter", 10, chatterCallback);
    ROS_INFO("ROS 1 Subscriber ready...");
    // 进入循环处理回调
    ros::spin();
    return 0;
}

ROS2

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using std::placeholders::_1;

class ROS2Subscriber : public rclcpp::Node {
public:
    ROS2Subscriber() : Node("ros2_subscriber") {
        // 创建订阅者 (使用lambda表达式或bind)
        subscription_ = this->create_subscription<std_msgs::msg::String>(
            "chatter", 10, std::bind(&ROS2Subscriber::topic_callback, this, _1));
            
        RCLCPP_INFO(this->get_logger(), "ROS 2 Subscriber ready...");
    }

private:
    void topic_callback(const std_msgs::msg::String::SharedPtr msg) const {
        RCLCPP_INFO(this->get_logger(), "ROS 2 Heard: '%s'", msg->data.c_str());
    }
    
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

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

ROS1

	// 初始化ROS节点
    ros::init(argc, argv, "ros1_publisher");
    ros::NodeHandle nh;
    
    // 创建发布者
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);
    
    ros::Rate rate(1); // 1Hz
    int count = 0;
    
    while (ros::ok()) {
        std_msgs::String msg;
        msg.data = "Hello ROS 1: " + std::to_string(count++);
        // 发布消息
        pub.publish(msg);
  
        ROS_INFO("Published: %s", msg.data.c_str());
        rate.sleep();
    }

ROS2

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

class ROS2Publisher : public rclcpp::Node {
public:
    ROS2Publisher() : Node("ros2_publisher"), count_(0) {
        // 创建发布者 (使用泛型模板)
        publisher_ = this->create_publisher<std_msgs::msg::String>("chatter", 10);
        
        // 创建定时器
        timer_ = this->create_wall_timer(
            1000ms, std::bind(&ROS2Publisher::timer_callback, this));
    }

private:
    void timer_callback() {
        auto message = std_msgs::msg::String();
        message.data = "Hello ROS 2: " + std::to_string(count_++);
        
        // 发布消息
        publisher_->publish(message);
        
        RCLCPP_INFO(this->get_logger(), "Published: '%s'", message.data.c_str());
    }
    
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;
};

int main(int argc, char* argv[]) {
    // 初始化ROS 2
    rclcpp::init(argc, argv);
    
    // 创建并运行节点
    auto node = std::make_shared<ROS2Publisher>();
    rclcpp::spin(node);
    
    // 关闭ROS 2
    rclcpp::shutdown();
    return 0;
}
消息区别

ROS1

# std_msgs/String.msg
# #include "std_msgs/String.h"
string data

ROS2

# std_msgs/msg/String.msg
#include "std_msgs/msg/string.hpp"
# ROS 2 消息在 msg 子命名空间中
string data
自定义消息

ROS1

# my_package/msg/MyCustom.msg

string first_name
string last_name
uint32 age
float32 score

package.xml

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

CMakeLists.txt

find_package(catkin REQUIRED COMPONENTS
  message_generation
  std_msgs
)

add_message_files(
  FILES
  MyCustom.msg
)

generate_messages(
  DEPENDENCIES
  std_msgs
)

catkin_package(
  CATKIN_DEPENDS message_runtime std_msgs
)

ROS2

string first_name
string last_name
uint32 age
float32 score

package.xml

<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rosidl_default_generators</depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>

CMakeLists.txt

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/MyCustom.msg"
  DEPENDENCIES std_msgs
)

ament_export_dependencies(rosidl_default_runtime)
主要架构差别
特性ROS 1ROS 2
节点初始化ros::init()rclcpp::init()
节点创建ros::NodeHandle继承 rclcpp::Node
发布者nh.advertise<>()create_publisher<>()
订阅者nh.subscribe()create_subscription<>()
消息类型std_msgs::Stringstd_msgs::msg::String
回调处理ros::spin()rclcpp::spin()
消息指针ConstPtrSharedPtr
命名空间扁平结构msg 子命名空间
构建系统catkinament_cmake
消息生成message_generationrosidl_default_generators

4. ROS2 调试

# 错误
error while loading shared libraries: libOgreMain.so.1.12.1: cannot open shared object file: No such file or directory

# 解决
source /opt/ros/humble/setup.bash 
# 错误
root@nuc:/workspace# ros2 run rviz2 rviz2 
qt.qpa.xcb: could not connect to display 
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
[ros2run]: Aborted
# 解决
ROS2 Docker 可视化
https://blog.youkuaiyun.com/qq_39779233/article/details/142900876
# 这个写到brshrc 中
export DISPLAY=:0
# 在docker 环境外执行
xhost +local:
ROS2多机
  • 物理连接性测试 组播测试

    # 发送端
    ros2 multicast send
    
    # 接收端
    ros2 multicast receive
    
  • 通讯测试

    sudo apt install ros-humble-examples-rclpy-minimal-publisher
    # 发送端
    ros2 run examples_rclcpp_minimal_publisher publisher_member_function
    # 接收端
    ros2 topic list
    
  • 设置ROS_DOMAIN_ID

    # 设置 domain_id 
    export ROS_DOMAIN_ID=1
    # 打印 domain_id 
    echo $ROS_DOMAIN_ID
    
    • ROS_DOMAIN_ID 相同,即可相互通信
    • ROS_DOMAIN_ID 不同,不可相互通信,但是组播测试成功
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值