ROS手动编写消息发布器和订阅器topic demo(C++)

ROS手动编写消息发布器和订阅器topic demo(C++)_第1张图片

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 文件:

ROS手动编写消息发布器和订阅器topic demo(C++)_第2张图片

message_generation
  message_runtime
其中 exec_time 也可能是 run_time,看原来的 package.xml 怎么写的。

修改 CMakeLists.txt:

ROS手动编写消息发布器和订阅器topic demo(C++)_第3张图片

ROS手动编写消息发布器和订阅器topic demo(C++)_第4张图片

接下来进入工作空间:

cd ~/catkin_ws
编译:
catkin_make
ROS手动编写消息发布器和订阅器topic demo(C++)_第5张图片

如果类似这样就说明成功了。

进入 devel/include/

cd devel/include/
可以看到有我们的程序包名:


进入,可以看到生成的:

3. 编写 talker.cpp

进入 package 下的 src 目录:

cd ~/catkin_ws/src/topic_demo/src

创建 talker.cpp

vim talker.cpp

将以下代码写入:

#include                          //类似 C 语言的 stdio.h 
#include                   //要用到 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("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("gps_info",1);

advertise 是一个函数模板, 是将其类型定为 gps 类型,这个函数有两个参数,第一个是 topic 名称,消息在 publisher 上会先存在一个消息队列中,第二个参数决定了消息队列的长度。

保存退出,创建 listener.cpp

vim listener.cpp

将以下代码写入:

#include 
#include 
#include    //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

将以下语句加入

ROS手动编写消息发布器和订阅器topic demo(C++)_第6张图片

保存退出


5. 编译运行

启动 master

roscore

进入工作空间

cd ~/catkin_ws

编译

catkin_make

分别运行

rosrun topic_demo talker 
rosrun topic_demo listener

运行结果:

ROS手动编写消息发布器和订阅器topic demo(C++)_第7张图片

ROS手动编写消息发布器和订阅器topic demo(C++)_第8张图片


你可能感兴趣的:(ROS,ROS学习)