背景介绍
- 自动驾驶系统包括障碍物检测、行为决策、路径规划等一系列复杂的工程模块,同时还要支持激光雷达、相机、GPS等一系列传感器的实时数据收集和实时处理。如何将这些功能模块相互独立又相互交互集成一起,构建成一个稳定的自动驾驶系统是一个巨大的挑战,也是自动驾驶计算框架所承载的基本功能。
- 使用框架开发,可以将更多的精力放在算法模块的迭代上
- 框架能够在开发阶段减少各个模块(感知、定位、决策控制等)之间的耦合,在运行阶段可以将各个模块串联起来
- 自动驾驶涉及大量的图像点云处理算法,对于可视化和调试工具有很大的需求
- 障碍物检测需要看Detection的那个框准不准
- 路径规划需要看自动驾驶算法规划的路径是否符合当前的一些决策行为
- 定位也需要看车辆当前是否在准确的车道内
- 为什么是ROS?
- ROS是一个比较强大、灵活的机器人编程框架。从软件架构的层面来说,它是一个基于消息传递的分布式多进程框架,很早就被机器人行业广泛使用。很多著名的机器人开发框架,如基于四元数的坐标转换、3D点预处理驱动、定位算法、SLAM等都是基于ROS开发的开源的现成方案。
- ROS基于消息机制,开发者可以根据功能把软件拆分成独立的子模块,子模块通过不断的组合能够建立起比较复杂的系统来完成复杂的功能。
- ROS是学术界广泛使用的一个框架,对实验各种新算法提供了一些支持。
ROS概述
- ROS的历史
- ROS是2007年在斯坦福大学里面的一个实验室学生开发出来的一套机器人通用的一个框架,2013年被纳入OSRF机构统一管理,如今被很多公司和大学的研究所广泛地使用到一些科研项目中。
- ROS的特征(点对点、分布式、跨语言、轻量级、开源)
- 点对点:两个节点之间进行消息通讯是一个点对点的行为。
- 它支持分布式:在部署多机之间的消息通讯时,ROS提供了一个天然的支持。
- 它是跨语言,它并不关注每个节点之间是用什么语言来写的。你只需要按照ROS提供的一些接口完成消息的订阅和分发即可以完成一个消息之间的通信。
- 它是一个轻量级的ROS程序,用户只需要关注自己核心模块的算法逻辑,不需要关注底层是如何通信、如何断开通信、如何进行服务和参数之间的一些交互的。
- 它是一个开源的框架,大家都可以往ROS里面贡献自己的一些想法和代码。
- 核心概念
- 松耦合
- ROS是一个松耦合的框架,松耦合就是各个节点之间的通信是一个解耦合的关系。
- 节点
- 自动驾驶系统里面的感知模块、定位模块、决策模块或者控制模块,这些模块就是一个简单的算法集合,在ROS里面被称为一个节点。
- 节点管理器
- 在ROS里面被定义为Master,用来集中式管理各个独立的、松耦合、无序节点之间的逻辑关系,它是轻量级的介入,当各个节点启动完成以后,他们在通信连接完成之前起到中转也就是类似于交换机的作用。
- Topic
- 两个节点之间的通信主题。
- Topic内部使用的数据格式是Message。
- 松耦合
- ROS运行例子:
- Perception、Planning在启动的时候没有先后关系
- Perception先启动并向Roscore发送一个注册信息,同时会订阅名为Obstacle的Topic
- Planning节点启动后也向Roscore发送一个注册信息,同时会订阅名为Obstacle的Topic
- 在这种情况下,Roscore会发送一个通知信息给Planning,在它发送注册信息之前已经有一个节点启动了
- 此时Planning会向Perception发送消息请求通信连接,Planning收到消息之后会在Planning和Perception两个节点中间建立一个实时通信链路
- 当通信链路建立之后,Roscore的功能就暂时完成了
- 松耦合在此有两种体现
- Perception和Planning两者之间的启动没有先后关系。
- 当通信链路建立之后,Roscore的功能就暂时完成了。
ROS实践
启动Roscore
1
roscore
通过一个简单的命令行
roscore
就可以启动一个节点管理器,不需要进行任何参数的传入,也不需要进行任何配置如果有很多个节点启动的时候,会使用
roslaunch
启动一个Talker程序
1
rosrun roscpp_tutorials talker
rosrun
,前面是Package包,后面是实际的可执行文件,通过这样简单的一个命令可以直接启动一个Talker
查看Talker Node
1
2
3
4
5
6
7
8列出Node
rosnode list
查看Node的信息
rosnode info /talker
查看Topic的信息
rostopic info /chatterNode的信息包含发送的Topic以及它发送的Service
通过这个
rostopic info
命令我们能看到Topic的发送方和接收方rostopic type
是查看Topic的一个Message的消息类型rostopic echo
是相当于起了一个Listener节点,去展示Talker发的Topic包含的具体信息
启动一个Listener节点
1
rosrun roscpp_tutorials listener
Listener启动向Roscore发送一个注册信息,同时会订阅Topic
Roscore会发送一个通知信息给Listener:在它发送注册信息之前已经有一个节点启动了
此时,Listener会向Talker发送消息请求通信连接,Listener收到消息之后会在Listener和Talker两个节点中间建立一个实时通信链路
这个通信链路是基于TCP的
ROS的Catkin编译系统
1
2
3
4
5
6
7
8Build a package with
catkin build package_name
Whenever you build a new package, update your environment
source devel/setup.bash
Launch the node with
roslaunch ros_package_template ros_package_template.launch在启动节点的时候使用了Roslaunch,Roslaunch是一个Shell脚本文件
ROS原理(一)
ROS的不足
- 大数据传输性能瓶颈
- 实验性项目里面采用的Topic是Message,数据量是比较小的,但在实际自动驾驶场景里面数据量非常大。
- ROS架构对大数据传输存在很大的性能瓶颈,一种直接后果是时延非常高,这在自动驾驶整个系统里面是非常危险的。
- 单中心的网络存在单点风险
- 整个ROS虽然是一个松耦合的架构,节点管理器介入的时候,只是在节点建立通信之前有一个简单的拓扑映射
- 这种关系虽说极大程度释放了各个节点之间开发的耦合,但同时也带来了比较大的风险
- 如果Roscore存在一些故障退出,而节点之间使用了需要不定时的交互方式,像服务、参数进行数据交互的时候就会存在一定的风险
- 数据格式缺乏后向兼容
- ROS是基于Message的分发和订阅的消息通讯框架,使用Message需要提前设置Message包含哪些类型的数据
- 把这个模块放到一个更复杂的系统里面的时候,要格外注意Message之间的数据兼容
Apollo ROS对ROS的改进
- 通信性能优化
- 原因
- 自动驾驶大量使用传感器引发很大的传输带宽需求
- 单路传感器消息有多个消费者时负载成倍增长
- 针对这一问题,Apollo ROS做了一个基于共享内存的通信机制减少数据的复制次数(减少了从用户到内核态以及从内核态到用户的两次数据拷贝),从而提升这种通信模式的效率
- 原因
- 消息通信延迟
- 传送一帧5M大小的数据,基于ROS Socket大概需要四毫秒左右的时间,基于共享内存通信只需要两毫秒左右
- 吞吐量
- 在吞吐量测试1:1情况下,整机性能可以达到5.5GB每秒的速度,如果是1:4,性能提升会更明显
- CPU资源占用率
- CPU资源占用率在共享内存通信情况下降低约30%, 主要是因为减少了多次内存复制