ros2 嵌入式程序的交叉编译
Title: ros2 嵌入式程序的交叉编译
文章目录
关联博文:
0. 前言
针对简单情况, 只要设置好交叉编译工具链中的环境变量就可以.
I. 系统环境
1. 主机 host 操作系统
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.5 LTS
Release: 22.04
Codename: jammy
printenv ROS_DISTRO
humble
2. 嵌入式 embedded 操作系统
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.5 LTS
Release: 22.04
Codename: jammy
humble
II. 主机上配置编译环境
1. 主机上安装交叉编译工具
sudo apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
2. 获得嵌入式系统的镜像文件
我用的正好是现成的
https://bingda.yuque.com/staff-hckvzc/owgkl4/kzp230ib7a8sddsx
或者使用 dd 命令自制一个 (ros2 嵌入式程序的交叉编译 —— 镜像文件的制作), 如
dd if=/dev/nvme0p1p8 of=/mnt/disk/rootfs.img
镜像文件下载保存为 ~/crosscompile_ws/rootfs_image/opi5pro_22.04_humble_v1.0.1.img
3. 在主机上挂载嵌入式系统的镜像文件
创建挂载点
sudo mkdir -p /mnt/embedded_rootfs
检查镜像文件的分区结构
通过 file 命令查看镜像文件的类型,确认是否包含分区表(多数嵌入式镜像会包含多个分区)
file ~/crosscompile_ws/rootfs_image/opi5pro_22.04_humble_v1.0.1.img
如果是包含分区表的镜像,需通过 fdisk 查看分区偏移量(即根文件系统所在分区的起始位置)
fdisk -l ~/crosscompile_ws/rootfs_image/opi5pro_22.04_humble_v1.0.1.img

计算挂载偏移量(针对多分区镜像), 分区的起始扇区 × 扇区大小(通常 512 字节)= 偏移量(单位:字节)
offset=$((2158592*512))
挂载嵌入式文件系统分区
sudo mount -o loop,offset=$offset -t ext4 ~/crosscompile_ws/rootfs_image/opi5pro_22.04_humble_v1.0.1.img /mnt/embedded_rootfs
4. 针对嵌入式 python 库问题的处理
ros2 在编译时会调用 python 动态库来确定版本等信息, 但是总是找不到交叉编译需要的嵌入式 python 动态库, 最后只能将镜像文件中的嵌入式 python 动态库拷贝到主机上, 供交叉编译时调用.
sudo cp /mnt/embedded_rootfs/usr/lib/aarch64-linux-gnu/libpython3.10.so /usr/lib/aarch64-linux-gnu/
如果没有这一步, 编译时会出现如下错误

