Skip to main content

ROS 2 Demonstration-Based Trajectory Tracking for a 2-DOF Planar Robot

ROS 2 Python project for demonstration-trajectory replay, joint-space PD control, simulated 2-DOF planar robot dynamics, disturbance injection, and quantitative tracking-error analysis.

ROS 2 control architecture for trajectory tracking of a simulated 2-DOF planar robot

This ROS 2 project implements a compact closed-loop software pipeline for replaying a joint-space demonstration trajectory and tracking it on a simulated two-degree-of-freedom planar robot. I separated the reference publisher, feedback controller, dynamics simulator, and tracking logger into independent ROS 2 nodes so that the communication, control, disturbance, and analysis workflow can be inspected and extended clearly.

The current version was built and run with ROS 2 Jazzy. A disturbed simulation using the current public controller tuning produced 3,554 logged samples over 71.08 seconds. The quantitative results below are computed from that recorded CSV file and include the initial convergence transient.

ROS 2 control architecture

ROS 2 node and topic architecture for demonstration-based trajectory tracking
Figure 1. ROS 2 closed-loop trajectory-tracking architecture. A trajectory publisher provides desired joint states, the PD controller computes torque commands, the planar dynamics node simulates the robot response, and the tracking logger records desired and actual motion for offline analysis.

The demonstration trajectory is loaded from config/demo_trajectory.csv and published on /desired_joint_states. The controller combines this reference with feedback from /actual_joint_states and publishes the two-joint command on /control_torque. The simulation and controller both operate at 100 Hz, while the tracking logger records the desired and actual states at 50 Hz.

ROS 2 component Interface / rate
Trajectory publisher /desired_joint_states · 100 Hz
PD controller /control_torque · 100 Hz
Planar dynamics /actual_joint_states · 100 Hz
Tracking logger CSV output · 50 Hz

Feedback controller and simulated dynamics

The controller is intentionally simple: joint-position and joint-velocity errors are mapped to torque commands using a saturated PD law. The current public launch configuration uses Kp = [30, 12], Kd = [5, 1.5], and a torque limit of ±20 N·m in the simulated model.

tau = Kp * (q_des - q) + Kd * (qdot_des - qdot)

The plant is a lightweight horizontal two-link rigid-body model with viscous friction. Its simulated dynamics are evaluated numerically at 100 Hz and include optional additive joint disturbances.

M(q) qddot + C(q, qdot) + B qdot = tau + disturbance
Simulation setting Value
Proportional gains [30, 12]
Derivative gains [5, 1.5]
Torque saturation ±20 N·m
Stochastic disturbance standard deviation 0.15 N·m
Sinusoidal disturbance amplitude 0.25 N·m

The disturbance parameters belong to the simulated joint-torque model. They are not measurements of noise or external loading from a physical robot.

Measured trajectory tracking

Desired and actual joint trajectories for the simulated 2-DOF planar robot
Figure 2. Desired and actual joint trajectories during the disturbed simulation. The beginning of the recording contains the startup convergence transient. After convergence, the actual joint trajectories closely follow the repeated demonstration reference while disturbance injection remains enabled.

The final recorded dataset contains 3,554 samples spanning 71.08 seconds. Tracking metrics are calculated directly from the logged joint-position errors over the complete recording, including the startup transient.

Tracking metric Measured value
Joint 1 RMSE 0.03397 rad
Joint 2 RMSE 0.06120 rad
Mean joint-error norm 0.01873 rad
Logged samples 3,554
Recorded duration 71.08 s

These numbers describe this specific simulation run. They should not be interpreted as physical robot accuracy, a statistical robustness guarantee, or performance across untested robot models and disturbance conditions.

Tracking error under disturbance

Joint tracking errors and Euclidean error norm during the disturbed simulation
Figure 3. Joint tracking error with disturbance injection enabled. The initial transient produces the largest errors in the recording. After the controller converges, both joint errors remain much smaller around the repeating trajectory despite the simulated stochastic and sinusoidal disturbances.

The error norm is computed from the two joint-position errors at each logged sample. The relatively large initial transient is retained rather than removed from the reported RMSE values, so the quantitative summary reflects the complete saved run rather than only a selected steady portion.

Relation to learning-based robot control

This project does not implement reinforcement learning. Its role is to provide a small and readable ROS 2 control baseline that already contains the interfaces needed for later learning-based experiments: desired-state publishing, state feedback, torque commands, disturbance injection, synchronized logging, and quantitative analysis. A future residual-learning controller could therefore be added without changing the basic data flow of the package.

Scope and limitations

The current project is software- and simulation-based. The robot is represented by a simplified 2-DOF planar rigid-body model, the demonstration is a predefined CSV trajectory rather than motion recorded from a human or physical robot, and the feedback controller is PD rather than a learned policy. The project does not use Gazebo, MuJoCo, PyBullet, or a physical robotic platform.

The reported metrics come from one disturbed simulation run with the documented controller and disturbance settings. No Monte Carlo robustness study, formal stability proof, hardware experiment, or cross-distribution ROS 2 validation is claimed. The current workflow has been executed successfully with ROS 2 Jazzy.

Reproducibility

The repository contains the ROS 2 Python package, launch file, demonstration CSV, plotting scripts, rosbag helper, and tracking logger. A clean Jazzy workspace can build and launch the complete pipeline with the commands below.

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
git clone https://github.com/mhfakouri/ros2-planar-robot-trajectory-tracking.git

cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --symlink-install
source install/setup.bash

ros2 launch ros2_demo_based_tracking demo_tracking.launch.py

By default, the logger writes to /tmp/ros2_demo_tracking_log.csv. The repository's plotting script reads that CSV and computes the RMSE and mean error-norm values used in the results summary.