ROS2学习笔记29--项目从ROS1迁移到ROS2的经验参考
Posted 鸿_H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ROS2学习笔记29--项目从ROS1迁移到ROS2的经验参考相关的知识,希望对你有一定的参考价值。
环境:ubuntu20.04 ,ros-foxy(ros2),vscode
背景:项目需要,一直折腾把ros1下面的包升级到ros2版本.以下纯属个人查找资料摸索,自我理解所得,有错误的地方,望大佬们不吝赐教.
1.消失的句柄
ros1里面有成员句柄,里面还分各种命名空间啥的,然后跟话题,参数息息相关,而在ros2里面就没有句柄成员了,个人感觉是可采用节点指针来取代其功能.
ros1句柄:
ros::NodeHandle nh;
ros2可改写:
std::shared_ptr<rclcpp::Node> nh;
参考链接:
2.接口文件(msg/srv)编写规则
1)ros2
接口(自定义
消息)名称首字母
必须大写
;并且需要在packages.xml
文件里面写:
<member_of_group>rosidl_interface_packages</member_of_group>
2)编译接口(自定义数据类型)包时,注意:
Header header #ros1,but error in ros2
std_msgs/Header header #ros2 witten
3)包名字,不
能有连续
的下划
线,不
能在最后
有下划
线;第一个字符
必须是字母
,后面字符可以是字母数字下划线
,但保证不能下划线是最后.错误例子,如:
custom__msg
custom_msg_
2custom_msg
正确案例:
custom_msg
4)ros2中,自定义消息类型(接口)时,类型和变量名称只能一个空格
隔开:
sensor_msgs/PointCloud2 border_area #ros1 define style,but error in ros2
sensor_msgs/PointCloud2 border_area #ros2 style
5)ros2中,自定义消息类型(接口)时,名称只能由小写字母
或单个下划线
和数字
组成:
float32 WB_Angle_Feedback #ros1,error in ros2
float32 wb_angle_feedback #ros2
float32 wb_angle_feedback_1 #ros2
3.创建发布者
ros
1:
声明:
ros::Publisher objects_info_pub_;
构造函数里面创建publisher:
objects_info_pub_ = node_handle_.advertise<sensor_msgs::msg::PointCloud2>( "/objects_info_pub_topic", 10);
node_handle_
为句柄
(ros::handle node_handle_
)
ros
2:
声明:
rclcpp::Publisher<sensor_msgs::msg::PointCloud2> objects_info_pub_;
构造函数里面创建publisher:
objects_info_pub_= this->create_publisher<sensor_msgs::msg::PointCloud2>("/objects_info_pub_topic", 10);
参考链接:https://blog.csdn.net/qq_45701501/article/details/118577437
4.创建订阅者
ros
1:
声明:
ros::NodeHandle n;
ros::Subscriber objects_info_sub_;
在类构造函数里面创建subscriber,并启动回调函数:
//--------------------create_subscription-----------------------------
objects_info_sub_= n.subscribe("objects_info_pub_topic", 1, Callback);
//callback function
void Callback(const sensor_msgs::msg::PointCloud2::ConstPtr msg){
//do stuff
}
ros
2:
声明:
rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr objects_info_sub_;
在类构造函数中创建subscriber,并启动回调函数:
//--------------------create_subscription-----------------------------
objects_info_sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
objects_info_pub_topic, 1,
std::bind(&Callback,
this, std::placeholders::_1));
//或者
objects_info_sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
objects_info_pub_topic, 1,
[this](const sensor_msgs::msg::PointCloud2::ConstPtr msg)
{Callback(msg)};
//--------------------/create_subscription-----------------------------
//callback function
void Callback(const sensor_msgs::msg::PointCloud2::ConstPtr msg){
//do stuff
}
参考链接:https://blog.csdn.net/qq_45701501/article/details/118577437
5.spin()和shutdown()系列
ros1 -> ros2
ros::spin(); rclcpp::spin(node);//std::shared_ptr<rclcpp::Node> node
ros::spinOnce(); rclcpp::spinOnce(node);//std::shared_ptr<rclcpp::Node> node
ros::shutdown(); rclcpp::shutdown();
spin()
表示循环并监听回调函数;spinOnce()
表示仅监听回调函数,并不循环
参考链接:
https://roboticsbackend.com/ros2-rclcpp-parameter-callback/
https://www.huaweicloud.com/articles/13536904.html
6.类
对于ros包类,下面是个人的基本思考采用的方式,仅供参考:
ros
1:
class A
{
....
};
ros
2:
class A : public rclcpp:Node
{
....
};
为啥我这么考虑呢?个人理解,在ros1
时,我们想打印点消息到终端,只要头文件包含了"ros/ros.h"
,直接使用 ROS_INFO("...")
即可输出,但是ros2里面输出,并不单单是"rclcpp/rclcpp.h"
,而且需要有节点指针
指向get_logger()
函数才行输出的,如RCLCPP_INFO(this->get_logger(),"...");
,为了方便使用this
,所以直接继承rclcpp::Node
类,来得方便.否则,目前我能想到的方法是全局构造一个节点指针来搞.
参考链接:
7.时间系列
ros
1:
时间点声明:
ros::Time timestamp ;
使用例子:
ros::Time timestamp = ros::Time::now();
时间段声明:
定时器声明:
定时器回调:
ros
2:
时间点声明:
rclcpp::Time timestamp ;
使用例子:
rclcpp::Time timestamp = np->now();//std::shared_ptr<rclcpp::Node> np
时间段声明:
定时器声明:
rclcpp::TimerBase::SharedPtr timer1;
定时器回调:
std::shared_ptr<rclcpp::Node> nh;
//创建定时器
rclcpp::TimerBase::SharedPtr timer1;
//定时器timer1初始化,250ms中断,回调函数timer1_callback
timer1 = nh->create_wall_timer(250ms,timer1_callback);
参考链接:
https://blog.csdn.net/yang434584531/article/details/115749810#commentBox
8.创建包以及编译指令
ros1:
创建包:
catkin_create_pkg <package_name>
编译包:
catkin_make
ros2:
创建包:
ros2 pkg create --build-type ament_cmake <package_name>
编译包:
colcon build
参考链接:https://blog.csdn.net/qq_45701501/article/details/118574569#t6
9.cmakelists.txt部分细节参考
ros2:
launch文件夹查找标签:
参考链接:
10.parameter参数系列
ros1:
ros::handle node_handle;
node_handle_.param("/listen_freq_param", listen_freq_, 1000);
ros2:
rclcpp::Node::SharedPtr nh;
nh->get_parameter_or("/listen_freq_param", listen_freq_, 1000);
这里有个小疑惑,参考材料说,"/listen_freq_param"这个参数,需要声明才能使用使用,形式如:
this->declare_parameter<bool>("b_use_", true);
this->get_parameter_or<bool>("b_use_", b_use_, true);//无法获取时用默认值
参考链接:
https://blog.csdn.net/yang434584531/article/details/115749810#commentBox
11.创建服务器端
ros1:
ros2:
参考链接:
12.创建客户端
ros1:
ros2:
参考链接:
13.创建action
ros1:
ros2:
参考链接:
14.初始化init()
ros
1:
ros::init(argc, argv, "listener");
ros
2:
rclcpp::init(argc, argv);
ros1的话,初始化时候,随便给了节点名了,但在ros2里面,只是初始化,节点名在其他地方搞的,如:
auto node = rclcpp::Node::make_shared("listener");
参考链接:
16.vscode的cpp开发时路径配置经验参考
1)编译器空间,尽量保证只放一个包,目地是防止路径污染导致疏忽错误;
2)路径添加,第一种是安装在系统上面的,如"/opt/ros/foxy/include/"
,第二种是自定义的,如自定义包位置,"/home/ylh/xxx_ws/install/custom_pkg_xxx/include"
,还有自己当前包的头文件引用,如"${workspaceFolder}/include"
3)路径添加方式,第一次加载包时,头文件会有很多下划波浪线报错,光标停留报错行,会出现 小灯泡 ,单击小灯泡,打开界面;此时会在编译器工作空间的目录,生成 .vscode
文件夹,选择文件c_cpp_properties.json,
添加上述路径,效果如:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/home/ylh/xxx_ws/install/custom_pkg_xxx/include",
"/opt/ros/foxy/include/",
"${workspaceFolder}/include"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
注意,自定义包的头文件路径,一般都是在所在工作空间编译生成的include
文件夹下面的 包名/include
.
如果担心手写路径写错的话,可终端cd
进去目标文件夹,pwd
输出全路径,在复制过来即可.
17.打印终端输出
ros1版本:
ROS_INFO_ONCE("Waiting for yqy...");
ros2版本:
RCLCPP_INFO_ONCE(nh->get_logger(),"Waiting for yqy...");
解析:nh
为(rclcpp::Node
)节点指针,如果是在rclcpp::Node
子类里面,可使用this->get_logger()
.
其他输出类似,把ROS
修改成RCLCPP
,然后括号里面添加xx->get_logger(),
,如:
ROS_INFO -> RCLCPP_INFO
ROS_DEBUG -> RCLCPP_DEBUG
......
18.头文件引用自定义接口
ros1版本:
#include <std_msgs/Int16MultiArray.h> //ros1写法
ros2版本:
#include <std_msgs/msg/int16_multi_array.h>//ros2写法,增加了详细路径msg以及将大写改为小写,
//并添加以大写字母为界添加下划线
19.回调函数的形参
//ros1:
void callback(const std_msgs::String::ConstPtr & msg);
//ros2:
void callback(std_msgs::msg::String::ConstSharedPtr msg);
注意形式参数写法的变化
其他
奈何笔记过于凌乱,后续继续更新上面内容....
#####################
不积硅步,无以至千里
好记性不如烂笔头
感觉有点收获的话,麻烦大大们点赞收藏哈
以上是关于ROS2学习笔记29--项目从ROS1迁移到ROS2的经验参考的主要内容,如果未能解决你的问题,请参考以下文章