III. 主机上编译
1. 下载 ROS2 测试代码到主机上
clone ros2 代码并check 对应版本
https://github.com/ros2/examples.git
git branch -a
git checkout humble
2. 编写交叉编译工具链文件
# toolchain-aarch64.cmake
set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")
set(CMAKE_SYSROOT /mnt/embedded_rootfs)
set(PYTHON_SOABI cpython-310-aarch64-linux-gnu)
set(PythonExtra_EXTENSION_SUFFIX cpython-310-aarch64-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
文件命名为 toolchain-aarch64.cmake, 存储在 ~/crosscompile_ws/toolchain-aarch64.cmake.
3. 进行交叉编译
colcon build \
--merge-install \
--cmake-force-configure \
--cmake-args \
-DCMAKE_TOOLCHAIN_FILE=/home/robot/crosscompile_ws/toolchain-aarch64.cmake \
-DCMAKE_BUILD_TYPE=Release
--event-handlers console_direct+
-DCMAKE_TOOLCHAIN_FILE 指定工具链文件, -DCMAKE_BUILD_TYPE 设置编译类型.
都是简单 example 程序, 没有遇到什么问题, 编译成功
VI. 嵌入式上运行
1. 传输交叉编译后的文件
传输编译后获得的整个 install 文件夹到嵌入式主控板上, 命令格式
scp -r host_directory user@remote_host_ip:/remote_directory
传输复制命令
sudo scp -r ./install/* bingda@192.168.88.30:/home/bingda/ros2_install/
2. 嵌入式环境下运行
cd ~/ros2_install
source ./setup.bash
ros2 run examples_rclcpp_minimal_publisher publisher_member_function
cd ~/ros2_install
source ./setup.bash
ros2 run examples_rclcpp_minimal_subscriber subscriber_member_function

VII. 结论
这个方法最简单, 主要是文件系统是现成的镜像, 省去了利用 docker 获得嵌入式文件系统这些步骤.
但这种方法适合于简单的 ros 2 应用程序的交叉编译, 对于 package 之间相互引用的复杂 ros 2 应用存在诸多问题, 如 “附 II. 交叉编译中可能的问题”.
针对复杂情况, 请参考下一篇博文.
附 I. 镜像挂载脚本实现
镜像挂载自动化脚本 auto_mount.sh 实现
#!/bin/bash
IMAGE_FILE="/home/robot/crosscompile_ws/rootfs_image/opi5pro_22.04_humble_v1.0.1.img"
MOUNT_POINT="/mnt/embedded_rootfs"
# 检查镜像文件是否存在
if [ ! -f "$IMAGE_FILE" ]; then
echo "错误: 镜像文件 $IMAGE_FILE 不存在!"
exit 1
fi
# 创建挂载点(如果不存在)
if [ ! -d "$MOUNT_POINT" ]; then
echo "创建挂载点目录: $MOUNT_POINT"
sudo mkdir -p "$MOUNT_POINT"
fi
# 提取第二个分区(Linux filesystem)的起始扇区
# 从fdisk输出中过滤包含"Linux filesystem"的行,然后提取起始扇区数值
START_SECTOR=$(fdisk -l "$IMAGE_FILE" | grep "Linux filesystem" | awk '{print $2}')
if [ -z "$START_SECTOR" ] || ! [[ "$START_SECTOR" =~ ^[0-9]+$ ]]; then
echo "错误: 无法提取有效的起始扇区!"
echo "请检查分区是否存在或分区类型是否正确"
exit 1
fi
# 计算偏移量(扇区大小默认512字节)
SECTOR_SIZE=512
OFFSET=$((START_SECTOR * SECTOR_SIZE))
echo "找到分区: 起始扇区=$START_SECTOR, 扇区大小=$SECTOR_SIZE字节, 偏移量=$OFFSET字节"
# 执行挂载操作
echo "正在挂载镜像到 $MOUNT_POINT..."
sudo mount -o loop,offset=$OFFSET -t ext4 "$IMAGE_FILE" "$MOUNT_POINT"
# 检查挂载是否成功
if [ $? -eq 0 ]; then
echo "成功挂载镜像到 $MOUNT_POINT"
else
echo "挂载失败!"
exit 1
fi
镜像卸载 auto_unmount.sh 实现
sudo umount /mnt/embedded_rootfs
权限改为可执行 +x.
附 II. 交叉编译中可能的问题
其他稍微复杂一点的 ros2 程序交叉编译中可能遇到一些问题.
比如在编译自定义 ros2 消息包时, 可能遇到如下问题.
1. 自定义 ros2 消息包中的问题
Traceback (most recent call last):
File “/mnt/embedded_rootfs/opt/ros/humble/share/rosidl_generator_cpp/cmake/…/…/…/lib/rosidl_generator_cpp/rosidl_generator_cpp”, line 38, in
sys.exit(main())
File “/mnt/embedded_rootfs/opt/ros/humble/share/rosidl_generator_cpp/cmake/…/…/…/lib/rosidl_generator_cpp/rosidl_generator_cpp”, line 34, in main
generate_cpp(args.generator_arguments_file)
File “/opt/ros/humble/local/lib/python3.10/dist-packages/rosidl_generator_cpp/init.py”, line 39, in generate_cpp
return generate_files(
File “/opt/ros/humble/local/lib/python3.10/dist-packages/rosidl_cmake/init.py”, line 59, in generate_files
assert (template_basepath / template_filename).exists(),
AssertionError: Could not find template: idl__type_support.hpp.em
[解决方法 1]
主机中能够查找到这个确实的文件
find /opt/ros/humble -name "idl__type_support.hpp.em"
但是镜像文件系统中无法查找到该文件
sudo find /mnt/embedded_rootfs -name "idl__type_support.hpp.em"
处理方法利用主机中的模版文件, 交叉编译命令中添加 -Drosidl_generator_cpp_DIR=/opt/ros/humble/share/rosidl_generator_cpp/cmake
colcon build \
--merge-install \
--cmake-force-configure \
--cmake-args \
-DCMAKE_TOOLCHAIN_FILE=/home/robot/crosscompile_ws/toolchain-aarch64.cmake \
-Drosidl_generator_cpp_DIR=/opt/ros/humble/share/rosidl_generator_cpp/cmake
或者工具链配置文件 toolchain-aarch64.cmake 中增加
# 指定 rosidl_generator_cpp 的 CMake 配置文件路径
set(rosidl_generator_cpp_DIR "/opt/ros/humble/share/rosidl_generator_cpp/cmake" CACHE PATH "Path to rosidl_generator_cpp CMake config")
因为 rosidl_generator_cpp 是编译阶段使用的代码生成工具, 依赖主机架构的可执行程序, 所以该路径指向的是主机上的 ROS 2 安装目录 (而非目标镜像文件系统路径).
[解决方法 2]
在运行 colcon build 进行编译前, 在主机终端中 source 镜像系统中 ros2 setup.bash 以此来该终端的环境变量为镜像系统的环境变量.
source /mnt/embedded_rootfs/opt/ros/humble/setup.bash
2. 复杂应用程序中的问题
类似如 nav2 相关的复杂应用程序甚至会形成编译顺序的循环约束 “a cycle in the constraint graph”, 使得交叉编译无法执行下去.
[解决方法 1]
参考 ros2 嵌入式程序的交叉编译 —— 基于 Chroot 文件系统隔离.
参考资料
[1] ros2_humble_foxy_x86交叉编译环境搭建
版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/woyaomaishu2/article/details/152664753?spm=1001.2014.3001.5502
本文作者:wzf@robotics_notes
更多推荐



所有评论(0)