ROS2 and Micro-ROS Version 2
Created: 2025-11-29 21:10:37 | Last updated: 2025-11-30 00:44:02 | Status: Public
MicroROS Robot Expansion Board - Complete Setup Guide
Overview
This guide covers setting up a MicroROS control board (ESP32-S3) with ROS2 Humble on Raspberry Pi 5. The board manages motors, IMU, lidar, and servos, connecting to ROS2 via a micro-ROS agent.
Table of Contents
- Hardware Overview
- RPI 5: Install ROS2 Humble
- RPI 5: Install micro-ROS Agent
- ESP32: Setup Development Environment
- ESP32: Install micro-ROS Components
- Configure & Flash the Board
- Hardware Connections
- Test the System
- Robot Bringup & Advanced Features
- Quick Reference
- Essential Documents Reference
Hardware Overview
MicroROS Control Board (ESP32-S3)
- Core: ESP32-S3-WROOM-1U-N4R2 (4MB Flash, 2MB PSRAM)
- Motors: 4x encoder motor interfaces (M1-M4)
- Sensors: ICM42670P 6-axis IMU, MS200 lidar interface
- Servos: 2x PWM servo (S1, S2)
- Power: Type-C PD output for RPI 5 (5.1V/5A)
- Communication: WiFi, Bluetooth, Serial (UART0/UART1)
GPIO Pin Map (Key Assignments)
| Function | GPIO | Notes |
|---|---|---|
| Motor M1 PWM | 4, 5 | Encoder: 6, 7 |
| Motor M2 PWM | 15, 16 | Encoder: 47, 48 |
| Motor M3 PWM | 9, 10 | Encoder: 11, 12 |
| Motor M4 PWM | 13, 14 | Encoder: 1, 2 |
| Servo S1 | 8 | Range: -90° to 90° |
| Servo S2 | 21 | Range: -90° to 20° |
| IMU I2C | 39 (SCL), 40 (SDA) | ICM42670P |
| Lidar UART1 | 17 (TX), 18 (RX) | MS200 230400 baud |
| Type-C Serial | 43 (TX), 44 (RX) | 115200 baud |
| Buzzer | 46 | Active buzzer |
| MCU LED | 45 | Status indicator |
RPI 5: Install ROS2 Humble
1. Set Locale to UTF-8
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
locale # Verify
2. Add ROS2 Repository
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update && sudo apt install curl gnupg lsb-release -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
-o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" \
| sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
3. Install ROS2 Humble
sudo apt update
sudo apt upgrade
sudo apt install ros-humble-desktop python3-argcomplete python3-colcon-common-extensions
# Auto-source on login
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc
4. Verify Installation
# Test with talker/listener
ros2 run demo_nodes_cpp talker
# In another terminal:
ros2 run demo_nodes_cpp listener
RPI 5: Install micro-ROS Agent
Option A: Docker (Recommended)
# Install Docker
sudo apt install docker.io
sudo usermod -aG docker $USER
# Log out and back in for group changes
# Run WiFi agent (UDP on port 8090)
docker run -it --rm --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4
# Run Serial agent (alternative)
docker run -it --rm -v /dev:/dev --privileged --net=host \
microros/micro-ros-agent:humble serial --dev /dev/ttyUSB0 -b 921600 -v4
Exit agent: Ctrl+C (don’t just close terminal or Docker runs in background)
Option B: Build from Source
# Install dependencies
sudo apt install python3-rosdep
sudo rosdep init
rosdep update
# Create workspace
mkdir -p ~/uros_ws/src
cd ~/uros_ws
git clone -b humble https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup
# Install packages and build
rosdep install --from-paths src --ignore-src -y
colcon build
source install/local_setup.bash
# Build agent
ros2 run micro_ros_setup create_agent_ws.sh
ros2 run micro_ros_setup build_agent.sh
# Run agent (source first each time)
source ~/uros_ws/install/local_setup.sh
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8090 -v4
ESP32: Setup Development Environment
1. Install Dependencies
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv \
cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
2. Download ESP-IDF v5.1.2
mkdir -p ~/esp
cd ~/esp
git clone -b v5.1.2 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32s3
3. Activate ESP-IDF (Required Every Terminal Session)
source ~/esp/esp-idf/export.sh
Add to ~/.bashrc for convenience (optional):
alias get_idf='source ~/esp/esp-idf/export.sh'
4. Configure Basic Project Settings
Create a test project or use hello_world:
cd ~/esp/esp-idf/examples/get-started/hello_world
idf.py set-target esp32s3
idf.py menuconfig
Key Settings in menuconfig:
- Serial flasher config → Flash size: 4MB, check “Detect flash size when flashing bootloader”
- Component config → ESP PSRAM → Enable “Support for external, SPI-connected RAM”
- Component config → ESP System Settings → CPU frequency → 240MHz
- Component config → FreeROS → Kernel → configTICK_RATE_HZ → 1000
- Partition Table → Select “Single factory app (large), no OTA”
Save: Press S, then Q to quit
5. Test Compilation
idf.py build
idf.py flash monitor # Connect board via USB first
# Exit monitor: Ctrl+]
ESP32: Install micro-ROS Components
1. Download micro-ROS Component
mkdir -p ~/esp/Samples/extra_components
cd ~/esp/Samples/extra_components
git clone -b humble https://github.com/micro-ROS/micro_ros_espidf_component.git
cd micro_ros_espidf_component
2. Install Python Dependencies
source ~/esp/esp-idf/export.sh # Ensure ESP-IDF active
pip3 install catkin_pkg lark-parser empy colcon-common-extensions
3. CRITICAL: Configure micro-ROS Limits
Edit ~/esp/Samples/extra_components/micro_ros_espidf_component/colcon.meta:
"rmw_microxrcedds": {
"cmake-args": [
"-DRMW_UXRCE_XML_BUFFER_LENGTH=400",
"-DRMW_UXRCE_TRANSPORT=udp",
"-DRMW_UXRCE_MAX_NODES=1",
"-DRMW_UXRCE_MAX_PUBLISHERS=3",
"-DRMW_UXRCE_MAX_SUBSCRIPTIONS=3",
"-DRMW_UXRCE_MAX_SERVICES=1",
"-DRMW_UXRCE_MAX_CLIENTS=1",
"-DRMW_UXRCE_MAX_HISTORY=3"
]
}
Adjust these based on your needs:
- Factory firmware uses: 3 publishers (imu, odom, scan), 3 subscribers (cmd_vel, beep, servos)
- Don’t over-allocate - ESP32 has limited RAM
4. Compile micro-ROS Library
cd ~/esp/Samples/extra_components/micro_ros_espidf_component/examples/int32_publisher
source ~/esp/esp-idf/export.sh
idf.py set-target esp32s3
# Wait for auto-download and compilation (takes several minutes)
# Look for "Configuring done" and "Generating done"
5. Verify Library Built
ls ~/esp/Samples/extra_components/micro_ros_espidf_component/*.a
# Should see: libmicroros.a
6. Clean micro-ROS Cache (if you change colcon.meta)
cd ~/esp/Samples/extra_components/micro_ros_espidf_component/examples/int32_publisher
idf.py clean-microros
# Then rebuild: idf.py set-target esp32s3
Configure & Flash the Board
1. Create Your Project (or Use Factory Firmware)
Option A: Start from Example
cd ~/esp/Samples
cp -r extra_components/micro_ros_espidf_component/examples/int32_publisher my_robot
cd my_robot
Option B: Use Factory-Style Firmware
Use the twist_subscriber and odom_publisher examples as templates.
2. Configure Project CMakeLists.txt
Add to root CMakeLists.txt:
set(EXTRA_COMPONENT_DIRS "~/esp/Samples/extra_components")
3. Configure WiFi and Agent Settings
cd ~/esp/Samples/my_robot # or your project folder
source ~/esp/esp-idf/export.sh
idf.py menuconfig
Navigate to:
- micro-ROS Settings → WiFi Configuration
- WiFi SSID: Your network name
- WiFi Password: Your password
- micro-ROS Settings
- micro-ROS Agent IP: RPI 5 IP address (e.g., 192.168.1.100)
- micro-ROS Agent Port: 8090
- micro-ROS example-app settings
- Ros domain id: 20 (or match your ROS_DOMAIN_ID)
- Ros namespace: Leave empty (or use namespace prefix)
Save: Press S, then Q
4. Build and Flash
idf.py build
idf.py flash monitor
# Exit monitor: Ctrl+]
5. Alternative: Configuration via Serial Script
If using factory firmware, configure via config_robot.py:
# Edit script with your WiFi/IP settings
python3 config_robot.py
# Press reset button on board within 5 seconds of boot
Hardware Connections
Motor Connections (310 Encoder Motors)
| Motor | Board Interface | Cable Color Code |
|---|---|---|
| Left Front (M1) | Motor1 port | White shell → Board, Black shell → Motor |
| Left Rear (M2) | Motor2 port | White shell → Board, Black shell → Motor |
| Right Front (M3) | Motor3 port | White shell → Board, Black shell → Motor |
| Right Rear (M4) | Motor4 port | White shell → Board, Black shell → Motor |
Motor Port Pinout (e.g., M1):
- M1+/M1-: Motor power
- GND/VCC: Encoder power (3.3V)
- H1A/H1B: Encoder pulse signals
MS200 Lidar
- Anti-reverse connector - plug directly into lidar port
- Auto-configured: UART1 (GPIO17 TX, GPIO18 RX) @ 230400 baud
PWM Servos (Optional)
- S1 (bottom port): GPIO8, range -90° to 90°
- S2 (top port): GPIO21, range -90° to 20° (gimbal limited)
- Pinout: Brown=GND, Red=5V, Yellow=Signal
ESP32 WiFi Camera (Optional)
- Connect to custom GPIO ports
- Creates AP:
Yahboom-ESP32_WIFI(no password) - Stream:
http://192.168.4.1:81/stream
Power
- Battery: 7.4V LiPo via T-connector
- RPI 5: Type-C PD (5.1V/5A) from board
- Main switch: Controls all power
Test the System
1. Start Agent on RPI 5
# Set ROS_DOMAIN_ID to match board
export ROS_DOMAIN_ID=20
# Run agent
docker run -it --rm --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4
2. Power On Board
- Turn on main switch
- Watch serial monitor (if connected): Should see WiFi connection → Agent connection
- Agent terminal should show: Node creation, publishers/subscribers registered
3. Verify Node Connection (RPI 5)
# List nodes (should see /YB_Car_Node or your node name)
ros2 node list
# Check node details
ros2 node info /YB_Car_Node
# List all topics
ros2 topic list
4. Test Published Topics
Lidar:
ros2 topic echo /scan
ros2 topic hz /scan # Should be ~11Hz
IMU:
ros2 topic echo /imu
ros2 topic hz /imu # Should be ~20Hz
Odometry (raw encoder):
ros2 topic echo /odom_raw
ros2 topic hz /odom_raw # Should be ~20Hz
5. Test Subscribed Topics (Control)
Move robot forward (0.5 m/s):
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.5, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"
Rotate in place (1.5 rad/s):
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.5}}"
Stop:
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"
Buzzer (on/off):
ros2 topic pub --once /beep std_msgs/msg/UInt16 "data: 1" # On
ros2 topic pub --once /beep std_msgs/msg/UInt16 "data: 0" # Off
ros2 topic pub --once /beep std_msgs/msg/UInt16 "data: 300" # Beep 300ms
Servos:
ros2 topic pub --once /servo_s1 std_msgs/msg/Int32 "data: 30" # S1 to 30°
ros2 topic pub --once /servo_s2 std_msgs/msg/Int32 "data: -60" # S2 to -60°
Robot Bringup & Advanced Features
1. Install Required Packages
sudo apt install ros-humble-robot-localization ros-humble-imu-filter-madgwick \
ros-humble-tf2-tools ros-humble-rqt-tf-tree
2. Full Bringup Launch (Sensor Fusion)
This fuses IMU + odometry and publishes TF tree:
# Ensure agent is running first
ros2 launch yahboomcar_bringup yahboomcar_bringup_launch.py
What this does:
- Filters IMU data (imu_filter_madgwick)
- Fuses IMU + odom → /odom (EKF fusion)
- Publishes TF: odom → base_footprint → base_link → imu_frame
- Loads robot URDF model
3. Visualize in RViz
rviz2
# In RViz:
# - Set Fixed Frame: "base_link"
# - Add → TF
# - Add → LaserScan → Topic: /scan
# - Add → RobotModel
4. View TF Tree
ros2 run rqt_tf_tree rqt_tf_tree
# Or:
ros2 run tf2_ros view_frames
# Generates frames.pdf
5. Keyboard Control (Optional)
ros2 run yahboomcar_ctrl yahboom_keyboard
# Use i/j/k/l for movement, q/z for speed
6. Joystick Control (Optional)
# Terminal 1:
ros2 run yahboomcar_ctrl yahboom_joy
# Terminal 2:
ros2 run joy joy_node
Quick Reference
ESP-IDF Commands
# Activate environment (every new terminal)
source ~/esp/esp-idf/export.sh
# Configure project
idf.py menuconfig
# Set target chip
idf.py set-target esp32s3
# Build only
idf.py build
# Flash only
idf.py flash
# Flash and monitor
idf.py flash monitor
# Monitor only
idf.py monitor
# Exit monitor
Ctrl+]
# Clean micro-ROS (after changing colcon.meta)
idf.py clean-microros
# Full clean
idf.py fullclean
micro-ROS Agent Commands
# Docker WiFi agent
docker run -it --rm --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4
# Docker Serial agent
docker run -it --rm -v /dev:/dev --privileged --net=host \
microros/micro-ros-agent:humble serial --dev /dev/ttyUSB0 -b 921600 -v4
# Source-built agent
source ~/uros_ws/install/local_setup.sh
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8090 -v4
# Exit agent
Ctrl+C
ROS2 Topic Quick Reference
| Topic | Type | Rate | Direction | Purpose |
|---|---|---|---|---|
/cmd_vel |
Twist | - | Subscribe | Robot speed control |
/scan |
LaserScan | 11Hz | Publish | MS200 lidar data |
/imu |
Imu | 20Hz | Publish | Filtered IMU data |
/odom_raw |
Odometry | 20Hz | Publish | Raw encoder odometry |
/odom |
Odometry | 20Hz | Publish | Fused IMU+odom (after bringup) |
/beep |
UInt16 | - | Subscribe | Buzzer control (0/1/ms) |
/servo_s1 |
Int32 | - | Subscribe | Servo 1 angle (-90 to 90) |
/servo_s2 |
Int32 | - | Subscribe | Servo 2 angle (-90 to 20) |
Kinematics Parameters
From robot_kinematics_analysis.md:
- W (wheelbase width): Distance between left/right wheels
- L (wheelbase length): Distance between front/rear wheels
- A = W/2, B = L/2
- ROBOT_APB = A + B (used in code)
Speed equations:
V_m1 = V_x - V_z * (A+B) // Left front
V_m2 = V_x - V_z * (A+B) // Left rear
V_m3 = V_x + V_z * (A+B) // Right front
V_m4 = V_x + V_z * (A+B) // Right rear
Network Configuration
# On RPI 5, match board's ROS_DOMAIN_ID
export ROS_DOMAIN_ID=20
# Add to ~/.bashrc to persist
# Check RPI 5 IP
ip addr show
# Both devices must be on same LAN
# For VM: use "Bridge mode" networking
Troubleshooting
| Problem | Solution |
|---|---|
| Agent won’t connect | Check: WiFi SSID/password, agent IP, port 8090, ROS_DOMAIN_ID match |
No /YB_Car_Node |
Press reset on board, restart agent, check serial monitor |
| “Service not ready” | Agent not running or wrong IP/port |
| Motors don’t move | Check battery voltage (7.4V), motor connections, /cmd_vel topic |
| Compilation fails | Re-run source ~/esp/esp-idf/export.sh, check ESP-IDF version (5.1.2) |
| “libmicroros.a not found” | Build int32_publisher example first, verify EXTRA_COMPONENT_DIRS path |
| Serial port busy | Stop agent if using /dev/ttyUSB0, close other serial monitors |
Multiple nodes in ros2 node list |
Ctrl+C agent, reset board, restart agent cleanly |
| IMU/Lidar no data | Check hardware connections, verify topics with ros2 topic list |
Essential Documents Reference
From Your Text Dump - Priority Reading Order
MUST READ (in this order):
1. brief-introduction-of-microros-control-board.md - Hardware specs, GPIO pins
2. 3.-microros-control-board-configuration.md - Board config script
3. set-up-esp32-idf-development-environment.md - ESP-IDF install
4. install-esp32-microros-components.md - Critical: micro-ROS build process
5. install-and-start-microros-agent.md - Agent setup on RPI 5
Hardware Integration Examples:
6. subscribe-speed-control-topics.md - /cmd_vel subscriber, motor control
7. release-speed-topic.md - Odometry publisher
8. publish-lidar-data-topics.md - MS200 lidar integration
9. release-imu-data-topic.md - IMU publisher
Testing & Verification:
10. 1.-robot-information-release.md - Factory firmware topics, ROS2 CLI testing
Optional (for custom features):
- subscribe-pwm-servo-topics.md - Servo control
- subscribe-buzzer-topics.md - Buzzer control
- robot-kinematics-analysis.md - 4-wheel drive equations
- 4.-robot-state-estimation.md - Sensor fusion (EKF)
- customized-transmission-method.md - Serial transport vs UDP
Skip for now:
- ROS2 tutorial docs (1.introduction-to-ros2.md through 23.ros2-tf2-coordinate-transformation.md) - Generic ROS2 info
- ESP32 hardware examples (led.md, beep.md, encoder.md, etc.) - Low-level testing only
- Calibration docs - Do after basic system works
Next Steps
- Basic Testing: Verify all topics publish/subscribe correctly
- Calibration: Run
calibrate_linear.pyandcalibrate_angular.pyfor accuracy - Mapping: Install
ros-humble-slam-toolboxorros-humble-cartographer - Navigation: Install
ros-humble-navigation2 - Vision: Add camera (ESP32 WiFi or USB camera on RPI 5)
License & Support
- ESP-IDF: Apache 2.0
- micro-ROS: Apache 2.0
- ROS2: Apache 2.0
Board-specific issues: Refer to Yahboom documentation
ROS2/micro-ROS issues: Check official repos and forums
Version: 1.0 | Last Updated: 2025-01-29