ROS1和ROS2的区别以及ros的topic话题

一.ROS1和ROS2的区别

ROS1和ROS2的区别以及ros的topic话题_第1张图片ROS1和ROS2的区别以及ros的topic话题_第2张图片

ROS虽然将各个部分的各个组件给有机的连接起来,但是需要通过一个叫做Ros Master的东西,所有节点(可以理解为某一个组件,比如:激光雷达)的通信建立必须经过这个主节点,一旦Ros Master主节点挂掉后,就会造成整个系统通信的异常。 

除了不稳定这个问题,ROS还有很多其他地方存在着问题:

•通信基于TCP实现,实时性差、系统开销大

•对Python3支持不友好,需要重新编译

•消息机制不兼容

•没有加密机制、安全性不高

OS层

从原来的只支持linux平台变成了支持windows、mac甚至是嵌入式RTOS平台,这一点要点个赞。之前认识公众号一老哥,做扫地机器人,为了降低成本,平台性能真的是非常的受限。

MiddleWare中间件层

1.去中心化master,ROS和ROS2中间件不同之处在于,ROS2不要了master节点。去中心化后,各个节点直接可以通过DDS的进行节点之间的相互发现,各个节点都是平等的,且可以1对1、1对n、n对n进行互相通信。

1.不造通信的轮子,通信直接更换为DDS进行实现(这个小智也要点赞,让专业的人做专业的事情)采用DDS通信,使得ROS2的是实行、可靠性和连续性上都有了增强。

ROS2进行改进有:

1.python2到pyhton3的支持

2.编译系统的改进(catkin到ament)

3.软件包更新到c++11

4.可以使用相同 API 的进程间和进程内通信

5.持续更新........

ROS1中的话题机制还存在吗?

答案:还是存在的,只不过命令行参数变了很多。ROS2向下兼容ROS1。

二.ros的topic话题

ROS 消息队列的运行机制
下面只是自己的理解,如果有误望大家指正!
问:ROS中,publisher和subscriber都有一个消息队列用于数据收发时候的缓存,那么它们的作用分别是什么?
答:ROS话题的通信是异步的,也就是publisher只管不停的发但不管是否被接收,publisher是向Topic的消息队列发布信息,而不是publisher直接push给subscriber,publisher发送数据后,订阅该topic的subscriber则会过来读取,系统会通过位置指针管理不同subscriber读取消息队列的位置,因此可以支持任意多个subscriber对话题进行读取,每个subscriber读取到数据后,会将数据放置到自己的缓存队列上,然后触发注册的回调函数进行处理…
        综上所述,publisher不停将消息发布到消息队列上,直到队列占满,然后新到的消息把最老的消息挤出队列,因此,publisher消息队列的作用就是,缓存一定数量的历史信息,让不能及时订阅的subscriber能读取到之前发布的信息。如果没这个需求或是想让subscriber读取到最新的消息,那么让消息队列长度设为1 。
        而subscriber的消息队列的作用是,将回调函数来不及处理的信息及时的缓存,这样不至于因为回调函数执行或调用过慢,导致数据的丢失。
多话题回调机制

ros::spinOnce()和spin()

当一个节点订阅了多个话题时,每调用一次ros::spinOnce(),每个接收到消息的subscriber都去执行它的回调函数,那么问题来了,每个subscriber执行回调函数的次数是多少呢?难道每次每个subscriber就调用一次回调函数? 还有多个subscriber的回调函数的执行顺序是什么样呢?
上一节讲到了,subscriber的消息队列用于缓存来不及处理的消息,那么每次调用ros::spinOnce()时,如果各个subscriber只是执行一次回调函数,那么消息队列估计很长时间都不会清0, 所以, 应该说每次调用ros::spinOnce()都会执行与消息队列中缓存的信息数量相同次数的回调函数,只要回调函数执行够快的话,就能清空队列。
另外, 当多个subscriber都需要调用回调函数时,则按顺序依次执行各个subscriber的回调函数。
 

执行一次spinOnce()所调用的所有回调函数的输出,可见chatter2在执行回调函数里的1S延时操作时,消息队列的数据也更新了,也就是说,执行回调函数时,消息队列并不会被锁定住。
另外,在chatter2回调函数延时的时候,chatter1的回调函数也是处于等待当中,就是说这些回调函数都是串行执行的。
而ros::spin()可以看作r.sleep()=0的ros::spinOnce(),即
while (ros::ok())
{
ros::spinOnce();
}

ros::MultiThreadedSpinner
MultiThreadedSpinner的用法是:

  ros::MultiThreadedSpinner spinner(4); // 数字表示调用的线程数  
  spinner.spin(); // spin() will not return until the node has been shutdown


通过MultiThreadedSpinner调用的回调函数就不再是串行执行的了,而是多线程并行执行!

总结:
1、spinOnce()/spin()调用时是串行执行所有的回调函数,并且是各个话题按顺序执行的,执行的次数与调用spinOnce()时消息队列的元素个数相同。
2、MultiThreadedSpinner调用的回调函数就不再是串行执行的了,而是多线程并行执行。

你可能感兴趣的:(算法,人工智能)