赞
踩
Open Robotics为多个平台提供了预构建的ROS 2包,但许多开发人员仍需要依赖交叉编译1,原因如下:
交叉编译简单软件(例如,不依赖外部库的软件),只需要使用交叉编译器工具链替代本地工具链即可。
交叉编译的复杂性往往由以下因素带来:
ROS 2交叉编译工具由Open Robotics和ROS Tooling Working Group所共有。
它是一个Python脚本,使用docker容器中的模拟器为受支持的目标架构编译ROS 2源文件。
该工具的详细设计可在ROS 2 design2中找到。 使用该工具的说明在cross_compile包中。
如果您使用的是旧版本,请遵循交叉编译指南。
接下来我们看一下设置和管理用于交叉编译的sysroot环境的ROS 2工具的方案。
本方案的目标是简单和可扩展。
我们可以使用colcon mixins扩展支持新的交叉编译配置。
ROS的交叉编译指南和esteve/ros2_raspbian_tools库中说明了如何使用CMake和Docker镜像的工具链将ROS 2交叉编译未受官方支持的架构,如ARM64和ARM-HF。
esteve/ros2_objc和esteve/ros2_java也提供对Android和iOS等其他平台的支持。
理想情况下,我们应该能够通过单个命令来交叉编译用于ROS 2的ROS包。该命令还应该具备良好的可扩展性以便于支持新平台。该设计方案是对ARM-HF和ARM64架构的一级支持的推动。
我们将继续使用交叉编译教程的一般方法。这涉及到为目标平台构建一个sysroot,使用QEMU和Docker,然后在colcon mixins中使用C和C++交叉编译器进行编译。
我们将在交叉编译教程中添加一组命令来进行二次封装。这些命令将为目标平台使用一个新的workspace目录,并基于以下关键字确定:
我们称此工作区目录称为cc-root。平台意味着体系结构,但是像generic_armhf
这样的通用平台也属于此语境范畴。平台标识符的例子如:generic_armhf-ubuntu_bionic-fastrtps-crystal
或turtlebot_armhf-ubuntu_bionic-fastrtps-dashing
。我们将添加以下命令:
create-cc-sysroot
命令,将使用Docker为目标平台生成sysroot,并将其存储在cc-root的sysroot子目录中。这个命令将接受参数来指定目标平台,例如:create-cc-sysroot --arch generic_armhf --os ubuntu_bionic \
--rmw fastrtps --rosdistro crystal
create-cc-sysroot
生成的sysroot的选项,使用相同的路径约定。performance_test
包。这将在cc-root generic_armhf-ubuntu_bionic-fastrtps-crystal
的build
、install
和log
子目录下交叉编译生成相应的二进制文件。colcon build --mixin cc-generic_armhf-ubuntu_bionic-fastrtps-crystal \
--packages-up-to performance_test # any other other `colcon build` arguments
cc-build
命令,确保使用create-cc-sysroot
创建了sysroot,然后在Docker容器中启动交叉编译相应的Docker镜像。create-cc-sysroot
命令将暗自执行以下操作:
COPY
以将工作区的内容获取到容器中。rosdep
确保workspace的系统依赖项没有丢失。注意,由于使用了QEMU,我们可以在Docker中为ARM-HF架构运行rosdep
。sysroot
子目录中。CMAKE_TOOLCHAIN_FILE
参数指向工具链文件(例如generic_linux.cmake),从而为交叉编译设置适当的CMake参数。ROS 2基本镜像是使用Docker官方镜像的ros2/cross_compile中的sysroot/Dockerfile_ubuntu_arm的变体。
OSRF将发布带有预构建ROS 2的基本ROS 2镜像,这用于交叉编译用户包。
OSRF还将发布其他基本ROS 2镜像,并预装用于构建ROS 2的系统设置和基本工具,这些工具应该用于从源构建ROS 2。
create-cc-sysroot
命令也支持以下可选参数:
--sysroot-base-image
:指定一个Docker镜像作为依赖于工作空间的sysroot镜像的基础镜像。所指定的参数可作为docker image pull
的有效参数,并在FROM
Dockerfile 语句中使用。如果没有指定,该命令将从目标平台推断--sysroot-base-image
的值,并从Docker的官方ROS镜像、arm64v8 Dockerhub repo或arm32v7 Dockerhub repo上发布的镜像中进行拉取。--sysroot-image
:指定工作空间的sysroot的Docker镜像。构建将从该镜像中导出sysroot,而不是从工作区创建sysroot镜像。开发者需自行保证workspace的包所需的所有依赖项都被包含在镜像中。--use-base-image-sysroot
: Boolean标志,当为true时,将使用base ROS 2 Docker镜像构建sysroot,此时工作区包中声明的依赖项将被忽略。在没有额外依赖的情况下,该选项可以加速包的构建。通过创建相应的ROS 2 Docker镜像以及工具链文件的变体,我们可以添加对其他平台的支持。我们在Ubuntu Bionic的ROS 2 crystal和fastrtps版本上,首次添加了对ARM-HF和ARM64的通用版本的支持。
打包生成的二进制文件不在本文档的描述范围内。
满足以下条件后,交叉编译的二进制文件将在cc-root的工作区中可用(如generic_armhf-ubuntu_bionic-fastrtps-crystal
):
src
在内的整个工作区复制到远程设备rosdep
以在运行二进制文件前安装ROS相关依赖项。为了支持新平台的交叉编译,我们需要:
rosdep install
获取ROS 2源代码所需的依赖项。如果该平台存在预构建的二进制文件,我们也可以从二进制文件中获取依赖项。cross-compile
库添加新平台的colcon mixin,并根据工具链文件进行相应的修改。我们可以通过如下方法测试新平台的交叉编译支持情况:
create-cc-sysroot
为一些参考包(例如ApexAI/performance_test)构建一个自定义的sysroot映像,并将其文件系统导出至sysroot中。colcon test
。该容器将与工作区的bind mount一起启动,这样它们就可以访问已编译的二进制文件。为了简化针对新架构-操作系统组合的基础ROS 2 Docker镜像的开发,在未来的迭代中,我们可能会添加一个新的命令build-sysroot-base-image
,功能如下:
与该命令兼容的Dockerfiles将保留在ros2/cross_compile
中。如果需要,我们可以在CI/CD管道中使用它们。
本方案带来了简便的开发体验,其中:
cc-build
命令触发binfmt_misc
方式使用QEMU的Docker映像上执行rosdep install
的方式来扩展基本的sysroot应用。这个方案主要解决的是基于Linux平台的交叉编译。由于我们无法使用Apt安装Visual Studio编译器,因此我们也无法在Windows上进行交叉编译。
所以,在Windows或Mac开发环境上,我们只能通过在容器的方式运行本工具。当然,受限于虚拟化层,性能多少会有所下降。
我们应该为每个平台确定一个构建和发布基本ROS 2 Docker映像的过程。 理想情况下,为master发布从源代码构建的镜像应该是无感的,但根据可用资源的不同,这可能很难实现的。
可以使用colcon bundle插件将ROS工作区及其所有依赖打包成一个tarball。通过启动目标平台的Docker容器,构建并打包工作空间,并导出bundle,可以将其部署到目标硬件,从而交叉编译ROS 2的工作空间。 这种方法的主要缺点是在Docker映像中使用默认的ARM编译器会显著降低编译速度,这可能会给日常开发带来负担。通过安装qemu-user-static
,我们安装了QEMU二进制文件来模拟ARM32/64处理器,而且还在本地机器中注册了binfmt_misc
的钩子。这意味着每次程序启动时,如果是它希望运行在QEMU支持的平台上,则二进制文件将自动通过QEMU运行。实际上,它允许您在X86实例上直接运行ARM二进制文件,这个工作是在构建基本镜像时通过Docker隐式完成的。由于QEMU模拟器比正常的执行慢10倍以上,通过此方案我们将QEMU的使用限制在构建基本镜像阶段,在其余时间在本机上使用用于目标平台的交叉编译器。
colcon bundle方法需要在colcon bundle中添加对ROS 2的支持,而后者目前不支持Ament。 这将提供一种分发交叉编译的系统依赖项的方法,由于rosdep install
在资源受限的硬件上会花费很多时间,并且需要Internet连接,因此本方法提供了极大的便利性。 目前的方案和colcon bundle是互补方案,若colcon bundle最终支持ROS 2,我们就可以使用cc-build
轻松地完成交叉编译,最小化Docker的使用,然后使用colcon bundle
来生成可部署的工件。
对于依赖于工作空间的sysroot映像,我们可以通过不构建工作空间的sysroot映像来避免该工作空间的Docker COPY
,我们只需为基础ROS 2镜像启动一个容器,并bind mount该工作空间。 容器的入口点将在挂载工作空间的目录上启动rosdep
,然后我们就可以通过docker container export
导出容器的文件系统。这避免了COPY
,但缺点是我们的工作空间就不会有sysroot映像,而且每次启动容器时都必须在该镜像的入口点上运行rosdep
。该镜像对于运行测试非常有用,而最终的cc-test
命令可以进一步简化使用该镜像的操作。
最后,与交叉编译教程中的原始方案相比,本方案基本上在cross_compile/entry_point.sh中对上述教程所使用的命令进行了重新组织,这样就可以用简单的一行命令对工作区进行交叉编译工作区。 因此,本方案是上述教程的演进。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。