Cartesian impedance control of the Franka Emika Panda robotic arm with kinesthetic teaching and genetic algorithm parameter optimisation — built directly on libfranka.
Developed as part of MCT-352 Robotics, Mechatronics & Control Engineering Department, 2026.
Authors: Fida Hussain · Zain Ali Zahid · Syed Irtaza Abbas
- Overview
- Key Results
- Repository Structure
- System Architecture
- Dependencies
- Installation & Build
- Usage
- Configuration
- Results
- Known Limitations & Future Work
- Citation
- License
This project implements a Cartesian space impedance controller for the Franka Emika Panda (7-DOF) arm that allows compliant, force-aware interaction with the environment — the arm yields to external forces rather than rigidly tracking a path.
Three capabilities are integrated into a single platform:
| Module | Description |
|---|---|
| Cartesian Impedance Controller | Runs via libfranka at 1 kHz; computes joint torques from Cartesian pose error with gravity + Coriolis compensation |
| Hand-Guiding & Trajectory Replay | Operator physically moves the arm; waypoints are recorded and replayed automatically with SLERP/linear interpolation |
| GA Parameter Tuner | Genetic algorithm searches the 4D stiffness/damping space to minimise a composite tracking error objective |
All real-time control runs entirely within libfranka at 1 kHz directly on the hardware. ROS2 and multipanda_ros2 are used only for inverse kinematics via MoveIt 2 — they are not part of the torque control loop.
| Configuration | Max Error | RMS Error | Final Residual Error | Settle Time |
|---|---|---|---|---|
| Default (libfranka baseline) | 220.02 mm | 96.57 mm | 7.76 mm | > 5 s |
| Manual OAT Sweep | 183.53 mm | 76.76 mm | 4.44 mm | > 5 s |
| GA Optimised | 312.81 mm* | 71.92 mm | 3.10 mm | > 5 s |
*The higher peak error in Trial 3 is an intentional GA trade-off: the objective function prioritised steady-state convergence over transient excursion. The 60.1% reduction in final residual error and 25.5% reduction in RMS error are the practically meaningful gains for compliant manipulation tasks.
Optimised parameters: Kt = 231 N/m · Kr = 6.87 Nm/rad · Dt = 2.70 · Dr = 2.21
panda-impedance-control/
│
├── src/
│ ├── franka_waypoint_recorder.cpp # Hand-guiding, waypoint recording & trajectory replay
│ └── impedance_ga_tuner.cpp # Cartesian impedance controller + GA optimisation
│
├── config/
│ └── ga_config.yaml # All GA hyperparameters and impedance bounds (reference)
│
├── scripts/
│ ├── plot_trial_results.py # Per-trial position/error plots (reproduces report figures)
│ ├── plot_ga_convergence.py # GA fitness convergence across generations
│ └── compare_trials.py # Side-by-side metric comparison across all trials
│
├── results/
│ └── csv_logs/ # Place your recorded trial CSV logs here
│
├── report/
│ └── MCT352_Panda_Impedance_Control_Report.pdf # Full project report
│
├── docs/
│ └── architecture.md # Detailed system architecture notes
│
├── LICENSE
├── .gitignore
└── README.md
Note: There is no
CMakeLists.txtat the repo root. The source files slot into libfranka's own build system — see Installation & Build below.
┌─────────────────────────────────────────┐
│ Operator Interface Layer │
│ (keyboard, waypoint mgmt, GA loop) │
└────────────────┬────────────────────────┘
│ well-defined interfaces
┌────────────────▼────────────────────────┐
│ Control Layer │
│ Cartesian Impedance Controller │ ← 1 kHz real-time (libfranka)
│ Hand-Guiding Module (zero stiffness) │
│ Forward Kinematics + Jacobian │
└────────────────┬────────────────────────┘
│ joint torque commands / state
┌────────────────▼────────────────────────┐
│ Hardware Interface Layer │
│ libfranka → Franka Control Interface │ ← Panda arm (physical hardware)
└─────────────────────────────────────────┘
ROS2 + multipanda_ros2 + MoveIt 2
→ Used separately for inverse kinematics only
→ Not part of the real-time torque control loop
| Dependency | Version | Notes |
|---|---|---|
| Ubuntu | 22.04 LTS | Real-time kernel patch recommended |
| libfranka | ≥ 0.10.0 | Core dependency — provided via multipanda_ros2 setup |
| multipanda_ros2 | humble branch | Sets up the full environment including libfranka |
| ROS2 | Humble Hawksbill | Required by multipanda_ros2 for IK |
| Eigen3 | ≥ 3.3 | sudo apt install libeigen3-dev |
| Python | ≥ 3.10 | For analysis scripts only |
| Python libs | — | numpy, pandas, matplotlib |
Franka firmware: Developed and tested on firmware 4.2.2. Firmware 4.2.0 has known compatibility issues with the compiler stack — update via Franka World if needed.
Follow the setup instructions in the multipanda_ros2 repository (humble branch). This gives you the ~/source_code/libfranka directory used in all steps below.
git clone -b humble https://github.com/tenfoldpaper/multipanda_ros2.gitgit clone https://github.com/fida-121/panda_impedance_control.gitcp panda_impedance_control/src/franka_waypoint_recorder.cpp ~/source_code/libfranka/examples/
cp panda_impedance_control/src/impedance_ga_tuner.cpp ~/source_code/libfranka/examples/cd ~/source_code/libfranka/examples
nano CMakeLists.txtFind the block where existing examples are listed and add both entries in the same format as the others:
add_franka_example(franka_waypoint_recorder franka_waypoint_recorder.cpp)
add_franka_example(impedance_ga_tuner impedance_ga_tuner.cpp)Save and exit (Ctrl+O → Enter → Ctrl+X).
cd ~/source_code/libfranka/build
cmake ..
make -j4The compiled binaries will be at ~/source_code/libfranka/build/examples/.
pip3 install numpy pandas matplotlibMake sure the Panda arm is powered on, FCI is enabled in Desk, and the robot is in a safe starting configuration before running anything.
All executables are run from ~/source_code/libfranka/build/examples/:
cd ~/source_code/libfranka/build/examplesRenders the arm back-drivable with gravity + Coriolis compensation active. Move the arm freely and save poses as waypoints via the keyboard.
./franka_waypoint_recorder <robot-ip>Keyboard interface during guiding:
| Key | Action |
|---|---|
s |
Save current end-effector pose as a waypoint |
p |
Finish recording and prepare for replay |
↑ (Up arrow) |
Open gripper |
↓ (Down arrow) |
Close gripper / grasp object |
q |
Quit and return arm to safe configuration |
Do not press the physical flange button while in FCI mode — it conflicts with the external control interface and will halt the arm. Use the keyboard interface above for all interactions.
After pressing p to finish recording, the program transitions to replay mode:
Press [Enter] to start playback, or [q]+Enter to quit:
- Press Enter to execute the recorded trajectory
- Press Enter again after completion to replay once more
- Press q + Enter to exit
Waypoints are replayed with linear interpolation in position and SLERP in orientation for smooth, continuous reference trajectories.
Runs the full two-phase tuning pipeline: one-at-a-time manual sweep followed by genetic algorithm search over the complete 4D parameter space.
./impedance_ga_tuner <robot-ip>The arm executes the standardised test motion once per candidate parameter set per generation. Results are logged to a CSV file at every generation and the optimised parameter set θ* is printed to terminal on completion.
To visualise GA convergence after a run:
python3 ~/panda_impedance_control/scripts/plot_ga_convergence.py <path-to-ga-csv>All GA hyperparameters, parameter search bounds, safety thresholds, and fitness weights are documented in config/ga_config.yaml for reference, and implemented in the GAConfig struct inside impedance_ga_tuner.cpp.
To change settings, edit GAConfig in impedance_ga_tuner.cpp and rebuild with make -j4.
Key values:
ga:
population_size: 12
max_generations: 15
crossover_rate: 0.85
mutation_rate: 0.15
blx_alpha: 0.3
tournament_k: 3
elite_count: 2
parameter_bounds:
kt: [100.0, 250.0] # Translational stiffness (N/m)
kr: [5.0, 20.0] # Rotational stiffness (Nm/rad)
dt: [1.5, 2.7] # Translational damping ratio coefficient
dr: [1.5, 2.7] # Rotational damping ratio coefficient
safety:
min_damping_ratio: 0.65 # Rejects underdamped candidates (zeta = D/2)
max_torque_norm: 50.0 # Nm — hard abort
max_position_error_abort: 0.55 # m above initial displacement
fitness_weights:
w_rms: 1.0 # RMS tracking error
w_max: 0.5 # Peak error
w_settle: 0.3 # Settling time
w_osc: 0.2 # Oscillation penalty
w_overshoot: 0.3 # Overshoot penalty| File | Description |
|---|---|
report/MCT352_Panda_Impedance_Control_Report.pdf |
Full project report with derivations, figures, and code listings |
results/csv_logs/ |
Place raw GA trial CSV logs here for use with the analysis scripts |
scripts/plot_trial_results.py |
Reproduces the 4-panel trial figures from the report |
scripts/plot_ga_convergence.py |
Plots GA fitness across generations |
scripts/compare_trials.py |
Bar chart comparison of all three trial configurations |
- Settle time (1 mm threshold): Not achieved within the 5 s trial window across any configuration. This is a structural property of impedance control at these stiffness levels, not an implementation defect.
- IK trajectory jerk: Quintic polynomial interpolation reduced but did not eliminate inter-waypoint jerks. Continuous spline planning across all waypoints simultaneously is the recommended next step.
- Planned extensions:
- Bayesian optimisation as a more sample-efficient alternative to GA
- Online replanning under external contact disturbances
- GUI for hand-guiding and GA hyperparameter control without recompilation
If you use this work in your research, please cite:
@misc{hussain2026panda,
author = {Fida Hussain and Zain Ali Zahid and Syed Irtaza Abbas},
title = {Cartesian Impedance Control of the Franka Emika Panda with
Kinesthetic Teaching and Genetic Algorithm Optimisation},
year = {2026},
howpublished = {\url{https://github.com/fida-121/panda_impedance_control}},
note = {MCT-352 Robotics Semester Project, Mechatronics \& Control
Engineering Department}
}This project is licensed under the Apache License 2.0 — see LICENSE for details.
This project builds upon the libfranka Cartesian impedance control example (Apache 2.0) and the multipanda_ros2 bridge. Please respect the licenses of those dependencies.
