@lijiang

Sculpting in time

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

3-Minute Read

Problem

The system of raspberry pi zero w is currently raspberry pi official os image is armv6hf debian 11, and ROS2 official support only ubuntu debian aarch64, not support arm32, so to use ROS2 on raspberry pi zero w must be built from source. So the problem is that if you compile directly on zero w, obviously because of the hardware (cpu: 1 core, memory: 512M), the compilation will be extremely slow, I also tried to use armhf cross-compiler toolchain to compile the ROS source code on aarch64 system, but there will be a problem of missing system libraries. At the same time, I also consider the consistency of the subsequent development environment and zero w’s original system environment, I decided to use zero w’s native debian 11 armhf system as rootfs, make a docker image, and then run on aarch64 systems (such as raspberry pi 4, jetson agx), so that the compiled ros2 can be run on zero w directly. This way, the compiled ros2 can be run on zero w, and the runtime and compilation environments are consistent, which will be very convenient for subsequent tuning and debugging.

Compatibility

raspberry pi zero w uses cpu arm1176jzf-s, armv6 version, raspberry pi 4 uses ARM Cortex-A72 ARMv8-A version, we can get it from Cortex-A72 document, we can see that AArch32 for full backward compatibility with Armv7, that is, armv8 aarch32 instruction set compatible with armv7 aarch32, at the same time armv7 instruction set compatible armv6, then it also means that armv6 binary files can be run directly on raspberry pi 4 aarch64, and vice versa aarch64 binary of course can not be run on the armv6 system, so the idea is clear, we can build a docker image of the armhf root filesystem from raspberry pi armhf debian os and run it on an aarch64 system, compile ros2, then copy the compiled binary files to a zero w to run it directly.

Solve the problem

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

Recent Posts

Categories

About

Keep thinking, Stay curious
Always be sensitive to new things