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-effectors
  • config/joint_limits.yaml: override URDF limits if needed
  • config/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:

  1. Start hardware interface: ros2 launch your_arm_hardware arm_hardware.launch.py
  2. Launch MoveIt²: ros2 launch your_arm_moveit_config move_group.launch.py
  3. Launch RViz: ros2 launch your_arm_moveit_config moveit_rviz.launch.py
  4. 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 ros2web or ros2_web_visualizer to monitor from a tablet
  • Precision tuning: Tune PID loops in hardware_interface for 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.

© 2024 Open Motion Robotics. Built for ROS 2 Humble & MoveIt².

Designed with attention to clarity, speed, and reproducibility.

Comments

Popular posts from this blog

Guide to Voice-Activated Desktop Assistant: Integrating an Offline Speech Recognition Module with an STM32 Robotic Arm