ROS话题通信案例(三)——自定义消息msg(c++和python)
参考视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程_哔哩哔哩_bilibili
参考文档:http://www.autolabor.com.cn/book/ROSTutorials/
需求:
创建自定义消息,该消息包含人的信息:姓名、身高、年龄等。
流程:
- 按照固定格式创建 msg 文件
- 编辑配置文件
- 编译生成可以被 Python 或 C++ 调用的中间文件
1.定义msg文件
功能包下新建 msg 目录,添加文件 Person.msg
string name uint16 age float64 height
2.编辑配置文件
package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend> <!-- exce_depend 以前对应的是 run_depend 现在非法 -->
CMakeLists.txt编辑 msg 相关配置
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation ) # 需要加入 message_generation,必须有 std_msgs ## 配置 msg 源文件 add_message_files( FILES Person.msg ) # 生成消息时依赖于 std_msgs generate_messages( DEPENDENCIES std_msgs ) #执行时依赖 catkin_package( # INCLUDE_DIRS include # LIBRARIES demo02_talker_listener CATKIN_DEPENDS roscpp rospy std_msgs message_runtime # DEPENDS system_lib )
3.编译
编译后的中间文件查看:
C++ 需要调用的中间文件(.../工作空间/devel/include/包名/xxx.h)
Python 需要调用的中间文件(.../工作空间/devel/lib/python3/dist-packages/包名/msg)
C++实现
需求:
编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布自定义消息,订阅方订阅自定义消息并将消息内容打印输出。
分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
- 发布方
- 接收方
- 数据(此处为自定义消息)
流程:
- 编写发布方实现;
- 编写订阅方实现;
- 编辑配置文件;
- 编译并执行
0.vscode 配置
为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性
"/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径
1.发布方
#include "ros/ros.h" #include "plumbing_pub_sub/Person.h" /* 发布者:发布人的消息 1.包含头文件; 2.初始化ROS节点 3.创建节点句柄 4.创建发布者对象 5.编写发布者逻辑,发布数据。 */ int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ROS_INFO("这是消息发布方"); // 2.初始化ROS节点 ros::init(argc,argv,"banZhuanRen"); // 3.创建节点句柄 ros::NodeHandle nh; // 4.创建发布者对象 ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("Chat",10); // 5.编写发布者逻辑,发布数据。 //5.1.被发布的数据 plumbing_pub_sub::Person person; person.name = "张三"; person.age = 1; person.height = 1.73; //5.2.设置发布的频率 ros::Rate rate(1); //5.3.循环发布数据 while (ros::ok()) { //修改数据 person.age += 1; //核心:数据发布 pub.publish(person); ROS_INFO("发布的消息:%s,%d,%.2f",person.name.c_str(),person.age,person.height); //休眠 rate.sleep(); //建议 ros::spinOnce(); } return 0; }
配置
执行
2.订阅方
#include "ros/ros.h" #include "plumbing_pub_sub/Person.h" /* 订阅方:订阅消息 1.包含头文件; #include "plumbing_pub_sub/Person.h" 2.初始化ROS节点 3.创建节点句柄 4.创建订阅者对象 5.处理订阅的数据 6.调用spin()函数 */ void doPerson (const plumbing_pub_sub::Person::ConstPtr& person){ ROS_INFO("订阅人的信息:%s,%d,%.2f",person->name.c_str(),person->age,person->height); } int main(int argc, char *argv[]) { setlocale(LC_ALL,""); ROS_INFO("订阅方实现"); // 2.初始化ROS节点 ros::init(argc,argv,"jiaZhang"); // 3.创建节点句柄 ros::NodeHandle nh; // 4.创建订阅者对象 ros::Subscriber sub = nh.subscribe("Chat",10,doPerson); // 5.处理订阅的数据 // 6.调用spin()函数 ros::spin(); return 0; }
配置
执行
python 实现
0.vscode配置
将自定义 msg 所在的文件夹配置进 settings.json
1.发布方
在 scripts 下新建 demo03_pub_person_p.py
#! /usr/bin/env python import rospy from plumbing_pub_sub.msg import Person ''' 发布方:发布人的消息 1.导包; 2.初始化ROS节点; 3.创建发布者对象; 4.组织发布逻辑并发布数据。 ''' if __name__ == "__main__": # 2.初始化ROS节点; rospy.init_node("daMa") # 3.创建发布者对象; pub = rospy.Publisher("jiaoSheTou",Person,queue_size=10) # 4.组织发布逻辑并发布数据。 # 4.1.创建 Person 数据 p = Person() p.name = "奥特曼" p.age = 8 p.height = 1.85 # 4.2.创建 Rate 对象 rate = rospy.Rate(1) # 4.3.循环发布数据 while not rospy.is_shutdown(): pub.publish(p) rospy.loginfo("发布的消息:%s,%d,%.2f",p.name,p.age,p.height) rate.sleep()
2.权限设置
给 py 文件增加可执行权限
cys@ubuntu:~/demo03_ws/src/plumbing_pub_sub/scripts$ chmod +x *.py
3.配置 CMakeLists.txt
更改 CMakeLists.txt 中的配置
4.命令行测试
cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
cys@ubuntu:~/demo03_ws$ rosrun plumbing_pub_sub demo03_pub_person_p.py
cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
cys@ubuntu:~/demo03_ws$ rostopic echo jiaoSheTou
5.订阅方
在 scripts 下新建 demo04_sub_person_p.py
#! /usr/bin/env python import rospy from plumbing_pub_sub.msg import Person ''' 订阅方:订阅人的消息 1.导包; 2.初始化ROS节点; 3.创建订阅者对象; 4.处理订阅的数据; 5.spin()。 ''' def doPerson(p): rospy.loginfo("小伙子的数据:%s,%d,%.2f",p.name,p.age,p.height) if __name__ == "__main__": # 2.初始化ROS节点; rospy.init_node("daYe") # 3.创建订阅者对象; sub = rospy.Subscriber("jiaoSheTou",Person,doPerson) # 4.处理订阅的数据; # 5.spin()。 rospy.spin()
修改权限和配置
6.运行
启动发布方
启动订阅方
cys@ubuntu:~/demo03_ws$ source ./devel/setup.bash
cys@ubuntu:~/demo03_ws$ rosrun plumbing_pub_sub demo04_sub_person_p.py
7.绘制计算图
cys@ubuntu:~$ rqt_graph