ROS2学习笔记29--项目从ROS1迁移到ROS2的经验参考

更新时间:2023-07-05 19:11:40 阅读: 评论:0

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接⼝(⾃定义消息)名称⾸字母必须⼤写;并且需要在l⽂件⾥⾯写:
<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中,⾃定义消息类型(接⼝)时,类型和变量名称只能⼀个空格隔开:
nsor_msgs/PointCloud2              border_area  #ros1 define style,but error in ros2
nsor_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
6)ros2,⾃定义接⼝⽂件名称(注意和包名称区别),⾸字母⼀定要⼤写,字母之间不能有下划线,名称组成不含数字(不知道能不能使⽤数字),建议使⽤驼峰法来命名.正确样式如:
LidarObjectArray.msg
Num.msg
AddThreeInts.srv
3.创建发布者
ros1:
声明:
ros::Publisher objects_info_pub_;
构造函数⾥⾯创建publisher:
objects_info_pub_ = node_handle_.adverti<nsor_msgs::msg::PointCloud2>("/objects_info_pub_topic",10); node_handle_为句柄(ros::handle node_handle_)
ros2:
声明:
rclcpp::Publisher<nsor_msgs::msg::PointCloud2> objects_info_pub_;
构造函数⾥⾯创建publisher:
objects_info_pub_=this->create_publisher<nsor_msgs::msg::PointCloud2>("/objects_info_pub_topic",10);4.创建订阅者
ros1:
声明:
福州北峰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 nsor_msgs::msg::PointCloud2::ConstPtr msg){
//do stuff
}
ros2:
声明:
rclcpp::Subscription<nsor_msgs::msg::PointCloud2>::SharedPtr objects_info_sub_;
在类构造函数中创建subscriber,并启动回调函数:
//--------------------create_subscription-----------------------------
objects_info_sub_ =this->create_subscription<nsor_msgs::msg::PointCloud2>(
objects_info_pub_topic,1,
std::bind(&Callback,
this, std::placeholders::_1));
//或者
objects_info_sub_ =this->create_subscription<nsor_msgs::msg::PointCloud2>(
objects_info_pub_topic,1,
[this](const nsor_msgs::msg::PointCloud2::ConstPtr msg)
{Callback(msg)};
//--------------------/create_subscription-----------------------------
//callback function
void Callback(const nsor_msgs::msg::PointCloud2::ConstPtr msg){
//do stuff
}
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()表⽰仅监听回调函数,并不循环
参考链接:
/articles/13536904.html
6.类
对于ros包类,下⾯是个⼈的基本思考采⽤的⽅式,仅供参考:
ros1:
classA
{
....
};
ros2:
classA:public rclcpp:Node 
{
....
音乐的作用和意义
};
为啥我这么考虑呢?个⼈理解,在ros1时,我们想打印点消息到终端,只要头⽂件包含了"ros/ros.h",直接使⽤ ROS_INFO("...")即可输出,但是ros2⾥⾯输出,并不单单是"rclcpp/rclcpp.h",⽽且需要有节点指针指向get_logger()函数才⾏输出的,如RCLCPP_INFO(this-功败垂成什么意思
>get_logger(),"...");,为了⽅便使⽤this,所以直接继承rclcpp::Node类,来得⽅便.否则,⽬前我能
想到的⽅法是全局构造⼀个节点指针来搞.
参考链接:
7.时间系列
ros1:
时间点声明:
ros::Time timestamp ;
使⽤例⼦:
ros::Time timestamp = ros::Time::now();
时间段声明:
定时器声明:
定时器回调:
ros2:
时间点声明:
rclcpp::Time timestamp ;
使⽤例⼦:
rclcpp::Time timestamp = np->now();//std::shared_ptr<rclcpp::Node> np
时间段声明:
定时器声明:
rclcpp::TimerBa::SharedPtr timer1;
定时器回调:
std::shared_ptr<rclcpp::Node> nh;
//创建定时器
rclcpp::TimerBa::SharedPtr timer1;
//定时器timer1初始化,250ms中断,回调函数timer1_callback
timer1 = nh->create_wall_timer(250ms,timer1_callback);
参考链接:
江南古镇blog.csdn/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
9.部分细节参考
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_u_",true);
this->get_parameter_or<bool>("b_u_", b_u_,true);//⽆法获取时⽤默认值
参考链接:
blog.csdn/yang434584531/article/details/115749810#commentBox
11.创建服务器端
ros1:
ros2:西里古里走廊
参考链接:
12.创建客户端
ros1:
ros2:
参考链接:
13.创建action
ros1:
ros2:
参考链接:
14.初始化init()
ros1:
ros::init(argc, argv,"listener");
ros2:
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",
"intelliSenMode":"linux-gcc-x64"
}
],
"version":4
}

本文发布于:2023-07-05 19:11:40,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1080347.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:参考   名称   创建   路径   函数   报错   需要   数字
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图