自定义一个类型为gps的消息(包括位置x,y和工作状态state信息),一个node以一定频率发布模拟的gps消息,另一个node接收并处理,算出到原点的距离。
自定义消息的实现过程及说明
一、功能包的创建
-
1.进入src目录
cd ~/工作空间名/src
cd ~/catkin_ws/src
-
2.创建功能包
catkin_create_pkg topic_demo roscpp rospy std_msg
使用命令
catkin_create_pkg 功能包名 [依赖项1] [依赖项2] ...
话题编程所依赖的依赖项有:rospy
、roscpp
、std_msgs
。
二、自定义话题消息
(1)创建自定义消息文件步骤
-
1.进入功能包目录
cd ~/工作空间名/功能包名
cd ~/catkin_ws/topic_demo
-
2.创建msg文件夹用来存放msg文件
mkdir msg
-
3.创建msg文件
vi gps.msg
-
4.编辑msg文件
-
msg文件内容:
string state #工作状态 float32 x #x坐标 float32 y #y坐标
-
msg数据类型类似于结构体
在程序中对一个gps消息进行创建修改的方法和对结构体的操作一样。struct gps { string state; float32 x; float32 y; }
-
(2)添加编译选项步骤
-
1.编辑
CMakeLists.txt
- (1)在
find_package
中添加message_generation
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation #需要添加的地方 )
- (2)添加文件夹生成命令
add_message_files(FILES gps.msg) #catkin在cmake之上新增的命令,指定从哪个消息文件生成
- (3)添加生成消息的命令
generate_messages(DEPENDENCIES std_msgs) #catkin新增的命令,用于生成消息 #DEPENDENCIES后面指定生成msg需要依赖其他什么消息,由于gps.msg用到了flaot32这种ROS标准消息,因此需要再把std_msgs作为依赖
- (1)在
-
2.编辑
package.xml
- 添加:
<build_depend>message_generation</build_depend> <run_depend>message_runtime</run_depend>
- 添加:
-
3.编译后产生gps.h头文件,在include目录下
三、创建发布者
- topic_demo/src/talker.cpp
#include <ros/ros.h> #include <topic_demo/gps.h> //自定义msg产生的头文件 int main(int argc, char **argv) { ros::init(argc, argv, "talker"); //用于解析ROS参数,第三个参数为本节点名 ros::NodeHandle nh; //实例化句柄,初始化node topic_demo::gps msg; //自定义gps消息并初始化 ... ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info", 1); //创建publisher,往"gps_info"话题上发布消息 ros::Rate loop_rate(1.0); //定义发布的频率,1HZ while (ros::ok()) //循环发布msg { ... //处理msg pub.publish(msg);//以1Hz的频率发布msg loop_rate.sleep();//根据前面的定义的loop_rate,设置1s的暂停 } return 0; }
四、创建订阅者
-
topic_demo/src/listener.cpp
#include <ros/ros.h> #include <topic_demo/gps.h> #include <std_msgs/Float32.h> void gpsCallback(const topic_demo::gps::ConstPtr &msg) { std_msgs::Float32 distance; //计算离原点(0,0)的距离 distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2)); ROS_INFO("Listener: Distance to origin = %f, state: %s",distance.data,msg->state.c_str()); //输出 } int main(int argc, char **argv) { ros::init(argc, argv, "listener"); ros::NodeHandle n; ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback); //设置回调函数gpsCallback ros::spin(); //ros::spin()用于调用所有可触发的回调函数,将进入循环,不会返回,类似于在循环里反复调用spinOnce() //而ros::spinOnce()只会去触发一次 return 0; }
五、添加编译选项
-
CMakeLists.txt
的修改add_executable(talker src/talker.cpp) #生成可执行文件talker add_dependencies(talker topic_demo_generate_messages_cpp) #表明在编译talker前,必须先生编译完成自定义消息 #必须添加add_dependencies,否则找不到自定义的msg产生的头文件 #表明在编译talker前,必须先生编译完成自定义消息 target_link_libraries(talker ${catkin_LIBRARIES}) #链接 add_executable(listener src/listener.cpp ) #声称可执行文件listener add_dependencies(listener topic_demo_generate_messages_cpp) target_link_libraries(listener ${catkin_LIBRARIES})#链接
六、编译运行
(1)编译
-
进入工作空间
cd ~/catkin_ws
-
编译
catkin_make
(2)运行
-
运行发布者
rosrun topic_demo talker
-
运行订阅者
rosrun topic_demo listener