这是本文档旧的修订版!


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为基础才有意义。

从网络找到的一些参考: https://gitee.com/zxd2021-imx/meta-robot-platform/blob/Hardknott-5.10/imx/meta-robot/recipes-core/images/imx-robot-core.bb

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

再编译

.

.

. .

.

.

以下无用

ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_DISTRO=humble

接下来的方向是:

1. 尝试编译core-image-minimal
2. 添加相关digi包

比较core-image-minimal和core-image-base的差异,如果不大,则
1.ros-image-core改为以core-image-base为基础的镜像, (可能这个方向更好一些,东西更多),

正在进行的任务: 1. 编译一下core-image-minial ,并在cc93上跑起来,看看有哪些东西

*以下无用待参考后删除, 相关配置文件中的一些敲定可能有需要

待参考

待删除 。。

。。

。。

********************************

# Clone the OpenEmbedded metadata layers and generate conf/bblayers.conf .
build/scripts/mcf -f conf/$cfg

# Set up the shell environment for this build and create a conf/local.conf . We expect all of the variables below to be unset.
unset BDIR BITBAKEDIR BUILDDIR OECORELAYERCONF OECORELOCALCONF OECORENOTESCONF OEROOT TEMPLATECONF
source openembedded-core/oe-init-build-env

# The current directory is now the build directory; return to the original.
cd -

# An OpenEmbedded build produces a number of types of build artifacts, some of which can be shared between builds for
# different OpenEmbedded DISTRO-s and ROS distros. Create a common artifacts directory on the separate disk under which all
# the build artifacts will be placed. The edits to conf/local.conf done below will set TMPDIR to be a subdirectory of it.
mkdir -p "<ABSOLUTE-PATH-TO-DIRECTORY-ON-SEPARATE-DISK>"

====以下待删除 —

ROS官网上,可以看到,当前推荐的长期支持版本是:ROS Kinetic Kame ,该版本在github上有一个适用于yocto方式的验证性版本

meta-ros提供了两个镜像参考,分别是最小的core-image-ros-roscore以及扩展的core-image-ros-world
检查这两个bb文件,core-image-ros-world集成有packagegroup-ros-world,这个bb文件在https://github.com/bulwahn/meta-ros/blob/kinetic-experimental-v3-alpha1/recipes-ros/packagegroups/packagegroup-ros-world.bb 可以发现,这个镜像带有canopen等众多应用层的包,不过这个镜像模板并不是以dey为基础的,为了能在dey里面用,应该把相关的包编译进dey中,甚至在熟练后可以做一个dey-image-ros的镜像bb文件来打包编译所需的镜像

要把第三方的layer添加到项目中,请按下面这个方式操作:

1、 cd /usr/local/dey-2.4-r1/sources/meta-openembedded
2、 git clone https://github.com/bulwahn/meta-ros -b kinetic-experimental-v3-alpha1

3. 在项目文件夹中conf/bblayers.conf,把meta-ros添加到bblayers.conf
4. 查一下相关的包:bitbake-layers show-recipes |grep ros
现在可以编译指定包甚至是roscore镜像
5. bitbake core-image-ros-roscore  或者 bitbake core-image-ros-world 或者bitbake can_msgs等特定包

要把canopen等ros的包添加到dey镜像中,可参考参考DEY文件系统定制把can_msgs或ros_canopen包添加到dey镜像中

调试过程: 因为最初编译core-image-ros-world没过,所以展开调试排错,先试着编译一个socketcan_interface 出错时注意那些错误信息:比如这次是:

...undefined reference to symbol 'pthread_getspecific@@GLIBC_2.4'
.......error adding symbols:DSO missing from command line

google一下“undefined reference to symbol ‘pthread_getspecific@@GLIBC_2.4”(注意,最好不要用百度,查不到什么有用信息),有个贴子给出解决方案是:在编译时加上-lpthread控制参数 注意,如果您在tmp/work/ccimx6sbc-dey-linux-gnueabi/socketcan-interface/0.7.6-r0/里改是没有用的,在bitbake时会被刷新掉,用bitbake -C compile xxx可以使用本地的改变。为了更方便调试,可以用:bitbake -c devshell socketcan-interface来调出开发者shell,在源码树里临时改动并测试,这个devshell的源码树和tmp/work/ccimx6…gnueabi/里是一样的,找到socketcan_interface,里面有一个CMakeLists.txt,我们检查编译出错的地方刚好是socketcan_dump链接出错,所以在target_link_libraries(socketcan_dump..)最后加一个pthread,再编译就成功了