name: oh-cross-build-ros-pkg description: "Cross-compile third-party ROS 2 packages for OpenHarmony aarch64 (BQ3588HM). Use when user needs to 'cross-compile ROS package', 'port ROS package to OH', 'build ROS for OpenHarmony', '移植ROS包', '交叉编译ROS', 'OH aarch64 build', 'usb_cam board', 'deploy ROS package to board', 'third-party ROS package'. Triggers for cross-compiling any ROS 2 Humble package for the Bearkey BQ3588HM OpenHarmony board."
Cross-Build Third-Party ROS 2 Packages for OpenHarmony
Port and deploy third-party ROS 2 packages (e.g., usb_cam, camera_ros, nav2 etc.) to the BQ3588HM OpenHarmony board using the Docker-based cross-compilation toolchain.
When to Use This Skill
- User wants to add a new ROS 2 package to the board that is NOT part of IB_Robot source tree
- User says "移植XX包到板端", "板端编译XX", "cross-compile XX for OH"
- User needs a ROS driver (camera, lidar, etc.) on the board
- Package exists as a standard ROS 2 Humble package on GitHub / rosdistro
Do NOT use for:
- Building IB_Robot's own packages (
inference_service,robot_config, etc.) — useibrobot-buildorbuild_ibrobot_oh_custom.sh - Board connectivity — use
ibrobot-hdc - Running inference — use
bq3588-oh-rknn
Architecture Overview
Host (x86_64 Ubuntu 22.04)
+-- Docker container (voxelsky/ohos-ros-humble-builder:v0.1.5)
| Cross-compiles with OHOS SDK + toolchain
| Outputs aarch64 ELF binaries linked against musl
|
+-- OH_CUSTOM_ROOT/
+-- ibrobot_oh_ws/src/<package>/ ← source
+-- ibrobot_oh_ws/install/<package>/ ← build output
+-- install/ ← OH ROS 2 Humble runtime (sysroot)
+-- ohos-robot-toolchain/18/native/ ← OHOS SDK + sysroot
Board receives deployable install/<package>/ directory via hdc file send.
Prerequisites
These must exist before starting (one-time setup, likely already done):
| Component | Path on Host | Purpose |
|---|---|---|
| OH build root | ~/Research/bq3588_oh_ws/custom_build_root/ |
Contains all build artifacts |
| OH ROS 2 Humble runtime | <build_root>/install/ |
Cross-compilation sysroot |
| OHOS SDK | <build_root>/ohos-robot-toolchain/18/native/ |
Compiler + sysroot |
| Docker builder image | voxelsky/ohos-ros-humble-builder:v0.1.5 |
Build environment |
| HDC access to board | hdc -t 192.168.136.111:8710 |
Deployment transport |
Board-side prerequisites:
| Component | Board Path | Purpose |
|---|---|---|
| OH ROS 2 runtime | /data/install + /data/out |
Base ROS 2 libraries |
| ROS env script | /data/ros2ohos.env |
Environment setup |
| IB Robot install | /data/ibrobot/install |
IB Robot packages |
setup.sh chain |
/data/ibrobot/install/setup.sh |
Package discovery |
Step-by-Step Workflow
Step 1: Assess Package Feasibility
Before building, verify the package is compatible:
# Check package dependencies
grep -E "<build_depend>|<exec_depend>|<depend>" <pkg>/package.xml
Known compatible: Pure C/C++ packages, ROS 2 nodelets using standard message types, packages depending on rclcpp/rclpy + common messages.
Known problematic:
- Packages requiring CUDA/GPU
- Packages with x86_64 inline assembly
- Packages needing Qt/GTK GUI
- Packages with hard dependency on glibc (OH uses musl)
Library dependency checklist — if the package needs a library beyond what's in /data/out/lib/ and /data/install/lib/, you must also cross-compile that library first.
Common pre-installed libraries on the board:
libavcodec,libavformat,libswscale(ffmpeg)libopencv_*(OpenCV)libv4l2(V4L2)- Standard ROS 2 Humble libraries
Step 2: Clone Package Source
# Workspace source directory
OH_WS_SRC=<build_root>/ibrobot_oh_ws/src
# Clone the package (use --depth 1 for speed, specify branch if needed)
git clone --depth 1 -b <branch> <repo_url> ${OH_WS_SRC}/<package_name>
# Example: usb_cam
git clone --depth 1 -b main https://github.com/ros-drivers/usb_cam.git ${OH_WS_SRC}/usb_cam
Step 3: Cross-Build in Docker
Use the OH builder Docker image to cross-compile:
OH_CUSTOM_ROOT=<build_root> # e.g., ~/Research/bq3588_oh_ws/custom_build_root
OH_IMAGE=voxelsky/ohos-ros-humble-builder:v0.1.5
PACKAGE=<package_name> # e.g., usb_cam
docker run --rm -i \
-e WS_ROOT=/mnt/ohos/tmp \
-e OHOS_SDK=/mnt/ohos/tmp/ohos-robot-toolchain/18 \
--name ibrobot-oh-build \
-v "${OH_CUSTOM_ROOT}:/mnt/ohos" \
-v "${OH_CUSTOM_ROOT}:/mnt/ohos/tmp" \
"${OH_IMAGE}" \
bash -lc "
set -euo pipefail
export OHOS_CPU=aarch64
export OHOS_SDK=/mnt/ohos/tmp/ohos-robot-toolchain/18
build-ros-humble --custom \
--wd /mnt/ohos/tmp/ibrobot_oh_ws \
--custom-prefix /data/ibrobot/install \
--colcon-args --packages-select ${PACKAGE}
"
Key flags:
--custom: Uses the OHOS SDK cross-compilation mode--custom-prefix /data/ibrobot/install: Sets the install prefix to match board deployment path--packages-select: Only builds the target package(s) + their dependencies in the workspace
Step 4: Fix Ownership (if needed)
Docker runs as root; fix ownership of build artifacts:
docker run --rm \
-v "${OH_CUSTOM_ROOT}:/mnt/ohos" \
"${OH_IMAGE}" \
sh -c "chown -R $(id -u):$(id -g) /mnt/ohos/ibrobot_oh_ws/install /mnt/ohos/ibrobot_oh_ws/build /mnt/ohos/ibrobot_oh_ws/log || true"
Step 5: Verify Build Output
# Check binary type — must be aarch64 + musl
file ${OH_CUSTOM_ROOT}/ibrobot_oh_ws/install/${PACKAGE}/lib/*/$(basename ${PACKAGE}_node_exe || echo *)
# Expected output: "ELF shared object, 64-bit LSB arm64, dynamic (/lib/ld-musl-aarch64.so.1)"
Step 6: Deploy to Board
hdc file send ${OH_CUSTOM_ROOT}/ibrobot_oh_ws/install/${PACKAGE} /data/ibrobot/install/${PACKAGE}
Step 7: Verify on Board
# Check package discovery
hdc shell 'source /data/ros2ohos.env && source /data/ibrobot/install/setup.sh && ros2 pkg prefix ${PACKAGE}'
# Test run (use CycloneDDS!)
hdc shell 'source /data/ros2ohos.env && source /data/ibrobot/install/setup.sh && \
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp && \
timeout 10 ros2 run ${PACKAGE} <executable> --ros-args <params>'
CRITICAL: Always set RMW_IMPLEMENTATION=rmw_cyclonedds_cpp on the board. The default rmw_fastrtps_cpp crashes with assertion errors on OpenHarmony musl.
Step 8: Fix Runtime Issues
Common runtime problems and fixes:
| Problem | Cause | Fix |
|---|---|---|
No executable found |
Binary not marked executable or PATH issue | chmod +x the binary; use full path |
Assertion failed: ... cast_or_create_topic |
Using rmw_fastrtps_cpp |
Set RMW_IMPLEMENTATION=rmw_cyclonedds_cpp |
cannot open shared object |
Missing library | Check with ldd; deploy missing lib to /data/out/lib/ |
Cannot open device |
Permission denied on /dev/videoX |
chmod 666 /dev/videoX |
| Parameter not taking effect | ROS 2 parameter name mismatch | Check declare_parameter() names in source |
Integration with IB Robot Launch System
Once the package is deployed, integrate it into the robot launch:
For Camera Drivers
The robot YAML config at src/robot_config/config/robots/<robot>.yaml controls camera launch:
peripherals:
- type: camera
name: top
driver: opencv # "opencv" → uses usb_cam_node_exe
index: 0 # → /dev/video0 (or /dev/video20 on board)
width: 640
height: 480
fps: 30
pixel_format: mjpeg2rgb
frame_id: camera_top_frame
The driver: opencv mapping is defined in src/robot_config/robot_config/launch_builders/perception.py:52-107:
driver: opencv→ launchesusb_cam_node_exefromusb_campackagedriver: camera_ros→ launchescamera_ros_nodefromcamera_rospackagedriver: realsense2_camera→ launchesrealsense2_camera_node
If adding a new driver type, you must edit perception.py to add the mapping.
For Non-Camera Packages
Add the package to the appropriate launch builder:
- Navigation:
launch_builders/navigation.py - Voice/sensors: create a new builder
- Or add directly in
robot.launch.py
Deployed Packages Registry
| Package | Source | Version | Binary | Board Path | Status |
|---|---|---|---|---|---|
| usb_cam | ros-drivers/usb_cam | main (0b1c9d7) | usb_cam_node_exe (aarch64/musl) |
/data/ibrobot/install/usb_cam/ |
Verified 30 FPS @ 640x480 MJPEG |
Reference: Build Environment Variables
# Default values (override via CLI flags or environment)
OH_CUSTOM_ROOT=~/Research/bq3588_oh_ws/custom_build_root
OH_CUSTOM_WS=${OH_CUSTOM_ROOT}/ibrobot_oh_ws
OH_CUSTOM_SRC=${OH_CUSTOM_WS}/src
OH_CUSTOM_TOOLCHAIN_ROOT=${OH_CUSTOM_ROOT}/ohos-robot-toolchain
OH_CUSTOM_IMAGE=voxelsky/ohos-ros-humble-builder:v0.1.5
OH_CUSTOM_PREFIX=/data/ibrobot/install # on-device install prefix
OH_BOARD_ROS_PREFIX=/data/install # on-device ROS 2 Humble prefix
Reference: Board Environment
# Always source these two on the board before any ROS command
source /data/ros2ohos.env
source /data/ibrobot/install/setup.sh
# Always set DDS implementation
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
# For multi-machine (board + Ubuntu), use same domain
export ROS_DOMAIN_ID=42