Developing a Custom ROS 2 Hardware Interface for the Rugged Rover
Over the past few weeks, I’ve been working on integrating a custom hardware interface for the rugged wheeled rover platform we’re building. This post highlights the development process of the ROS 2 hardware interface, the decision to upgrade to a Teensy 4.1 microcontroller, and the ongoing challenges with PID tuning.
Hardware Interface with ros2_control
The robot uses a differential drive setup controlled via a Sabertooth 2x12 motor driver. To interface this with ROS 2, I created a custom package: rugged_rover_hardware_interfaces, following the ros2_control system interface pattern.
The SabertoothSystemInterface:
- Exports position and velocity state interfaces for the left and right wheel joints.
- Publishes battery voltage as an additional
StateInterface. - Publishes joint velocity commands via
sensor_msgs/JointState. - Subscribes to custom feedback messages (
rugged_rover_interfaces/msg/RoverFeedback) coming from the Arduino/Teensy, which includes encoder-based position, velocity, and battery voltage.
The interface is fully wired into the ROS 2 control loop and integrates cleanly with controller_manager and joint_state_broadcaster.
Microcontroller Upgrade: From Arduino Mega to Teensy 4.1
During initial development, I used an Arduino Mega to read encoders, perform PID calculations, and communicate with ROS via serial. While the Mega worked well for prototyping, several limitations started to bottleneck development:
- Limited clock speed (16 MHz) made it hard to handle high-frequency PID control and multi-tasking serial communications.
- Large physical footprint made internal mounting in the chassis more difficult.
- Lack of native USB high-speed and modern architecture led to sporadic delays under load.
The Decision: Teensy 4.1
To solve these issues, I’ve decided to move forward with a Teensy 4.1:
- 600 MHz ARM Cortex-M7 processor with 1 MB RAM gives us ample performance headroom.
- Compact form factor reduces space requirements in the electronics enclosure.
- Native USB High-Speed (480 Mbps) provides snappy ROS serial integration.
- Multiple hardware serial ports (up to 8!) simplifies wiring and expands options for future peripherals (e.g., GPS, IMU).
The upgrade will also enable smoother encoder sampling, non-blocking communication, and support for real-time motor control tasks on a single MCU.
PID Tuning Challenges
One of the more stubborn problems has been tuning the wheel speed PID controllers.
- With simulated data or slow commands, everything behaves predictably.
- Under real load, slight mismatches in encoder readings or noisy sampling can cause aggressive oscillations or sluggish response.
- Integral windup occasionally causes the rover to overshoot or lock into runaway output when reversing direction.
Next steps include:
- Implementing anti-windup in the PID logic.
- Adding low-pass filtering to the encoder velocity signal.
- Dynamically scaling PID gains based on load or command profile.
- Profiling CPU usage and ensuring sampling intervals remain consistent (especially after switching to Teensy).
What’s Next
- Finalize wiring for the Teensy 4.1 and update the firmware to support its serial and interrupt pin layout.
- Connect ROS 2 controllers (like
diff_drive_controller) and test real-world trajectory tracking. - Improve unit testing for the hardware interface and expand test coverage for safety-critical paths.
- Explore publishing diagnostics like battery voltage, current draw, and motor temperature for system health monitoring.
Stay tuned for future posts as I bring the full stack online—from URDF and Gazebo simulation to autonomous waypoint navigation and mission execution.