前言

内容概括:
本篇文章记录了ros2 交叉编译(从x86_ubuntu到 riscv_ubuntu)过程,以及问题解决。
整体思路:创建riscv_ubuntu docker镜像——源码编译ros2——交叉编译
因为ros2没有提供riscv预编译版本,所以不能像arm架构那样在创建docker就直接安装好ros2,需要先创建docker再用源码编译,相对来说实现过程复杂一些。


一、创建 riscv_ubuntu 镜像

下载ros2官方提供的 dockerfiles 和 示例examples
mkdir -p ~/cc_ws/ros2_ws/src
cd ~/cc_ws/
git clone https://github.com/ros-tooling/cross_compile.git -b 0.0.1 .
创建docker镜像

在执行创建docker镜像命令前需要先对Dockerfile_ubuntu_arm进行修改(在cross_compile/sysroot下),避免混淆可以先把文件名改为Dockerfile_ubuntu_riscv
拉取的docker 镜像是riscv64/ubuntu:jammy,docker hub镜像地址:riscv64/ubuntu

ARG ARM_ARCH=arm64v8
FROM ${ARM_ARCH}/ubuntu:bionic
修改为:
ARG ARM_ARCH=riscv64
FROM ${ARM_ARCH}/ubuntu:jammy

rosdep改为rosdepc:
--------------------------
RUN apt install -y \
    python3-colcon-common-extensions \
    python3-pip \
    python3-rosdep
修改为:
RUN apt install -y \
    python3-colcon-common-extensions \
    python3-pip
--------------------------
RUN python3 -m pip install -U \
    argcomplete \
    flake8 \
    flake8-blind-except \
    flake8-builtins \
    flake8-class-newline \
    flake8-comprehensions \
    flake8-deprecated \
    flake8-docstrings \
    flake8-import-order \
    flake8-quotes \
    pytest-repeat \
    pytest-rerunfailures
修改为:
RUN python3 -m pip install -U \
    rosdepc \
    argcomplete \
    flake8 \
    flake8-blind-except \
    flake8-builtins \
    flake8-class-newline \
    flake8-comprehensions \
    flake8-deprecated \
    flake8-docstrings \
    flake8-import-order \
    flake8-quotes \
    pytest-repeat \
    pytest-rerunfailures
--------------------------
RUN rosdep init
RUN rosdep update
RUN rosdep install --from-paths src \
    --ignore-src \
    --rosdistro crystal -y \
    --skip-keys "console_bridge \
        fastcdr \
        fastrtps \
        libopensplice67 \
        libopensplice69 \
        rti-connext-dds-5.3.1 \
        urdfdom_headers"
修改为:
RUN rosdepc init
RUN rosdepc update
RUN rosdepc install --from-paths src \
    --ignore-src \
    --rosdistro crystal -y \
    --skip-keys "console_bridge \
        fastcdr \
        fastrtps \
        libopensplice67 \
        libopensplice69 \
        rti-connext-dds-5.3.1 \
        urdfdom_headers"

执行创建docker命令:

cd ~/cc_ws/

# qemu  用于使用docker在目标文件系统上安装ROS 2依赖项
mkdir qemu-user-static
cp /usr/bin/qemu-*-static qemu-user-static

docker build -t riscv_ros2:latest -f cross_compile/sysroot/Dockerfile_ubuntu_arm .
docker run --name riscv_sysroot riscv_ros2:latest

执行docker run时会提示因为架构不同所以无法直接进入docker,没有影响,docker镜像能正常挂载使用。

二、源码编译ros2

拉取ros2源码
cd ~/cc_ws/ros2_ws
wget https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos
vcs-import src < ros2.repos

如果终端提示无法连接网址,则可以在浏览器打开手动保存网页到本地

将ros2源码目录挂载到docker
docker run -it --rm -v /home/sun/cc_ws/ros2_ws:/data --name riscv_sys e5279bcbe77

成功执行后就相当于进入docker镜像中执行后续操作,其中 /home/sun/cc_ws/ros2_ws 是本地包含src的目录, /data是docker镜像中挂载目录,riscv_sys是docker容器名称(sudo docker container查看),e5279bcbe77是docker镜像id(sudo docker images查看)

对ros2源码进行编译
# 挂载后在docker中进行操作
cd /data
ls   # 查看是否有src文件夹
colcon build --symlink-install  # 源码编译

在riscv64架构上通过源码编译ros2时会遇到一些问题:

问题一:mimick_vendor功能包不支持riscv64架构
在这里插入图片描述

  • 解决方法:在src中通过查找方法找到mimick_vendor功能包(一定要查找,因为直接进文件夹没有显示),对CMakelists进行修改,将对应两行内容修改为如下
set(mimick_version "90d02296025f38da2e33c67b02b7fa0c7c7d460c")
GIT_REPOSITORY https://github.com/ziyao233/Mimick.git

