- Project Overview & Demo
- System Architecture
- Key Features
- PI-Bot control center (GUI)
- Digital Twin
- Hardware & Wiring
- Quick start
- Challenges & Solutions
robotic_arm_project/
├── docs/
├── src/
├──── move_it_services/ # Custom Srv/Msg definitions (e.g. MoveToXYZ)
├──── my_robot_interfaces/ # Custom interfaces used in multiple nodes
├──── pca9685_servo_controller/ # Control the physical servos
├──── potentiometer_reader/ # Read out potentiometer values
├──── robot_controller/ # MoveIt2 controller config
├──── robot_description/ # URDF & meshes
├──── robot_fk/ # Forward kinematic calculations
├──── robot_gui/ # Pibot GUI
├──── robot_moveit/ # MoveIt2 configuration & SRDF
└── README.md # Documentation
The PI-Bot is a custom-engineered, 3D printed, 3-DOF robotic arm designed as a full-stack robotics project. It demonstrates the seamless integration of distributed software systems, real-time hardware interaction, and motion planning.
Core Motivation & Software Focus The primary goal of this project was to master the software stack, specifically to understand MoveIt and motion planning architectures from the ground up. To bridge the gap between theory and reality, I implemented the system using 3D-printed parts and budget-friendly servos.
While this accessible hardware introduces some mechanical imprecision, it served its purpose as a verification platform for the software. Future iterations will focus on hardware refinement to improve physical accuracy, though the core of this project remains a deep dive into robotics software engineering.
The project covers:
- Mechanical Design in CAD: 3-axis manipulator with gripper.
- Embedded Control: Custom ROS2 nodes on a Raspberry Pi 4 for PWM actuation and ADC sensor readout.
- Advanced Middleware: MoveIt2 for path planning and a synchronized Digital Twin.
- UI: A PySide6/Qt GUI for orchestration.
The PI-Bot is built on a distributed ROS2 architecture, separating high-level logic from hardware-near execution to ensure modularity and system stability.
Figure: High-level overview of the distributed control loop and node communication.
The workstation acts as the "Brain" of the system, running computationally intensive nodes:
- GUI-Node (PySide6): The central hub for user interaction. It subscribes to
/poti_anglesfor manual input and/fk_infofor real-time monitoring of the end-effector position. It orchestrates movements by calling the MoveIt2 Action Client and controls if the robot is in hardware or simulation mode. - MoveIt2 Action Client: Handles trajectory planning and inverse kinematics (IK). Once a path is planned, it publishes the trajectory points to the
/joint_statestopic. - Forward Kinematics Node: A dedicated node that processes joint angles to calculate the end-effector's XYZ position, providing feedback to the GUI.
- RViz Digital Twin: Subscribes to
/joint_statesto provide a real-time 3D visualization of the robot's physical state.
The Pi 4 serves as the bridge between the digital ROS2 environment and the physical hardware:
- Potentiometer Node: Interfaces with the ADS7830 ADC via I2C. It reads analog signals from the three potentiometers, processes them, and publishes the values to the
/poti_anglestopic. - Servo Controller Node: Subscribes to the
/joint_statesand/robot_modetopics from the main PC and converts these states into I2C commands for the PCA9685 Servo Driver. When the robot is in hardware mode, the driver generates PWM signals to control the four servo motors.
- ROS2 Middleware: All communication between the PC and the Raspberry Pi is handled over the local network using a shared ROS_DOMAIN_ID.
-
Multi-Modal Hybrid Control: The PI-Bot offers four distinct ways to interact with the hardware:
- Joint-Space Control: Precise manipulation of individual axes via interactive GUI sliders (0-180°).
- Cartesian-Space Control: Users can input target XYZ-coordinates (in mm). The system calls a custom
MoveToXYZservice to plan and execute the motion. - Hardware-in-the-Loop (HIL): Real-time physical analog potentiometers for intuitive manual positioning.
- Interactive Planning (MoveIt2): Full integration with RViz, allowing users to move the robot via Drag & Drop (Interactive Markers).
-
Real-time State Sync: The
sync_sliders_to_movementlogic continuously updates the GUI sliders to always match the actual hardware state, preventing jumps when switching control modes. -
Teach-In Sequence Recorder: Store specific positions of the end-effector, or gripper in a table and execute them as a complex motion sequence.
-
Asynchronous Processing: Multi-threaded Python/Qt implementation to keep the UI responsive during long-running trajectory executions and service/action calls.
The PI-Bot Control Center is a PySide6 (Qt)-based HMI providing centralized control, state monitoring, motion teaching, and direct servo manipulation via sliders.
Figure: The PI-Bot Control Center showing a programmed stacking sequence.
- Live Feedback: Displays the end-effector’s real-time XYZ coordinates (mm), computed by the Forward Kinematics (FK) node.
- Target Input: Users can enter desired Cartesian coordinates. Clicking “Send desired position” invokes MoveIt2 Inverse Kinematics (IK) to plan and execute the motion.
- Interactive Sliders: Direct control of all three joints and the gripper.
- Bi-directional Sync: Sliders continuously reflect the robot’s physical state, including movements from external potentiometers or those triggered by the “Send Desired Position” or “Sequence” functionality.
- Sequence Recorder:
- “Save Position” stores the current spatial position.
- “Save Grip” stores the current gripper state.
- Automation Workflow:
- The table holds command types:
MOVE→ spatial targetGRIPPER→ aperture state
- The table holds command types:
- Configuration:
- Pressing Delete removes the currently selected (orange-highlighted) row.
- Execution:
- Pressing “Send” runs the sequence from top to bottom, enabling autonomous repetitive tasks (e.g., stacking or sorting).
- Robot Mode:
- Simulation Mode → Digital twin visualization
- Hardware Mode → Physical servo actuation
- Control Mode:
- GUI Control
- Potentiometer Control (Hardware-in-the-Loop)
A core feature of the PI-Bot is the implementation of a Digital Twin. This virtual mirror ensures that every movement of the physical hardware is precisely reflected in the simulation environment (RViz) and vice versa.
Figure: Comparison between the physical 3-DOF arm (left) and its synchronized Digital Twin in RViz (right).
Figure: Comparison between the physical 3-DOF arm (left) and its synchronized Digital Twin in RViz (right).
- URDF & Mesh Integration: The robot is defined via a custom Unified Robot Description Format (URDF), using precise meshes from my own CAD Design and joint limits derived from the Moveit config.
- State Mirroring: By subscribing to the
/joint_statestopic, therobot_state_publisherupdates the TF-tree in real-time. - Safety & Planning: Before any physical movement occurs, MoveIt2 uses the Digital Twin to perform collision checking and trajectory validation, ensuring safe operation in the physical workspace.
- Remote Monitoring: Through the distributed architecture, the Digital Twin allows for full remote monitoring of the robot's status over the network without needing a direct line of sight to the hardware.
| Component | Quantity | Interface | Description |
|---|---|---|---|
| Raspberry Pi 4 (4GB) | 1 | Network/I2C | Main distributed controller node |
| ADS7830 ADC | 1 | I2C (0x48) | 8-channel 8-bit ADC for potentiometer readout |
| PCA9685 Driver | 1 | I2C (0x40) | 16-channel PWM controller for servos |
| MZ996 Servos | 2 | PWM | High-torque servos for the base and the first arm |
| 9G Micro Servo | 2 | PWM | Lightweight servo for the gripper mechanism and upper arm |
| Potentiometers | 3 | Analog | 10k Ohm linear potentiometers for HIL control |
| Power Supply | 1 | DC | External 5V/10A supply for Servo Driver |
Figure: Visual wiring overview.
Figure: Physical hardware setup.
Figure: Visual wiring schematic.
- I2C Bus Management: Both the ADS7830 (ADC) and the PCA9685 (PWM Driver) share the same I2C bus using unique hardware addresses (
0x48and0x40). This keeps the wiring simple and modular. - External Power Architecture: The Raspberry Pi alone cannot provide enough current for four servos, especially during high-torque startup. I implemented an external 5V/10A power supply connected via the PCA9685's power terminal
- Sensor Precision: The ADS7830 provides 8-bit resolution (0–255). Mapping 255 steps to the 180° range of the servos results in a precision of ~0.7° per step, which is more than sufficient for smooth manual manipulation via potentiometers.
- Signal Integrity & Motion Smoothing: To mitigate signal noise and prevent mechanical jitter, I implemented an Exponential Smoothing Filter (Low-pass) within the Servo Controller node. This ensures fluid joint transitions and protects the hardware from abrupt accelerations.
This project is developed and tested on Ubuntu 24.04 (Noble Numbat).
- Control Station (PC) – Runs GUI, MoveIt 2, and the Digital Twin in RViz
- Robot Hardware (Raspberry Pi) – Reading of the Potentiometers & controlling the servos
- OS: Ubuntu 24.04 (Noble Numbat)
- ROS 2 Jazzy: Installed -> https://docs.ros.org/en/jazzy/Installation.html
- Python-Version: 3.12
- Network:
- Both devices must be in the same network
ROS_DOMAIN_IDmust match on both machines
Before setting up the workspace, you must install the ROS 2 build tools (colcon), the dependency manager (rosdep) and some python tools.
# Install colcon, rosdep, and python tools
sudo apt update
sudo apt install python3-colcon-common-extensions python3-rosdep python3-pip -ysudo rosdep init
rosdep updateThe main PC can operate independently, allowing you to run the GUI, RViz, and MoveIt without connecting to the physical robot. In this mode, no hardware interaction is available, but the robot model in RViz can still be fully controlled through the GUI and MoveIt for simulation and testing.
1. Clone the repository
git clone https://github.com/BrenzingerLuca/robotic_arm_project.git
cd robotic_arm_project2. Python Environment Setup
Important: Virtual environments often cause path conflicts between ROS 2 and PySide6. To ensure seamless library discovery and communication, install requirements globally using the --break-system-packages flag instead of a venv.
pip install -r requirements.txt --break-system-packages3. Install ROS 2 Dependencies
# 1. Source the global ROS 2 installation
source /opt/ros/jazzy/setup.bash
# 2. Install project-specific dependencies
rosdep install --from-paths src --ignore-src -r -y4. Build and Source
# Build the project
colcon build --symlink-install
# Source the local workspace
source install/setup.bash5. Launch
ros2 launch robot_gui pibot_gui.launch.pyAfter launching, the robot displayed in RViz can be controlled using the GUI and MoveIt, enabling motion planning and visualization without requiring the physical hardware. Known issue: On the first launch RViz might fail to update the robot's pose. If the sliders have no effect, restart the program (Ctrl+C and relaunch).
This step is only required if the necessary hardware is available. However, for completeness, the full startup procedure is documented below.
The steps are the same as for the Main-PC but the launch file is different.
Launch
ros2 launch pca9685_servo_controller raspi.launch.pyThese packages provide access to the I²C bus (smbus2) and the PCA9685 PWM controller used for driving the servos.
Note: for this to work the I2C-Bus has to be activated and needs to be accessible.
Building the PI-Bot as a solo project involved several technical hurdles. Below are the key challenges encountered during development and the engineering decisions made to resolve them:
- Challenge: Initial tests showed significant servo jitter and occasional system resets when moving multiple joints simultaneously.
- Solution:
- Hardware: Offloaded PWM generation to a dedicated PCA9685 controller to ensure stable timing independent of the Raspberry Pi's CPU load.
- Power: Implemented a separate external 5V/10A power rail for the servos to prevent voltage drops on the Pi's logic board during high-torque movements.
- Software: Integrated an Exponential Smoothing filter (digital low-pass) in the
ServoControllernode to clean up noisy analog signals from the potentiometers.
- Challenge: When switching back to GUI control after using the physical potentiometers or running an automated sequence, the robot would "jump" abruptly to the last stored slider position.
- Solution: Developed the
sync_sliders_to_movementlogic. This function continuously synchronizes the GUI slider positions with the actual hardware joint states. This ensures a seamless handover between different control modes, preventing sudden mechanical stress or dangerous movements.
- Challenge: ROS2 service calls and action goals are blocking by nature. Running them in the same thread as the GUI would cause the interface to freeze during trajectory planning or robot execution.
- Solution: Integrated the ROS2 spin-loop asynchronously into the PySide6 event loop using a
QTimer. By utilizing non-blocking Action Clients andadd_done_callbackfunctions, the GUI remains fully responsive and interactive while the PI-Bot is planning or executing complex trajectories.
