- Hardware: Pico 2040 + Pi5
- Software: Ubuntu 24 + ROS2 Jazzy + Microros
# clone the repository
cd ~
gh repo clone mbot-project/mbot_firmware_ros
cd ~/mbot_firmware_ros
# compile the firmware code
mkdir build
cd build
cmake ..
makeThen flash the firmware to the pico board:
cd ~/mbot_firmware_ros/build
# calibration - wait until the robot stops moving
sudo mbot-upload-firmware flash mbot_calibrate_classic.uf2
# main firmware
sudo mbot-upload-firmware flash mbot_classic_ros.uf2libmicroros: This directory contains the precompiled micro-ROS static library (libmicroros.a) and all necessary header files for the Raspberry Pi Pico. This library includes:- ROS 2 client library core functionality
- Message type definitions
- Transport layer implementations
- Serialization/deserialization utilities
microros_static_library: Contains scripts and configuration files used to generate thelibmicrorosstatic library. We use it when we need to add customized ros data types. The key components include:library_generation.sh: Script that sets up the build environment, compiles micro-ROS packages, and generates the static librarycolcon.meta: Configuration for the colcon build systemtoolchain.cmake: CMake toolchain file for cross-compiling to Raspberry Pi Pico
comms: Communication Setupmbot: MBot Hardware Libraryrc(Robot Control): A library providing essential functions for robot control applications.- Supporting Files
available_ros2_types: A list of all ROS 2 message, service, and action types available in the micro-ROS librarybuilt_packages: A list of all Git repositories and their specific commit hashes used to build the micro-ROS library
src/: microROS-based implementationinclude/config/mbot_classic_config.h: MBot classic config filembot/include/mbot/defs/mbot_params.h: MBot system config file
mbot_classic_ros.c/.h: Core application logic, main loop, hardware interface calls, and microROS node initialization.mbot_ros_comms.c/.h: Handles all ROS-specific communication aspects including publisher/subscriber setup, message initialization, and callbacks.mbot_odometry.c/.h: Odometry calculation utilities.mbot_print.c/.h: Debug printing utilities.
| Topic | Pub Rate | QoS |
|---|---|---|
| /battery_adc | 4 HZ | Best Effort |
| /encoders | 50 HZ | Best Effort |
| /imu | 100 HZ | Best Effort |
| /motor_vel | 100 HZ | Best Effort |
| /odom | 25 HZ | Reliable |
| /tf | 50 HZ | Reliable |
- Using local state variables for robot state (
mbot_state_t,mbot_cmd_t) - Synchronizing state between hardware readings and ROS messages (hardware readings update
mbot_state, ROS messages are populated frommbot_state,mbot_cmdupdated by ROS callbacks). Key global state variables:mbot_state_t mbot_state: Defined inmbot_classic_ros.c, holds the current snapshot of all robot sensor data, odometry, and derived states. Updated bymbot_loop. Read bymbot_publish_state.mbot_cmd_t mbot_cmd: Defined inmbot_classic_ros.c, stores the latest commands received via ROS subscriptions. Updated by ROS callbacks inmbot_ros_comms.c. Read by motor control logic inmbot_loop.mbot_params_t params: Stores calibration parameters loaded from FRAM.
The firmware uses a single USB Type-C connection with dual CDC (Communication Device Class) interfaces:
-
Debug Channel (
/dev/mbot_debug):- Used for firmware debug messages and status prints
- Accessible via standard serial tools:
sudo minicom -D /dev/mbot_debug -b 115200
-
MicroROS Channel (
/dev//mbot_microros):- Dedicated to microROS communication
- Handles all ROS2 messages and services
- Used by micro-ros-agent for ROS2 bridge
This dual-channel approach allows simultaneous debugging and ROS communication without additional hardware connections.
TinyUSB (the USB stack used for CDC communication) requires frequent servicing via tud_task() (dual_cdc_task()).
If the USB stack is not serviced regularly (ideally every 1–10 ms), the host computer may think the device is unresponsive and disconnect the serial ports (/dev/mbot_debug, /dev//mbot_microros).
Do NOT use long sleep_ms() calls.
// BAD: This will block USB for 2 seconds!
sleep_ms(2000);Use the wait function we provide.
#include "comms/dual_cdc.h";
mbot_wait_ms(2000);- Using ROS time synchronization
- Maintaining fixed-rate control loops (e.g., 25Hz for sensor acquisition and control logic via
mbot_loop) - Periodic ROS state publishing (e.g., 20Hz via
timer_callbacktriggered byros_publish_timer)
Variables:
mbot_state.timestamp_usis the last time the mbot_state was updated bymbot_loop.mbot_state.last_encoder_timeis the Pico local time recorded at the start of the encoder read inmbot_loop, used for calculatingencoder_delta_t.nowvariable (local tombot_publish_statefunction) holds the ROS-synchronized epoch time obtained viarmw_uros_epoch_nanos(), used for timestamping outgoing ROS messages.