在这里插入图片描述

问题二:部分功能包编译时需要在网址下载但报错无法连接在这里插入图片描述

  • 解决方法:手动打开连接并下载,放到挂载的目录下,修改对应功能包的cmakelists 中的 URL 将网络地址修改该为本地文件 绝对路径(注意一定是 docker 镜像中的绝对路径,而不是本地绝对路径)
    在这里插入图片描述

问题三:riscv64_ubuntu缺少很多需要的依赖,需要一边编译一边报错再安装,ros2还有一些包比如rviz(ros 可视化)需要python绑定器等问题,若无法解决且不需要相关功能,则可以根据情况删除对应功能包

apt install libeigen3-dev
apt-get install libacl1-dev
apt-get install libx11-dev libxaw7-dev
apt-get install libldap2-dev
apt-get install libssl-dev
apt-get install libeigen3-dev
pip install lark-parser
apt-get install qtbase5-dev
apt-get install libfreetype-dev
apt install -y ninja-build
apt install python3-numpy
apt install libopencv-dev
apt install libbullet-dev
apt-get install libfreetype-dev
完成编译

ros2 完成源码有三百多个功能包,完整编译需要足够的磁盘空间,源码编译完成后就可以在对应目录下source 测试ros2 demo
在这里插入图片描述

测试ros2 demo
# 挂载后在docker中进行操作
cd /data
source install/local_setup.bash
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_py listener

在这里插入图片描述

注意:以挂载的方式使用docker,编译生成的文件内容是在本地,但是如果源码编译ros2则编译产生的build/install中的文件链接/索引路径都是相对于docker系统的绝对路径,所以想要使用riscv_ubuntu架构ros2只能每次都把cc_ws/ros2_ws挂载到/data下

三、交叉编译

前提:已将/cc_ws/ros2_ws挂载到docker /data下

将官方示例examples放到挂载目录下
cd ~/cc_ws
mkdir -p ~/cc_ws/ros2_ws/cross/src
sudo cp -r cross_compile/ ~/cc_ws/ros2_ws/cross/src
安装所需包和依赖
# 在docker中执行
apt install libssl-dev
pip install netifaces
apt-get install gcc-riscv64-linux-gnu
riscv64-linux-gnu-gcc --version
apt-get install g++-riscv64-linux-gnu
riscv64-linux-gnu-g++ --version
修改交叉编译工具链generic_linux.cmake

generic_linux.cmakecross/cross_compile/cmake-toolchains目录下:

# 显式设置交叉编译器   riscv_ubuntu系统自带  
set(CMAKE_C_COMPILER /usr/bin/riscv64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/riscv64-linux-gnu-g++)
-----------------------------------------------------

if("$ENV{TARGET_ARCH}" STREQUAL "" OR
   #"$ENV{CROSS_COMPILE}" STREQUAL "" OR
   "$ENV{SYSROOT}" STREQUAL "" OR
   "$ENV{ROS2_INSTALL_PATH}" STREQUAL "" OR
   "$ENV{PYTHON_SOABI}" STREQUAL "")
    message(FATAL_ERROR "Target environment variables not defined")
endif()

修改为

if("$ENV{TARGET_ARCH}" STREQUAL "" OR
   #"$ENV{CROSS_COMPILE}" STREQUAL "" OR
   "$ENV{SYSROOT}" STREQUAL "" OR
   "$ENV{ROS2_INSTALL_PATH}" STREQUAL ""
   #"$ENV{PYTHON_SOABI}" STREQUAL ""
   )
    message(FATAL_ERROR "Target environment variables not defined")
endif()
交叉编译
# # 挂载后在docker中进行操作
cd /data
source install/local_setup.bash
export TARGET_ARCH=riscv64
export SYSROOT=/
export ROS2_INSTALL_PATH=/data/install/

cd cross
# 交叉编译指令
colcon build --merge-install \
    --cmake-force-configure \
    --cmake-args \
        -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
        -DCMAKE_TOOLCHAIN_FILE="/data/cross/src/cross_compile/cmake-toolchains/generic_linux.cmake" \
完成交叉编译

交叉编译本质上是将x86架构下的代码文件编译成riscv架构下ros2可直接运行的可执行文件,编译后的生成文件在本地可以看到,但是不能运行,必须得在riscv架构硬件上或者docker 镜像中运行。

在这里插入图片描述

在这里插入图片描述

测试交叉编译ros2 demo
cd /data/cross
source install/local_setup.bash
ros2 run demo_nodes_cpp listener &
ros2 run demo_nodes_py talker

在这里插入图片描述

总结

因为ros2没有提供riscv架构预编译版本,所以整个实现交叉编译的过程比arm架构复杂一些,但整体思路和实现方法没有太多区别,后续还要看一下ros2底层代码逻辑在不同架构上具体的区别,以便更好的在不同架构平台开发功能。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