@lijiang

Sculpting in time

Do one thing and do it well.
Every story has a beginning and an end.

2 分钟

问题

raspberry pi zero w 的系统目前树莓派官方推出的镜像是armv6hf debian 11,而ROS2官方只支持ubuntu debian aarch64,不支持arm32,所以要在raspberry pi zero w上使用ROS2必须从源码构建。那么问题就在于如果直接在zero w上编译,显然因为硬件的原因(cpu: 1 core, memory: 512M),编译将会极其缓慢,我也尝试使用armhf交叉编译工具链在aarch64系统上编译ROS源码,但是会出现系统库缺失问题。同时我还考虑到后续的开发环境和zero w原始系统环境的一致性问题,我决定采用zero w的原生debian 11 armhf系统做为rootfs,制作docker image,然后运行在aarch64系统上(比如树莓派4,jetson agx),这样编译出来的ros2直接可以运行在zero w上,并且运行环境和编译环境都是保持一致的,这样对后续的调优以及debug处理都会非常方便。

兼容性

raspberry pi zero w 使用的是cpu arm1176jzf-s,armv6版本,raspberry pi 4 使用的是 ARM Cortex-A72 ARMv8-A版本,我们可以从Cortex-A72文档中看出AArch32 for full backward compatibility with Armv7,也就是armv8 aarch32指令集兼容armv7 aarch32,同时armv7指令集兼容armv6,那么也就意味着armv6的二进制文件是可以直接在raspberry pi 4 aarch64上运行,反之aarch64 binary当然无法在armv6系统上运行,这样思路一下子清晰了,我们可以将armhf的根文件系统制作成docker image,运行在aarch64系统上,然后编译ros2,最后将编译产物拷贝到zero w上直接运行。

解决问题

command line run on raspberry pi 4 ubuntu 20.04 aarch64 os

  1. donwload rpi zero w image (raspios-bullseye-armhf-lite)

  2. mount img file and copy all root partition files to /mnt

sudo losetup /dev/loop0 ./2023-05-03-raspios-bullseye-armhf-lite.img -P
sudo mount /dev/loop0p2 /mnt
sudo rsync -avz -P -p /mnt/ /opt/armv6-rpi-rootfs/
  1. build Docker image

Dockerfile

FROM scratch
ADD . /

docker build -t armhf-rootfs .

  1. ros2 compile environment prepare

docker run -ti –rm armhf-rootfs bash

# install build dependencies (also need run on rpi zero w)

apt install \
    bison \
    cmake \
    curl \
    libasio-dev \
    libbullet-dev \
    libcunit1-dev \
    libcurl4-openssl-dev \
    libeigen3-dev \
    liblog4cxx-dev \
    libopencv-dev \
    libtinyxml2-dev \
    python3-dev \
    python3-netifaces \
    python3-numpy \
    python3-setuptools \
    python3-yaml \
    python3-pip \
    libcppunit-dev python3-sip-dev python3-psutil python3-future

pip3 install rosinstall_generator colcon-common-extensions vcstool lark-parser packaging rosdep

# download ros2 humble source code 

vcs import --input ros2.repos src
  1. patch files
# don't build this unnecessary packages

touch src/ros-visualization/COLCON_IGNORE
touch src/ros/ros_tutorials/turtlesim/COLCON_IGNORE
touch src/ros2/demos/image_tools/COLCON_IGNORE
touch src/ros2/demos/intra_process_demo/COLCON_IGNORE
touch src/ros2/rviz/COLCON_IGNORE

src/ros-tooling/keyboard_handler/keyboard_handler/CMakeLists.txt

error case: libkeyboard_handler.so: undefined reference to `__atomic_fetch_add_8'

@@ -52,9 +52,8 @@
 # TODO(sloretz) stop exporting old-style CMake variables in the future
 ament_export_include_directories("include/${PROJECT_NAME}")
 ament_export_libraries(${PROJECT_NAME})
-
 ament_export_targets(export_${PROJECT_NAME})
-
+target_link_libraries(${PROJECT_NAME} -latomic)
 if(BUILD_TESTING)
   find_package(ament_lint_auto REQUIRED)
   find_package(ament_cmake_gtest)

src/ros2/rcutils/CMakeLists.txt

error case: librcutils.so: undefined reference to `__atomic_load_8'

@@ -130,7 +130,7 @@
   target_compile_definitions(${PROJECT_NAME} PUBLIC RCUTILS_ENABLE_FAULT_INJECTION)
 endif()

-target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})
+target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS} -latomic)

 # Needed if pthread is used for thread local storage.
 if(IOS AND IOS_SDK_VERSION LESS 10.0)
  1. compile

create toolchain.cmake,force cmake project build into cross compiling model

/opt/toolchain.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf)
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_CXX_FLAGS "-latomic")
colcon build --merge-install --cmake-force-configure --cmake-args -DCMAKE_TOOLCHAIN_FILE=/opt/toolchain.cmake
  1. upload ros2 install binary folder to rpi zero w and test
ros2 run demo_nodes_cpp talker

ros2 run demo_nodes_cpp listener

最新文章

分类

关于

Keep thinking, Stay curious
Always be sensitive to new things