这是本文档旧的修订版!
ROS2机器人操作系统的DEY镜像定制
DEY是以Yocto的方式开发定制嵌入式Linux系统,这意味着除了添加Meta-Digi外,您也可以添加其它Yocto项目组的layer,包括在生产自动化和物流行业常用ROS机器人操作系统。在github中我们可以看到meta-ros在一直保持开发和演进状态。
Yocto 4.0 Kirkstone (LTS)对应支持ROS2 Humble (LTS)是个长期支持的版本,也是我们要集成的对象。官方文档位于:https://docs.ros.org/en/humble/。更确切地说,在嵌入式Yocto源代码层面安装的文档是: https://github.com/ros/meta-ros/wiki/OpenEmbedded-Build-Instructions
1. 预安装包查缺补漏 通常在安装DEY时,应该已经把大部分依赖的安装包都安装好了,但为了防止ROS需要一些额外的包,参考文档,再执行一下它的依赖包安装:
sudo apt update sudo apt install gawk wget git diffstat unzip gcc-multilib \ build-essential chrpath socat cpio python3-pip python3-pexpect \ xz-utils debianutils iputils-ping \ python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev xterm \ g++-multilib locales lsb-release python3-distutils time \ liblz4-tool zstd file sudo locale-gen en_US.utf8 #这条不一定要执行,因为本来就是用默认英文的
2.找出环境变量和配置文件备用 为了整合meta-ros到dey的镜象中,有两种办法,一种是用meta-ros中的镜像名来编译,另一种是参考dey-image-qt来创建dey-image-ros,并在镜像的recipe里加上关键包的支持。为了调查清楚,首先在一个全新的虚拟机上演练一下官方文档安装过程,并检查其配置文件。
mkdir ros2-test cd ros2-test mkdir conf ln -snf ../conf build/. 在build/files/下,有一系列的mcf文件,我们需要拷贝ros2-humble-kirkstone.mcf到配置文件下,可见这是控制编译的主本配置文件, cp build/files/ros2-humble-kirkstone conf/.
上面这个主要是为了研究配置文件,供以后碰到问题时参考,可以不做这第2步,先直接拉meta-ros到源码,请参考下面
3. DEY的镜像bb文件研读 主要的image配置文件在:dey4.0/sources/poky/meta/recipes-core/images和dey4.0/sources/meta-digi/meta-digi-dey/recipes-core/images 其中,core-image-base是在poky的基础镜像文件中添加一些包实现的,所以先研读core-image-base基础镜像,它继承自更基础的core-image(sources/poky/meta/classes/core-image.bbclass) 接下来将拉取meta-ros,并研读相关的bb文件。
4. 拉取meta-ros 下载meta-ros到dey的源码目录下
cd dey4.0/sources git clone https://github.com/ros/meta-ros.git
我们还需要把这个layer添加到conf/bblayer.conf中,在文件的加上这三句:
/home/robin/dey-aio/dey4.0/sources/meta-ros/meta-ros-common \ /home/robin/dey-aio/dey4.0/sources/meta-ros/meta-ros2 \ /home/robin/dey-aio/dey4.0/sources/meta-ros/meta-ros2-humble \
注意下载下来的目录中,meta-ros-common和meta-ros2-humble是我们需要的。如果要编译ros的镜像,在meta-ros-common中有image相关的recipe,其中: cat ros-image-core可以观察,要定义的东西:
require ${COREBASE}/meta/recipes-core/images/core-image-minimal.bb SUMMARY = "A small image just capable of starting core ROS." DESCRIPTION = "${SUMMARY}" inherit ros_distro_${ROS_DISTRO} inherit ${ROS_DISTRO_TYPE}_image IMAGE_INSTALL:append = " \ ros-core \ "
从上面可以看出,和core-image-base的bbappend类似,这个ros-image-core也是参考poky/meta/recipes-core/images的基础镜像core-image-minimal添加一些包。
core-image-base和core-image-minimal的差别在于:core-image-base使用meta/classes/core-image.bbclass中的IMAGE_INSTALL定义的包,而core-image-minimal则在bb文件里定义来覆盖原来core-image下的包,移除了packagegroup-base-extended,得到一个更小的镜像。所以,ros2的镜像,应该以core-image-base为基础才有意义。
5. 定制core-image-ros 我们给镜像取这个名字,是因为core-image-base能支持cc93的BSP,我们只需加入ros支持即可,这个镜像的bb文件可以放在meta-digi/meta-digi-dey下的recipe-core/images。先一步一步来,从基础的core-image-base中添加ros相关的支持。
首先测试一下没加layer前的效果,也就是bb文件在meta-custom是否能正常编译,将core-image-base.bbappend文件复制出来,重命名为core-image-ros.bb,并加上一句inherit core-image,整个过程如下
cd sources/meta-custom mkdir -p recipe-core/images nano core-image-ros.bb # # Copyright (C) 2016-2022 Digi International. # IMAGE_FEATURES += " \ dey-network \ eclipse-debug \ ssh-server-dropbear \ ${@bb.utils.contains('DISTRO_FEATURES', 'gstreamer', 'dey-gstreamer', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'alsa', 'dey-audio', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'bluetooth', 'dey-bluetooth', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'dey-wireless', '', d)} \ " # Remove graphical packages for non-graphical platforms IMAGE_FEATURES:remove = "${@oe.utils.conditional('IS_HEADLESS', 'true', ' splash ', '', d)}" CORE_IMAGE_BASE_INSTALL += "dey-examples-digiapix" # The connectcore demo was removed from 'packagegroup-dey-core' for the # 6UL (because of rootfs space limits). Add it here, to install it in the # non-graphical core-image-base. CORE_IMAGE_BASE_INSTALL:append:ccimx6ul = " connectcore-demo-example" # SDK features (for toolchains generated from an image with populate_sdk) SDKIMAGE_FEATURES ?= "dev-pkgs dbg-pkgs staticdev-pkgs" # Add our dey-image tweaks to the final image (like /etc/build info) inherit core-image inherit dey-image
可以成功编译,接下来就是修改这个bb文件,加入ros相关的包。
DESCRIPTION = "A Robot image with base-featured + ROS core Linux system functionality installed." LICENSE = "MIT" IMAGE_FEATURES += " \ dey-network \ eclipse-debug \ ssh-server-dropbear \ ${@bb.utils.contains('DISTRO_FEATURES', 'gstreamer', 'dey-gstreamer', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'alsa', 'dey-audio', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'bluetooth', 'dey-bluetooth', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'dey-wireless', '', d)} \ " # Remove graphical packages for non-graphical platforms IMAGE_FEATURES:remove = "${@oe.utils.conditional('IS_HEADLESS', 'true', ' splash ', '', d)}" CORE_IMAGE_BASE_INSTALL += "dey-examples-digiapix" # SDK features (for toolchains generated from an image with populate_sdk) SDKIMAGE_FEATURES ?= "dev-pkgs dbg-pkgs staticdev-pkgs" # Add our dey-image tweaks to the final image (like /etc/build info) inherit core-image inherit dey-image inherit ros_distro_${ROS_DISTRO} inherit ${ROS_DISTRO_TYPE}_image IMAGE_INSTALL:append = " \ ros-core \ "
新建一个项目myrobot, 编译首个core-image-ros,并排除错误。
bitbake core-image-ros
首先要排除的是,在ros的三个layer中,对yocto版本限制了,只需把conf/layer.conf中的这句LAYERSERIES_COMPAT_ros-common-layer = “nanbield”中nanbield改为kirkstone,即可。
继续编译,碰到一个错误:
ERROR: ParseError at /home/robin/dey-aio/dey4.0/sources/meta-ros/meta-ros2/recipes-devtools/python/python3-pydantic_2.5.3.bb:10: Could not inherit file classes/python_hatchling.bbclass ,而python3-pydantic_2.5.3.bb
看样子,在meta-digi-dey里放ros镜像的bb是不行的,要大改,试着把这个文件拷到meta-ros-common/recipes-core/images/下,改名为ros-image-dey, 再编译一下看看,
此时,碰到的错误是ParseError at /home/robin/dey-aio/dey4.0/sources/meta-ros/meta-ros-common/recipes-core/images/ros-image-dey.bb:29: Could not inherit file classes/ros_humble.bbclass
看来,应该是不能直接复制双方的recipe,而要有技巧。
根据文档: https://docs.ros.org/en/humble/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html ,还是用一个脚本来设置这变量
nano ros-env ROS_VERSION=2 ROS_PYTHON_VERSION=3 ROS_DISTRO=humble chmod +x ros-env source ros-env
再编译仍有错,检索https://github.com/ros/meta-ros/wiki/OpenEmbedded-Build-Instructions#add-meta-ros-to-an-existing-openembedded-project, 里面提到没有用mcf配置文件时的一些方法:
1. 在conf/bblayers.conf 设置ROS_DISTRO, 因此在这个文件中加上 ROS_DISTRO = “humble” , 此外也加上ROS_DISTRO_TYPE = “ros”
2. DISTRO ?= “${MCF_DISTRO}” 没用mcf时,用真实的DISTRO替掉这个变量
发现没有把mcf配置文件用起来,一个可能的方案是,把mcf放在 conf/下,另一种情况是合并到conf/local.conf中。
注意到最核心的文档是:https://github.com/ros/meta-ros/wiki/OpenEmbedded-Build-Instructions#add-meta-ros-to-an-existing-openembedded-project ,还有https://github.com/ros/meta-ros/tree/master:文档中的History其中提到:
The initial port of ROS 2 port was undertaken by Erle Robotics. Their work was shared at this repository and integrated upstream into meta-ros.
It has been converted to use recipes generated by superflore. Please see this wiki page for details of what was done and the current development milestones.
wiki地址就是
https://github.com/ros/meta-ros/wiki/Superflore-OE-Recipe-Generation-Scheme
应该是ros转用recipe的方法,
为了得到ros-core, 折衷一下,先把不用的bb注销掉, 即python那几个错误的bb,改为.bb-rm,不启用。
精简一下conf/local.conf ,此时可编译通过:
继续除错,主要还是devtool那个目录,应该是版本问题,考虑到不把cc93当成开发电脑,这些python都可以先禁掉
/home/robin/dey-aio/dey4.0/sources/poky/meta/recipes-devtools/python/python3-cryptography_36.0.2.bb
一个可能有用参考:https://community.nxp.com/t5/i-MX-Processors/I-MX8M-plus-AI-Robot-platform/m-p/1303809#M176520