Guide to ROS2 MoveIt2 Integration for an Open-Source 3D-Printed Robotic Arm and Raspberry Pi
ROS 2 MoveIt² Integration for an Open-Source 3D-Printed Robotic Arm on Raspberry Pi
A step-by-step guide to bring a low-cost, open-hardware robotic arm to life—fully integrated with ROS 2 and MoveIt² for motion planning and real-world control.
Why This Matters: With MoveIt²—ROS 2’s official motion planning framework—and open-source arms like the OpenCRX, Roboteq Arm, or Universal Robot-inspired designs, you can run advanced motion planning—like obstacle-avoiding trajectories—on a Raspberry Pi 4 or 5. All while keeping cost, complexity, and hardware dependencies low.
1. What You’ll Build
By the end of this guide, you’ll have:
- ✅ A fully functional ROS 2 node controlling a 3D-printed robotic arm
- ✅ MoveIt² motion planning stack—complete with collision-aware planning
- ✅ A Raspberry Pi acting as both a controller and ROS 2 compute node
- ✅ Real-time control of joints via low-level hardware interfaces
All based on an open-source mechanical design, freely available URDF, and standard ROS 2 tooling—no vendor lock-in, no black-box drivers.
2. Hardware & Software Prerequisites
Hardware Requirements
- 3D-printed arm (e.g., 4- or 6-DOF, with servo/stepper motors)
- Raspberry Pi 4 (4GB+) or Pi 5 (for heavier planning workloads)
- Power supply: ≥3A for Pi 4, ≥5A for Pi 5
- Hardware interface: UART, CAN, PWM, or GPIO for motor control
Software Stack
- Ubuntu 22.04 (Jammy) or Raspberry Pi OS (Bookworm) + ROS 2 Humble Hawksbill
- MoveIt² (core + moveit_configs_utils + moveit_servo)
- ROS 2 control stack:
ros2_control+ hardware interfaces - System dependencies:
MoveIt Setup Assistant,urdf,xacro
3. Step-by-Step Setup Guide
3.1. Model Your Robot: The URDF & SRDF
Start with an open-source URDF (e.g., from evolvedminds). Your robot’s .urdf file must define:
- Physical links and joint types (revolute, prismatic)
- Inertial, visual, and collision properties for safe planning
- Transmission definitions (if using
ros2_control)
Example snippet for a revolute joint:
<joint name="joint1" type="revolute">
<axis xyz="0 0 1"/>
<limit effort="10" velocity="1.5" lower="-3.14" upper="3.14"/>
<safety_controller k_position="20" k_velocity="2"/>
</joint>
Next, generate a Semantic Robot Description Format (SRDF) file using the MoveIt Setup Assistant. This defines:
- Virtual joints (e.g., floating base)
- Collision groups (e.g., “end_effector”, “whole_arm”)
- End-effectors and planning groups
- Default pose configurations
3.2. Configure ros2_control for the Pi
Use ros2_control as the interface between MoveIt² and your hardware. Here’s a minimal .yaml config for a 6-DOF arm using PWM GPIO:
controller_manager:
ros__parameters:
update_rate: 100
joint_trajectory_controller: {} # for trajectory following
arm_controller:
type: joint_trajectory_controller/JointTrajectoryController
joint_trajectory_controller:
ros__parameters:
joints:
- joint1
- joint2
- joint3
- joint4
- joint5
- joint6
interface_names:
state: ["position", "velocity"]
command: ["position"]
state_interfaces: ["position", "velocity"]
command_interfaces: ["position"]
allow_partial_joints_goal: false
feedback_type: "full"
allow_integration_in_goal_trajectories: true
For low-level motor drivers, implement a custom hardware interface in C++ or Python. Example interface class header:
#include "hardware_interface/system_interface.hpp"
#include "rclcpp/rclcpp.hpp"
class ArmHardwareInterface : public hardware_interface::SystemInterface
{
public:
RCLCPP_SHARED_PTR_DEFINITIONS(ArmHardwareInterface);
hardware_interface::return_type configure(const HardwareInfo & info) override;
hardware_interface::return_type start() override;
hardware_interface::return_type stop() override;
hardware_interface::return_type read(const Time & time, const Duration & period) override;
hardware_interface::return_type write(const Time & time, const Duration & period) override;
};
3.3. Build the MoveIt² Stack
Use the MoveIt² Setup Assistant to generate a ready-to-configure moveit_configs_pkg. Key files:
config/robot_arm.srdf: planning groups, end-effectorsconfig/joint_limits.yaml: override URDF limits if neededconfig/kinematics.yaml: kinematic solver (e.g., KDL, CHOMP)launch/move_group.launch.py: launch MoveIt² node
To launch from your Pi:
ros2 launch your_arm_moveit_config move_group.launch.py
3.4. Test Motion Planning on Raspberry Pi
Run rviz2 with MoveIt² plugin. If your robot is simulated, use joint_state_publisher_gui + robot_state_publisher. For real hardware:
ros2 launch your_arm_moveit_config move_group.launch.py
ros2 launch your_arm_moveit_config moveit_rviz.launch.py
Try a simple Python planning script:
import rclpy
from moveit_msgs.action import MoveGroup
from rclpy.action import ActionClient
class SimplePlanner(Node):
def __init__(self):
super().__init__('simple_planner')
self._action_client = ActionClient(self, MoveGroup, 'move_group')
self.get_logger().info('Waiting for action server...')
self._action_client.wait_for_server()
def plan_to_pose(self):
goal_msg = MoveGroup.Goal()
# Set goal state, goal pose, etc.
self._action_client.send_goal_async(goal_msg)
def main(args=None):
rclpy.init(args=args)
node = SimplePlanner()
node.plan_to_pose()
rclpy.spin(node)
4. Common Pitfalls & Pro Tips
⚠️ Memory Limits on Raspberry Pi
MoveIt² can be memory-intensive, especially with collision checking and motion planning. Pro tip: Disable collision checks temporarily during development, use KDL instead of CHOMP for fast (but less robust) planning, and consider ros2_control with real-time priority.
🚀 Calibration Matters
For accurate motion, calibrate your joint encoders or potentiometers. If using stepper motors, track homing with ros2_control’s home interface. Use ros2 run tf2_tools view_frames to verify your transforms.
🔌 Real-Time Performance Tips
For smooth motion on a Pi, use librviz with minimal window resizing, pre-load collision maps, and consider offloading trajectory smoothing to a companion microcontroller (e.g., Teensy or ESP32 for low-level PWM).
5. Testing the Full Stack
Once everything is in place, run a full integration test:
- Start hardware interface:
ros2 launch your_arm_hardware arm_hardware.launch.py - Launch MoveIt²:
ros2 launch your_arm_moveit_config move_group.launch.py - Launch RViz:
ros2 launch your_arm_moveit_config moveit_rviz.launch.py - Test in RViz: “Plan” a Cartesian motion → “Execute” on hardware
Monitor for joint feedback and execution errors:
ros2 topic echo /joint_states
6. Going Further: Advanced Features
Now that the core integration works, explore:
- MoveIt Servo: Real-time teleoperation or sensor-based collision mitigation (e.g., via lidar or depth camera)
- MoveIt Task Constructor: Build multi-stage tasks (pick-place-rotate) as modular components
- Web-based UI: Use
ros2weborros2_web_visualizerto monitor from a tablet - Precision tuning: Tune PID loops in
hardware_interfacefor smoother motion
7. Conclusion
Integrating a 3D-printed open-source arm with ROS 2 and MoveIt² gives you the full power of industrial-grade motion planning—without the cost or complexity. The Raspberry Pi, once considered too weak for ROS 2 heavy lifting, now handles real-time trajectory planning with careful tuning. Every joint you calibrate, every URDF link you refine, brings you closer to building robots that move, think, and interact in the real world.
Ready to print, wire, and code? Start small: one joint, one plan, one success message at a time.
Looking for the source files?
All URDF, SRDF, and launch templates for the OpenRovas Arm and Roboteq Arm are on GitHub—MIT licensed, community-driven.
Comments
Post a Comment