ROS 2开发者指南
目录
这个页面定义了我们在开发ROS 2时采用的实践和策略。
一般原则
以下原则适用于所有ROS 2的开发:
共享所有权:每个参与ROS 2开发的人都应该对系统的所有部分有所所有感。代码的原始作者没有特殊的权限或义务来控制或维护该代码块。每个人都可以自由地在任何地方提出更改、处理任何类型的问题票和审核任何拉取请求。
愿意做任何工作:作为共享所有权的必然结果,每个人都应该愿意承担任何可用的任务,并为系统的任何方面做出贡献。
寻求帮助:如果在某个任务上遇到困难,请适当地通过工单、评论或电子邮件向你的开发同事寻求帮助。
质量实践
根据它们所遵循的开发实践,软件包可以根据不同的质量水平进行分类,根据《REP 2004:软件包质量分类指南 <https://www.ros.org/reps/rep-2004.html>》中的准则进行分类。这些分类根据版本管理、测试、文档编写等方面的策略进行区分。
以下部分是我们遵循的特定开发规则,以确保核心软件包具有最高质量(“一级”)。我们建议所有ROS开发人员努力遵守以下政策,以确保ROS生态系统的质量。
版本管理
我们将使用`语义化版本指南 <http://semver.org/>`__(semver
)进行版本管理。
我们还将遵守一些基于``semver``的ROS特定规则,这些规则是在``semver``完整意义上建立的。
不应该在已发布的ROS发行版中进行主要版本增加(即破坏性变更)
补丁(保持接口兼容)和次要(非破坏性)版本增加不会破坏兼容性,因此此类更改*允许*在发布中进行
主要ROS版本是发布破坏性变更的最佳时机。如果核心包需要多个破坏性变更,则应将它们合并到集成分支(例如rolling)中,以便快速在CI中发现问题,但同时发布以减少ROS用户的主要发布数量
尽管主要增量需要新的发行版,但新的发行版并不一定需要进行主要更新(如果开发和发布可以在不破坏API的情况下进行)
对于编译代码,ABI(应用二进制接口)被视为公共接口的一部分。任何需要重新编译依赖代码的更改都被视为主要更改(破坏性的)
ABI破坏性更改可以在次要版本升级之前(加入滚动发布)进行
尽管 Dashing 和 Eloquent 的主要版本组件为``0``,我们仍对核心包的API稳定性进行强制执行,尽管 SemVer 规范 中有关初始开发的规定
随后,软件包应努力达到成熟状态并增加到版本``1.0.0``以符合``semver``的规范
注意事项
这些规则是*尽力而为*的。在极端情况下,可能需要在一个主要版本/发布中打破API的兼容性。对于非计划中的兼容性断裂,是将主版本号还是次版本号增加将根据具体情况进行评估。
例如,考虑一个涉及发布的 X-turtle 和对应的主版本号为``1.0.0``的 Y-turtle 的情况。
如果在 X-turtle 中发现必须打破API兼容性的问题,显然不能选择升级到``2.0.0``,因为``2.0.0``已经存在。
在这种情况下处理X-turtle版本的解决方案,都是非理想的,包括:
增加X-turtle的次要版本:非理想,因为它违反了语义化版本规范(SemVer)中破坏性变更必须增加主要版本的原则。
将X-turtle的主要版本升级到超过Y-turtle(
3.0.0
):非理想,因为旧发行版的版本将会高于已有的新发行版版本,这将使得特定版本条件代码失效/破坏。
开发人员将需要决定使用哪种解决方案,或者更重要的是,他们愿意违背哪个原则。我们不能建议选用其中一种,但无论哪种情况,我们都要求采取明确的措施手动向用户传达中断情况及其解释(不仅仅是版本号的增加)。
如果没有 Y-turtle,即使修复只是一个补丁,X-turtle 也必须升级到 2.0.0
。这种情况符合 SemVer 规则,但违反了我们自己的规定,即在发布的分发版中不应引入主要增量。
这就是为什么我们将版本规则视为“尽力而为”。尽管上述例子不太可能出现,但准确定义我们的版本系统非常重要。
公共 API 声明
根据 semver
,每个软件包必须明确声明一个公共 API。我们将使用软件包的质量声明中的“公共 API 声明”部分来声明哪些符号是公共 API 的一部分。
对于大多数 C 和 C++ 包,声明是其安装的任何头文件。然而,定义一组被视为私有的符号也是可以接受的。在头文件中避免私有符号可以帮助实现 ABI 的稳定性,但并非必需。
对于其他语言如 Python,必须明确定义公共 API,以便清楚地知道哪些符号可以依赖于版本指南。公共 API 还可以扩展到构建工件,如配置变量、CMake 配置文件等,以及可执行文件、命令行选项和输出。包的文档应清楚地说明公共 API 的任何元素。如果你使用的内容在包的文档中没有明确列出作为公共 API 的一部分,那么你不能指望它在次要或修补版本之间不发生变化。
废弃策略
在可能的情况下,我们还将使用主要版本增量的滴答滴答废弃和迁移策略。新的废弃将在新的发行版中提出,伴随着编译器警告,表示该功能正在被废弃。在下一个发布中,该功能将被完全移除(不再有警告)。
示例函数 foo
已弃用,并被函数 bar
替代:
版本 |
API |
---|---|
X-turtle |
void foo(); |
Y-龟 |
[[已弃用("使用bar()")]] void foo(); <br> void bar(); |
Z-龟 |
void bar(); |
在发行版发布之后,我们不能添加废弃项。然而,废弃项不一定需要引发主要版本的升级。如果在发行版发布之前进行次要版本的升级,就可以引入废弃项(类似于破坏ABI的更改)。
例如,如果X-turtle作为``2.0.0``开始开发,可以在X-turtle发布之前的``2.1.0``中添加废弃项。
我们将尽可能在不同发行版之间保持兼容性。然而,与语义化版本控制(SemVer)相关的注意事项一样,特定情况下可能无法完全遵守打勾或废弃项。
变更控制流程
所有更改都必须通过拉取请求进行。
我们将在ROSCore仓库的拉取请求中执行`开发者证书 (DCO) <https://developercertificate.org/>`_ 的强制要求。
它要求所有提交消息都包含与提交作者相匹配的``Signed-off-by``行及其电子邮件地址。
您可以在``git commit``命令中添加``-s`` /
--signoff``参数或手动编写所需的消息(例如:``Signed-off-by: Your Name Developer <your.name@example.com>
)。只涉及空格删除、拼写错误更正和其他 微小更改 的拉取请求,不需要DCO。
对于每个拉取请求,始终在所有 一级支持平台 上运行CI作业,并在拉取请求中包含作业链接。(如果您无权访问Jenkins作业,将有人为您触发作业。)
需要至少来自未参与拉取请求撰写的其他开发人员的1个批准才能被视为已批准。在合并之前需要批准。
软件包可以选择增加此数字。
在合并相关更改之前,必须先提出对文档(API文档、功能文档、发布说明等)所需的任何更改。
文档
所有的软件包都应该在其README中包含或从其README中链接到以下文档元素:
描述和目的
公共API的定义和描述
示例
如何构建和安装(应该引用外部工具/工作流程)
如何构建和运行测试
如何构建文档
如何进行开发(对于描述诸如``python setup.py develop``之类的内容很有用)
许可证和版权声明
每个源文件必须有一个许可证和版权声明,通过自动化检查工具进行检查。
每个软件包必须有一个LICENSE文件,通常是Apache 2.0许可证,除非该软件包有现有的宽松许可证(例如,rviz使用三条款的BSD许可证)。
每个软件包应该对自身和其目的进行描述,尽量假设读者没有关于ROS或其他相关项目的先前知识而意外发现该软件包。
每个软件包应该定义和描述其公共API,以便用户可以合理地预期语义版本控制政策所覆盖的内容。即使在C和C++中,公共API可以通过API和ABI检查来强制执行,这也是一个很好的机会来描述代码的结构和每个部分的功能。
理应很容易通过任何软件包的文档了解如何构建、运行、构建并运行测试,并构建文档。显然,我们应该避免在常见工作流程中重复自己,比如在工作空间中构建软件包,但基本工作流程应该被描述或引用。
最后,它应该包含开发者的任何文档。这可能包括使用类似 python setup.py develop
的方法测试代码的工作流程,或者可能意味着描述如何利用软件包提供的扩展点。
示例:
功能:https://docs.ros.org/hydro/api/capabilities/html/
这个例子展示了描述公共API的文档
catkin_tools:https://catkin-tools.readthedocs.org/en/latest/development/extending_the_catkin_command.html
这是描述软件包扩展点的示例
(API文档尚未自动生成)
测试
所有的软件包都应该具备一定程度的 系统测试、集成测试和/或单元测试。
**单元测试**应该始终位于被测试的软件包中,并且应该使用诸如``Mock``之类的工具,尝试在构建的场景中测试代码库的狭窄部分。单元测试不应引入非测试工具的测试依赖,例如 gtest、nosestest、pytest、mock 等...
**集成测试**可以测试代码的各个部分之间或代码与系统之间的交互。它们通常以我们期望用户使用它们的方式测试软件接口。与单元测试类似,集成测试应该位于被测试的软件包中,除非绝对必要,否则不应引入非工具测试依赖,即所有非工具依赖都应在极端审查下才被允许,因此应尽量避免使用。
**系统测试**旨在测试软件包之间的端到端情况,并应位于它们自己的软件包中,以避免软件包膨胀或耦合以及避免循环依赖。
通常情况下,应尽量减少外部或跨包的测试依赖,以避免循环依赖和紧密耦合的测试包。
所有的包都应该有一些单元测试和可能的集成测试,但其数量取决于包的质量分类。以下小节适用于“Level 1”包:
代码覆盖率
我们将提供行覆盖率,并保证行覆盖率达到95%以上。如果有合理降低百分比目标的情况,必须明确记录。我们可以提供分支覆盖率,或者将某些代码排除在覆盖率之外(测试代码、调试代码等)。在合并更改之前,我们要求覆盖率要增加或保持不变,但在适当的理由下,可能会接受降低代码覆盖率的更改(例如,删除以前覆盖的代码可能会导致百分比下降)。
性能
我们强烈建议进行性能测试,但我们也认识到对于某些软件包来说,这并没有意义。如果有性能测试,我们将选择在每次更改或发布之前进行检查,或者两者都要进行。我们还需要对降低性能的更改或发布进行合并的理由。
代码检查器和静态分析
我们将使用:doc:ROS代码风格,并使用来自`ament_lint_common<https://github.com/ament/ament_lint/tree/humble/ament_lint_common/doc/index.rst>`_的代码检查器来强制执行。必须使用`ament_lint_common`的所有代码检查器和静态分析工具。
ament_lint_auto
文档提供了关于运行 ament_lint_common
的信息。
一般实践
一些实践适用于所有 ROS 2 开发。
这些实践不会影响软件包质量等级(如 REP 2004 中所述),但在开发过程中仍然强烈推荐。
问题
在提交问题时,请确保:
提供足够的信息让其他人能够理解问题。在ROS 2中,以下几点对于缩小问题原因范围非常有帮助。在每个类别中尽可能尝试多种替代方案将特别有帮助。
包含一系列重现问题的步骤。
如果遇到错误,请考虑提供一个`简短、自包含、正确(可编译)的示例 <http://sscce.org/>`__。如果其他人能够轻松地重现错误,问题更有可能被解决。
提及已尝试过的故障排除步骤,包括:
升级到最新版本的代码,该版本可能包含尚未发布的错误修复。参见`此部分 <building-from-source>`,并按照说明获取"rolling"分支。
尝试使用不同的RMW实现。请参考`此页面 <../../How-To-Guides/Working-with-multiple-RMW-implementations>`了解如何操作。
分支
注解
这只是一些指南。选择分支名称以匹配其自身工作流程是包维护者的责任。
在一个包的源代码库中,为其所针对的每个ROS发行版创建**单独的分支**是一种良好的做法。这些分支通常以它们所针对的发行版命名。例如,针对Humble发行版的开发可以创建一个名为``humble``的分支。
从这些分支中也可以发布版本,以适应相应的发行版。针对特定ROS发行版的开发可以在相应的分支上进行。例如:针对``foxy``的开发提交将被放到``foxy``分支,并且针对``foxy``的软件包发布将从同一分支进行。
注解
这需要软件包维护者根据需要执行回溯或向前移植,以保持所有分支与功能的同步。维护者还必须对所有仍然进行软件包发布的分支进行常规维护(修复错误等)。
例如,如果某个功能已合并到特定于Rolling的分支(例如``rolling``或``main``),并且该功能也适用于Humble发行版(不会破坏API等),那么将该功能回溯到Humble特定分支是一种良好的做法。
如果存在新功能或错误修复,则维护者可以为这些旧的发行版进行发布。
关于 main
和 rolling
呢?
main
通常目标为 Rolling <../../Releases/Release-Rolling-Ridley>`(即下一个尚未发布的ROS版本),但维护者可能决定从 ``rolling` 分支进行开发和发布。
拉取请求
一个拉取请求应该只关注一个更改。不同的更改应该放入不同的拉取请求中。参见 GitHub完美拉取请求指南。
补丁应该尽量保持最小的大小,并避免任何不必要的更改。
拉取请求必须包含最少数量的有意义的提交。
在拉取请求正在审核中时,您可以创建新的提交。
在合并拉取请求之前,所有的更改应该被压缩成少量的语义提交,以保持历史清晰。
在审核期间避免压缩提交记录。您的审阅人员可能不会注意到您所做的更改,从而引入混淆的可能性。而且,无论如何在合并之前都要进行压缩;提前压缩没有任何好处。
任何开发者都可以审核并批准拉取请求(请参阅 General Principles)。
当您正在处理尚未准备好审核或合并的更改时,请使用草稿拉取请求。当这些更改准备好进行审核时,将拉取请求从草稿状态移出。请注意,如果您想从草稿拉取请求中获得特定人员的早期反馈意见,可以在拉取请求的描述或评论中提及他们。
如果您的拉取请求依赖于其他拉取请求,请通过在拉取请求的描述顶部添加
- Depends on <link>
来链接到每个所依赖的拉取请求。这样做有助于审阅人员了解拉取请求的上下文。当您开始审查拉取请求时,请在拉取请求上发表评论,以便其他开发人员知道您正在进行审查。
拉取请求审查不是只读的,审查人员会发表评论,然后等待作者处理。作为审查人员,可以自由地进行一些小的改进(拼写错误、样式问题等)。作为拉取请求的发起人,如果您在一个分支上工作,请勾选`允许来自上游贡献者的编辑 <https://github.com/blog/2247-improving-collaboration-with-forks>`__ 选项,这将有助于前述情况。作为审查人员,也可以自由地进行一些较大的改进,但考虑将它们放在一个单独的分支中(在评论中提到新的分支,或者从新分支向原始分支发起另一个拉取请求)。
任何开发人员(作者、审查人员或其他人)都可以合并任何已批准的拉取请求。
库版本管理
我们将同时对一个包中的所有库进行版本控制。这意味着库的版本继承自该包。这样可以防止库和包的版本分歧,并与共享同一个代码仓库的包发布策略保持一致。如果您需要库具有不同的版本,请考虑将它们拆分为不同的包。
开发过程
默认分支(大多数情况下是滚动分支)必须始终构建,通过所有测试并且没有警告信息。如果出现任何回归问题,最重要的是至少恢复到先前的状态。
始终使用启用了测试的构建。
在对更改进行推送之前,始终在本地运行测试,并确保它们在拉取请求中正常工作。除了使用自动化测试外,还要手动运行修改后的代码路径,以确保补丁按预期工作。
对于每个拉取请求,始终运行适用于所有平台的CI作业,并在拉取请求中包含作业链接。
有关推荐的软件开发工作流程的更多详细信息,请参阅“软件开发生命周期”_部分。
RMW API的更改
当更新 RMW API 时,需要同时更新Tier 1中间件库的RMW实现。例如,RMW API 中引入了新函数 rmw_foo()
,必须在以下软件包中实现(截至ROS Galactic版本):
如果可行的话,也应考虑更新非一级中间件库(例如,根据更改的大小)。有关中间件库及其等级的列表,请参阅 REP-2000。
跟踪任务
为了帮助组织ROS 2的工作,核心ROS 2开发团队使用看板式 GitHub项目看板。
然而,并不是所有问题和拉取请求都在项目看板上跟踪。一个看板通常表示一个即将发布的版本或特定的项目。可以通过浏览 ROS 2存储库的个别问题页面 来浏览票证。
任何给定的ROS 2项目看板中的列名称和用途可能会有所不同,但通常遵循相同的一般结构:
待办事项:与项目相关的问题,可以分配处理
进行中:正在进行工作的活动拉取请求
审核中:工作已完成且准备好进行审核的拉取请求,以及目前正在进行主动审核的请求
完成:合并/关闭拉取请求和相关问题(仅供参考)
如果要请求更改权限,请在您感兴趣的工单上发表评论即可。根据复杂程度,描述您打算如何解决问题可能会很有用。我们将更新状态(如果您没有权限),然后您可以开始处理拉取请求。如果您经常做出贡献,我们可能会直接授予您管理标签等权限。
编程约定
防御式编程:确保尽早持有假设。例如,检查每个返回代码,并确保至少抛出异常,直到处理情况更加优雅为止。
所有错误消息必须指向
stderr
。在尽可能狭窄的范围内声明变量。
保持一组项目(依赖项、导入项、包含项等)按字母顺序排列。
特定于 C++。
避免直接将流 (
<<
) 输出到stdout
/stderr
,以防止多个线程之间的交错。避免使用引用来操作
std::shared_ptr
,因为这会破坏引用计数。如果原始实例超出作用域且引用正在使用中,它将访问已释放的内存。
文件系统布局
软件包和存储库的文件系统布局应遵循相同的约定,以便为浏览我们的源代码的用户提供一致的体验。
包布局
src
: 包含所有的 C 和 C++ 代码同时包含未安装的 C/C++ 头文件
include
: 包含所有已安装的 C 和 C++ 头文件<package name>
:对于所有已安装的 C 和 C++ 标头,它们应该由包名进行命名空间分隔
<package_name>
:包含所有 Python 代码test
:包含所有自动化测试和测试数据config
:包含配置文件,例如 YAML 参数文件和 RViz 配置文件doc
:包含所有的文档launch
:包含所有的启动文件package.xml
:根据`REP-0140 <https://www.ros.org/reps/rep-0140.html>`_定义的(可能会更新用于原型设计)CMakeLists.txt
:仅限使用 CMake 的 ROS 软件包setup.py
:仅适用于仅使用Python代码的ROS软件包README
:可以作为项目的首页在GitHub上显示这可以是简短或详细的,但至少应该链接到项目文档
考虑在此README中添加CI或代码覆盖率标签
它也可以是
.rst
或任何 GitHub 支持的格式
CONTRIBUTING
:描述贡献准则这可能涉及许可证的含义,例如使用 Apache 2 许可证时
LICENSE
:此软件包的许可证副本或许可证CHANGELOG.rst
:REP-0132 兼容的变更日志
存储库布局
每个软件包应该位于与软件包同名的子文件夹中。如果一个存储库只包含一个软件包,它可以选择位于存储库的根目录中。
上游软件包
Debian和Ubuntu上游的软件包
感谢Jochen Sprickerhof和Leopold Palomo-Avellaneda的辛勤努力,一些`ROS 2软件包现在可以从Debian和Ubuntu的主要存储库中获取<https://wiki.debian.org/DebianScience/Robotics/ROS2/Packages>`_。`这里有Jochen在ROSCon 2015上的简要概述<https://vimeo.com/142151399#t=29m15s>`_。原始的ROS软件包已经根据Debian的准则进行了修改,包括将软件包拆分为多个部分,在某些情况下更改名称,根据FHS准则安装到/usr,并在共享库上使用soversions。
此外,一些引导依赖项,如命令行工具如``vcstool``和``colcon``以及一些库如``osrf-pycommon``和``ament``也被上游打包。
与来自http://packages.ros.org的OSRF提供的ROS软件包不同,上游存储库中的软件包没有附加到特定的:doc:ROS分发版。相反,它们代表了时间上的快照,将定期在Debian不稳定版本中更新,然后在不同的Debian和Ubuntu发行版中的各个时间点被锁定。
不要混合使用
我们强烈建议不要在同一系统上混合使用来自上游Debian/Ubuntu和来自http://packages.ros.org的ROS软件包。在某些情况下,这样的混合系统可能会正常工作,但两组软件包之间可能会产生负面互动。我们正在与Jochen和他的朋友合作,通过文档和软件包冲突规范来最小化问题的可能性,但我们预计一些风险仍然存在,包括一些相当微妙的问题。
因此,我们建议您选择要么从上游安装软件包,要么从http://packages.ros.org安装,但不要同时两者兼而有之。不仅不应该同时安装来自两者的软件包,而且如果您打算使用上游软件包,那么您甚至不应该在apt源中具有http://packages.ros.org条目(即在``/etc/apt/sources*``中的任何文件中)。同时启用两者可能会导致两个来源之间名称重叠的软件包混合,例如``python3-rospkg``。
开发者工作流程
我们使用 GitHub项目面板 来跟踪与即将发布的版本和较大项目相关的未解决问题和活动中的PR。
通常的工作流程是:
讨论设计(在适当的存储库上的GitHub票证,并在需要时在 https://github.com/ros2/design 上创建设计PR)
在一个分支上的特性分支上编写实现
请查看 开发人员指南 以获取指导方针和最佳实践
编写测试
启用并运行代码检查工具
一旦本地构建没有警告并且所有测试都通过,请在你的功能分支上运行CI:
访问 ci.ros2.org
登录(右上角)
点击
ci_launcher
作业点击"使用参数构建"(左列)
在第一个框中输入"CI_BRANCH_TO_TEST",输入您的特性分支名称
点击
build
按钮
(如果您不是ROS 2的贡献者,您无法访问CI工作区。在这种情况下,请联系您的PR审查者为您运行CI)
如果您的使用场景需要运行代码覆盖率:
如果 CI 作业在没有警告、错误和测试失败的情况下构建成功,请在您的 PR 或汇总所有 PR 的高级票证上发布您作业的链接(参见示例 here)
请注意,这些徽章的 Markdown 代码位于“ci_launcher”作业的控制台输出中
当 PR 被批准后:
提交 PR 的人使用“Squash and Merge”选项将其合并,以便保持干净的历史记录
如果这些提交应该保持分开:将所有的 nitpick/linters/typo 提交合并在一起,然后合并剩余的提交集合
注意:每个 PR 应该针对一个具体的功能,因此大部分情况下 Squash and Merge 是有意义的
合并后删除该分支
架构开发实践
本节描述了在对ROS 2进行重大架构更改时应采用的理想生命周期。
软件开发生命周期
本节逐步描述了如何规划、设计和实现一个新功能:
任务创建
创建设计文档
设计评审
实现
代码评审
任务创建
需要对ROS 2关键部分进行更改的任务应在发布周期的早期阶段进行设计审查。如果设计审查在后期阶段进行,则更改将成为未来发布的一部分。
编写设计文档
设计文档不得包含机密信息。是否需要为您的更改编写设计文档取决于任务的大小。
您正在进行小的更改或修复错误:
不需要设计文档,但应在适当的存储库中打开一个问题来跟踪工作并避免重复努力。
您正在实施新功能或希望为OSRF拥有的基础架构(如Jenkins CI)做贡献:
需要设计文档,并应贡献给 ros2/design,以便在 https://design.ros2.org/ 上访问。
您应该fork存储库并提交拉取请求,详细说明设计。
在拉取请求或提交消息中提及相关的ros2问题(例如,
任务ros2/ros2#<问题编号>的设计文档
)。详细说明可在`ROS 2 Contribute <https://design.ros2.org/contribute.html>`__页面找到。设计评论将直接在拉取请求上进行。
如果任务计划在特定版本的ROS中发布,应在拉取请求中包含这些信息。
设计文档审查
一旦设计准备好进行审查,应打开拉取请求并指定适当的审阅者。建议将项目所有者(即所有受影响软件包的维护者,根据``package.xml``维护者字段定义,参见`REP-140 <https://www.ros.org/reps/rep-0140.html#maintainer-multiple-but-at-least-one>`__)作为审阅者。
如果设计文档很复杂或者审阅人员的日程安排有冲突,可以设置一个可选的设计审查会议。在这种情况下,
会议之前
至少提前一周发送会议邀请
建议会议持续一个小时
会议邀请应列出审查期间需要做出的所有决策(需要包维护者批准的决策)
- 会议要求出席人员:设计拉取请求的审查人员
会议可选出席人员:所有OSRF工程师,如果适用的话
在会议期间
任务负责人主导会议,提出他们的想法,并管理讨论,以确保在规定时间内达成一致意见
会议之后
任务负责人应该向所有与会者发送会议纪要
如果有关设计的小问题被提出:
任务所有者应根据反馈意见更新设计文档的拉取请求
不需要额外的审查
如果有关设计方面的重大问题被提出:
可以删除没有明确一致意见的部分,这是可以接受的
设计中有争议的部分可以在未来作为一个独立任务重新提交
如果无法移除有争议的部分,直接与包的所有者合作以达成一致
一旦达成共识:
确保已合并`ros2/design <https://github.com/ros2/design/>`__的拉取请求(如果适用)
更新并关闭与此设计任务相关的 GitHub 问题
实现
开始之前,请参阅 Pull requests 部分以了解最佳实践。
对于每个需要修改的存储库:
修改代码,完成后或定期备份工作,然后进入下一步。
使用``git add -i``进行自我审查,并将更改添加到暂存区。
使用``git commit -s``创建一个新的带有签名的提交。
构建农场介绍
构建农场位于 ci.ros2.org。
每晚我们运行夜间任务,对各种场景和平台进行构建和运行所有测试。此外,在合并之前,我们还会将所有拉取请求与这些平台进行测试。
这是当前的目标平台和架构设置,尽管它会随时间变化而发展:
Ubuntu 22.04 Jammy
amd64
aarch64
Windows 10
amd64
构建农场上有几类工作:
手动工作(由开发人员手动触发):
ci_linux:在Ubuntu Xenial上构建+测试代码
ci_linux-aarch64:在ARM 64位机器(aarch64)上的Ubuntu Xenial上构建+测试代码
ci_linux_coverage:构建 + 测试 + 生成测试覆盖率
ci_windows:在 Windows 10 上构建 + 测试代码
ci_launcher:触发上述所有作业
每晚运行的夜间任务:
调试:使用CMAKE_BUILD_TYPE=Debug构建和测试代码
每夜构建(Linux平台,调试模式)
每夜构建(Linux平台,aarch64架构,调试模式)
每夜构建(Windows平台,调试模式)
发布:使用CMAKE_BUILD_TYPE=Release构建和测试代码
每夜构建:Linux平台 Release 版本
每夜构建:Linux(aarch64架构)平台 Release 版本
每夜构建:Windows平台 Release 版本
重复执行:构建,然后运行每个测试最多20次或直到失败(也称为稳定性测试)
每夜Linux重复执行
每夜Linux-aarch64重复执行
每夜Windows重复执行
覆盖率:
nightly_linux_coverage:构建 + 测试代码 + 分析 C/C++ 和 Python 的覆盖率
结果以 Cobertura 报告的形式导出
打包(每晚运行;结果打包成一个归档文件):
通过提供源码和二进制包的构建、持续集成、测试和分析,另外两个构建农场支持 ROS / ROS 2 生态系统。
有关详细信息、常见问题和故障排除,请参阅:构建农场。
覆盖率运行注意事项
ROS 2软件包的组织方式是,给定软件包的测试代码不仅包含在该软件包内,还可以存在于其他软件包中。换句话说,在测试阶段,软件包可以执行属于其他软件包的代码。
为了达到ROS 2核心软件包中所有可用代码的覆盖率,建议使用一组固定的建议存储库运行构建。该集合在Jenkins中的覆盖率作业的默认参数中定义。
如何从构建工厂报告中读取覆盖率
查看给定包的覆盖率报告:
当``ci_linux_coverage``构建完成后,点击``Coverage Report``
向下滚动到``Coverage Breakdown by Package``表格
在表格中,查看名为"Name"的第一列
构建工厂中的覆盖率报告包括在ROS工作空间中使用的所有软件包。覆盖率报告包括与同一软件包对应的不同路径:
以以下形式的名称条目:
src.*.<repository_name>.<package_name>.*
。这些对应于针对软件包自身源代码的单元测试运行以以下形式的名称条目:
build.<repository_name>.<package_name>.*
。这些对应于针对构建或配置时生成的文件的软件包的单元测试运行以以下形式的名称条目:
install.<package_name>.*
。这些对应于来自其他软件包的测试运行的系统/集成测试
如何从构建农场报告中计算覆盖率
使用自动脚本获取组合单元覆盖率:
从ci_linux_coverage Jenkins构建中复制构建的URL
下载 get_coverage_ros2_pkg 脚本
执行脚本:``./get_coverage_ros2_pkg.py <jenkins_build_url> <ros2_package_name>``(README)
从脚本输出的"Combined unit testing"最后一行中获取结果
替代方法:从覆盖率报告中获取组合单元覆盖率(需要手动计算):
当ci_linux_coverage构建完成后,点击``Cobertura Coverage Report``
向下滚动到``Coverage Breakdown by Package``表格
在表格中,查找第一列“Name”下的内容(其中<package_name>是您正在测试的软件包):
在模式“src.*.<repository_name>.<package_name>.*”下的所有目录中,获取列“Lines”中的两个绝对值。
在模式“build/.<repository_name>.*”下的所有目录中,获取列“Lines”中的两个绝对值。
使用上述选择:对于每个单元格,第一个值是测试的行数,第二个值是代码总行数。汇总所有行以获得测试的行数总和和正在测试的代码行数总和。进行除法运算以获取覆盖率。
如何使用 lcov(Ubuntu)在本地测量覆盖率
要在自己的机器上测量覆盖率,请安装``lcov``。
sudo apt install -y lcov
本节的其余部分假设您正在使用自己的 colcon 工作空间。使用覆盖率标志进行调试编译。可以使用 colcon 标志来针对特定的软件包。
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} --coverage" -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} --coverage"
lcov
需要一个初始基准,您可以使用以下命令生成。根据您的需要更新输出文件位置。
lcov --no-external --capture --initial --directory . --output-file ~/ros2_base.info
运行测试以获得与覆盖率测量相关的软件包。例如,如果同时测量``rclcpp``和``test_rclcpp``
colcon test --packages-select rclcpp test_rclcpp
使用类似的命令捕获 lcov 结果,但这次不使用``--initial``标志。
lcov --no-external --capture --directory . --output-file ~/ros2.info
合并追踪的 .info 文件:
lcov --add-tracefile ~/ros2_base.info --add-tracefile ~/ros2.info --output-file ~/ros2_coverage.info
生成 HTML,以便轻松可视化和标注覆盖的代码行。
mkdir -p coverage
genhtml ~/ros2_coverage.info --output-directory coverage