ROS手动编写消息发布器和订阅器topic demo(C++)
1.首先创建 package
cd ~/catkin_ws/src
catkin_create_pkg topic_demo roscpp rospy std_msgs
2. 编写 msg 文件
cd topic_demo mkdir msg cd msg vim gps.msg
将以下代码写入:
float32 x float32 y string state
x 是横坐标,y 是纵坐标,state 是状态
还记得以前说的吗:点击打开链接
修改 package.xml 文件:
<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
其中 exec_time 也可能是 run_time,看原来的 package.xml 怎么写的。
修改 CMakeLists.txt:
接下来进入工作空间:
cd ~/catkin_ws
编译:
catkin_make
如果类似这样就说明成功了。
进入 devel/include/
cd devel/include/
可以看到有我们的程序包名:
进入,可以看到生成的:
3. 编写 talker.cpp
进入 package 下的 src 目录:
cd ~/catkin_ws/src/topic_demo/src
创建 talker.cpp
vim talker.cpp
将以下代码写入:
#include <ros/ros.h> //类似 C 语言的 stdio.h #include <topic_demo/gps.h> //要用到 msg 中定义的数据类型 int main(int argc,char **argv){ ros::init(argc,argv,"talker"); //解析参数,命名节点为 talker ros::NodeHandle nh; //创建句柄,相当于一套工具,可以实例化 node,并且对 node 进行操作 topic_demo::gps msg; //创建 gps 消息 msg.x = 1.0; //设置 x 初值 msg.y = 1.0; //设置 y 初值 msg.state = "working"; //设置 state 初值 ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info",1);//创建 publisher 对象 ros::Rate loop_rate(1.0); //创建 rate 对象,定义循环发布的频率,1 HZ while(ros::ok()){ //只要没有关闭,一直循环 msg.x = 1.03 * msg.x; //以指数增长,每隔 1s msg.y = 1.01 * msg.y; ROS_INFO("Talker:GPS: x = %f,y = %f",msg.x,msg.y); //打印函数,类似 printf() pub.publish(msg); //发布消息 loop_rate.sleep(); //根据定义的发布频率,sleep } return 0; }
其中 nh.advertise<topic_demo::gps>("gps_info",1);
advertise<topic_demo::gps> 是一个函数模板,<topic_demo::gps> 是将其类型定为 gps 类型,这个函数有两个参数,第一个是 topic 名称,消息在 publisher 上会先存在一个消息队列中,第二个参数决定了消息队列的长度。
保存退出,创建 listener.cpp
vim listener.cpp
将以下代码写入:
#include <ros/ros.h> #include <topic_demo/gps.h> #include <std_msgs/Float32.h> //ROS自带的浮点类型,类似 float,但是不同 void gpsCallback(const topic_demo::gps::ConstPtr &msg){ //回调函数,参数类型为 ConstPtr 类型的指针,它被定义在之前编译生成的 gps.h 中,指向 gps 的消息 std_msgs::Float32 distance; //声明一个距离变量 distance distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2)); //之所以是 distance.data,是因为 Floa32 是一个结构体,成员变量 data 才存储着值 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); // ros::spin(); return 0; }
n.subscribe(),第一个参数指明需要监听哪个 topic,第二个是 subscribe 的消息队列长度,第三个参数一般是个指针,指向了处理此消息的回调函数。也就是你希望对接收到的消息进行怎么样的处理,都写在第三个参数所指向的函数中。
目前的工作已经完成的差不多了,最后
4. 修改 CMakeLists.txt
将以下语句加入
保存退出
5. 编译运行
启动 master
roscore
进入工作空间
cd ~/catkin_ws
编译
catkin_make
分别运行
rosrun topic_demo talker
rosrun topic_demo listener
运行结果: