C++版本

  1. ros::init(argc, argv, "node_name");

ros系统的初始化函数,使用ros系统提供的APIs的前提必须步骤

  1. ros::NodeHandle nh;

句柄函数,话题、服务和参数服务器的公共接口

  1. ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);

广播一个话题,同时负责订阅者状态的回调。用到的参数依次是:话题名称,队列大小。尖括号中是使用的信息类型

  1. ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter", 10, doMsg);

注册一个话题订阅服务器,接收消息并用回调函数处理。用到的参数依次是:话题名称,队列大小、回调函数名(句柄)

  1. ros::Rate r(1);

Rate()是一个类,使用前要先实例化。构造函数起到的是一个定时器的作用。允许你指定一个循环的频率,该对象会记录距离上次调用Rate::sleep的时间差,并且sleep恰当的时间保证循环频率的正确。

一般Rate::sleep()会包括在一个死循环中,由系统负责任务的调度。

  1. ros::spin()ros::spinOnce()

一看名字就知道这是俩亲兄弟,学名叫ROS消息回调处理函数,通常出现在ROS的主循环中,程序需要不断调用spin()spinOnce()

这里摘抄一段网上的解释:

消息订阅器一旦知道chatter上面有data,就会将这data作为参数传入callback函数中,但是此时还没有执行callback函数,而是把callback函数放到了一个回调函数队列中。所以当发布器不断发送data到chatter上面时,就会有相应的callback函数进入队列中,它们函数名一样,只是实参不一样。

那么什么时候才会执行callback函数呢?

就是ros::spin()和ros::spinOnce()的事了。

当spinOnce函数被调用时,spinOnce就会调用回调函数队列中第一个callback函数,此时callback函数才被执行,然后等到下次spinOnce函数又被调用时,回调函数队列中第二个callback函数就会被调用,以此类推。

所以,这会有一个问题。因为回调函数队列的长度是有限的,如果发布器发送数据的速度太快,spinOnce函数调用的频率太少,就会导致队列溢出,一些callback函数就会被挤掉,导致没被执行到。

而对于spin函数,一旦进入spin函数,它就不会返回了,相当于它在自己的函数里面死循环了。只要回调函数队列里面有callback函数在,它就会马上去执行callback函数。如果没有的话,它就会阻塞,不会占用CPU。

发布方使用spinOnce(),等待订阅方接受信息并调用回调函数。

订阅方使用spin(),进入spin的死循环中,一直循环着接收发布方的消息。