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
-
donwload rpi zero w image (raspios-bullseye-armhf-lite)
-
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/
- build Docker image
Dockerfile
FROM scratch
ADD . /
docker build -t armhf-rootfs .
- 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
- 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)
- 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
- upload ros2 install binary folder to rpi zero w and test
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener