大家好,我是今天的翻译官小鱼。今天给大家带来一篇文章,详细描述了ROS2相对ROS1做出了哪些改变?看完之后,小鱼自感收获颇深,希望大家也能有所收获。
ROS1只在ubuntu进行 CI 测试。但ROS社区的中也做了对其他linux发行版的支持。
ROS2目前正在 Ubuntu Xenial、OS X El Capitan以及 Windows10上进行 CI 测试和支持(见ci.ros2.org)
ROS1 的核心是瞄准 C++03,并且在其 API 中不使用C++11 功能。ROS 2 广泛使用C++11,并部分使用C++14。将来,ROS2 可能会开始使用C++17,只要C++17在所有主要平台上都得到支持。
ROS1 的目标版本是 Python2 。ROS2 至少需要 Python 版本 3.5 。
ROS1 使用自定义序列化格式、自定义传输协议以及自定义中央发现机制。
ROS2 具有抽象的中间件接口,通过该接口提供序列化、传输和发现。目前,此接口的所有实现都基于 DDS 标准。这使得 ROS 2 能够提供各种优质的Qos服务策略,从而改善不同网络的通信。
有关编译系统的更多信息,请参阅ament 文章。
每个ROS包其实都是一个Cmake项目。在ROS 2中,支持其他编译系统。目前已经支持了Python包,这个小鱼在动手学ROS2教程里也有说明。
在 ROS1中, 只用到了一小部分setup.py
的功能。因为 setup.py
文件正在通过 CMake进行处理的。
在 ROS 2 中,Python类型的功能包可以使用 setup.py
的所有功能,例如输入点。可以使用python3 setup.py install
进行安装
在 ROS1 中,编译工具生成必须来自脚本,以便在能够在build功能包之前设置环境。(此方法仅在使用 ROS 特定编译工具编译 ROS 封装时才有效。)
在 ROS 2 中,环境设置被分为功能包脚本和工作目录脚本。每个包都提供必要的脚本,使其在build之后可以运行。编译工具仅调用工作目录特定脚本,然后调用功能包包特定脚本。
在 ROS1 中,多个包可以使用同一个CMake编译。虽然加快了编译速度,但每个包都需要确保正确定义交叉包目标依赖性。此外,所有包都共享相同的名称目录,从而会导致目标名称碰撞等。
在ROS2中,仅支持孤立的编译,即每个包都是单独编译的。安装目录可以独立或合并。
在 ROS1 中,编译完一个包是不需要安装到install目录的。将源码和devel目录相结合使用。但是每个包都必须支持devel目录才行。
在 ROS 2 中,在编译功能包后必须安装功能包才能使用。
ROS1之所以有devel目录是方便开发人员能够修改文件,比如Pythn代码和launch文件,想让用户修改完代码后不用编译就能使得修改生效。在ros2中使用symlinks替代了这个功能,这点小鱼在《动手学ROS2》教程里也有讲。
在 ROS1 中,catkin_simple的功能使编写ROS功能包的 CMake代码更加容易。在大多数哦况下,根本一点都不容易,怪谁呢?就怪一些设计限制,比如上面取消的devel目录的支持。
在ROS2 中,对CMake API 进行了重构,以支持此catkin的使用。
在 ROS1 中,编译系统会考虑仅具有manifest文件的包。在 ROS 2 中,无需显式文件即可在文件夹中检测带有支持编译系统的软件包。如果包遵循常见做法,甚至有可能检测到一些缺失的元信息(如依赖性)。
在 ROS1 中,.msg和 .srv 文件可以具有相同的名称,但生成的代码会发生碰撞。服务的请求和响应部分也是如此。
在 ROS 2 中,生成的代码使用单独的命名目录来保证它无碰撞。
生成的 Python 消息和服务代码当前使用 ROS1 和 ROS 2 中的相同模块和类名。因此,它们不能在一个应用程序中同时导入。
在 ROS 2 中,消息中的原始值现在可以具有默认值,当消息编译时设置。但非原始字段(即array of strings)的默认值尚不可行
这个设计太棒了,小鱼给点个赞。从设计上考虑,这是必要的,以便计算内存中消息的最大大小,从而允许预分配具有动态大小的消息。对于性能和实时使用案例非常有用。
在 ROS1 中,客户端库中定义了duration和time的类型。数据结构的成员名称在C++(sec, nsec)和 Python (secs, nsecs)中有所不同。
在 ROS 2 中,这些类型被定义为消息,因此跨语言一致。
该字段已弃用很长时间,在ROS1中大家基本上都不赋值的,小鱼没猜错的吧。
目前 ROS 2 不支持Topic名称中的命名目录。这主要是由于 DDS Topic名称中有字符的限制。设计文档描述了将来应如何添加此内容。
在 ROS1 中,有关 ROS graph 的所有信息必须从Master节点获取。在 ROS 2 中使用广播的方式取代,例如,某个参数发生了改变,则会发出通知。
在 ROS1 中,每个节点通常都有其自己的功能。在ROS2中,建议将具有相同生命周期的组件中分到一组。
生命周期可用于像 roslaunch 这样的能够确定由哪些组件组成的系统工具
在 ROS1 中,全局参数和节点特定动态配置参数是两个独立的概念。
在 ROS2中,正在使用统一的方法。它类似于动态配置,名为"全局参数服务"的节点将接受无条件设置值的请求。在 ROS1中需要对所有参数进行轮询,如果发生改变就发布出去,但ROS2中只要发生改变就可以通知其他节点。
ROS2关于Action的部分,官方说还没有,其实已经实现了,这里小鱼就先留个缺口,后面单独拎出来讲。
在 ROS1 中,开发人员只能在单线程执行或多线程执行之间进行选择。在 ROS2中,C++(例如跨多个节点)中提供了更精细的执行模型,自定义执行器可以轻松实现。对于Python的执行模块也有实现,这里小鱼也需要好好介绍,官方文档有点更新慢了。
在 ROS1 节点中,Topic只能在启动时重新映射remap。在ROS2中,可以在运行时进行话题的重映射和别名。
在 ROS1 节点名称中,名称是独一无二的,当开始使用同名的新节点时,通过关闭现有节点来强制执行此名称。在 ROS 2 中节点名称可以在运行时指定。
实时支持
ROS1 不支持编写实时代码,需要依赖于外部框架,如 Orocos。在 ROS2中,使用适当的 RTOS 编写实时节点。
节点 vs. 节点
在 ROS1 中,API 用于节点和节点的方案不同,需要开发人员决定在编程时间对节点的映射以进行处理。在 ROS 2 中,建议将每个组件编译到共享库中,然后可以单独加载或与其他组件(如 ROS1 节点)共享相同的过程。这有助于在部署时间选择流程布局。
在 ROS1 中,不可能在过程中创建多个节点。这是由于 API 本身,但也因为内部的逻辑所决定的。但在ROS2中,可以在过程中创建多个节点。(小鱼亲测可用,点赞)
在 ROS1 ros 启动文件中,XML 的定义功能非常有限。在 ROS2 launch文件中,使用 Python 编写,从而能够使用更复杂的逻辑(如条件等)
在 ROS1 中,通过根据ROS_PACKAGE_PATH定义在文件系统中查找各种资源(功能包、消息、插件等)。当ROS_PACKAGE_PATH很大且缓存产生不一致状态时,这可能导致性能不佳。
在 ROS 2 中,资源可以在编译时间在索引上注册,然后在运行时高效查询。
ROS1 重建所有依赖包,因为它假设 ABI 不兼容。为了避免这种重大开销,ROS2 包应能够声明其 ABI,以避免尽可能重构依赖包。
ROS1 只能从 Windows 上的源编译(它也仅适用于几个 ROS 包且不支持)。ROS 2 将提供基于Chocolatey的二进制包。
ROS2相对ROS1的确做了不少改变。我是小鱼,更多ROS2学习资料,欢迎大家关注公众号《鱼香ROS》。