How to Tune PID Controller Gains for Different Quadrotors in Peng
Tuning PID controller gains for different quadrotors in Peng requires editing the pid_controller section of config/quad.yaml to adjust proportional, derivative, and integral gains for both position and attitude control loops, then iterating through simulation runs while monitoring rise time, overshoot, and steady-state error.
The Peng quadrotor simulator implements a cascaded PID architecture where gains are decoupled from the core Rust logic and loaded via YAML configuration. This design allows you to stabilize diverse drone platforms—from lightweight agile racers to heavy-lift cargo vehicles—without recompiling the simulator source code.
Peng's PID Control Architecture
At the heart of the system lies the PIDController struct defined in src/lib.rs, which maintains separate gain matrices for translational and rotational dynamics.
The PIDController Struct
According to the Peng source code in src/lib.rs (lines 21-38), the controller stores:
kpid_pos: A 3×3 matrix of proportional, derivative, and integral gains for the x, y, and z axeskpid_att: Corresponding gains for roll, pitch, and yaw- Integral error accumulators: Track cumulative position and attitude errors
- Max-integral limits: Clamp values to prevent windup (
pos_max_intandatt_max_int)
The controller computes commands through two primary methods also located in src/lib.rs:
compute_position_control(lines 58-78): Implements the position PID lawacc = Kp·e_pos + Kd·e_vel + Ki·∫e_posto generate thrust and desired orientationcompute_attitude_control(lines 84-95): Implements the attitude PID law using Euler-angle error to produce torque vectors
These methods receive the discrete time step dt derived from control_frequency defined in config/quad.yaml (lines 11-14).
Step-by-Step Tuning Workflow
Systematic tuning of PID controller gains in Peng follows a structured approach that accounts for physical platform differences.
1. Characterize the Physical Platform
Before adjusting gains, identify the quadrotor's mass, inertia, and drag coefficient under the quadrotor section of config/quad.yaml. Heavier drones require larger proportional gains to overcome inertia, while high-drag configurations need aggressive integral action to eliminate steady-state bias.
2. Establish a Baseline
The repository ships with default values (position kp ≈ 7–11, attitude kp ≈ 1.5) that provide stable flight for a standard 1kg platform. Use these as your starting reference point.
3. Tune Position Gains First
Adjust the pos_gains block in config/quad.yaml using this sequence:
- Proportional (
kp): Increase until the drone reaches setpoints with minimal steady-state error but stops before oscillation begins - Derivative (
kd): Raise afterkpto dampen overshoot and mitigate ringing - Integral (
ki): Add sparingly to eliminate residual error from drag or asymmetry; always pair with appropriatepos_max_intlimits to prevent windup
4. Tune Attitude Gains
Modify the att_gains block similarly, noting that attitude dynamics respond faster than position. Typical kp values remain lower (≈ 1.5–2.0) because rotational inertia is usually smaller than translational mass.
5. Iterate Through Simulation
Run short hover or step-response tests after each modification, monitoring:
- Rise time: How quickly error drops to 10% of initial value
- Overshoot: Should remain below 5% for most applications
- Steady-state error: Target less than 1cm for position, less than 1° for attitude
6. Verify Integral Limits
Check that integral_pos_error and integral_att_error never saturate against pos_max_int or att_max_int. If saturation occurs, either lower the gain or raise the limit.
7. Optimize Control Frequency
If the system appears choppy or unstable, increase control_frequency in the YAML file (e.g., from 200Hz to 400Hz). Higher frequencies permit finer dt steps, allowing slightly higher gains without destabilizing the discrete-time controller.
Platform-Specific Tuning Strategies
Different quadrotor configurations demand specific gain adjustments in Peng:
- Heavy platforms (≥ 2kg): Multiply
pos_gains.kpby 1.5–2× and increasepos_gains.kdproportionally to maintain damping ratios - Lightweight agile drones: Reduce
pos_gains.kpto prevent aggressive thrust spikes; increaseatt_gains.kdfor smoother orientation tracking - High-drag environments: Modestly increase
pos_gains.kiand raisepos_max_intto compensate for constant velocity bias - Low-frequency control (100Hz): Keep gains conservative (≤ 70% of 200Hz values) because the larger
dtamplifies discretization errors
Implementation Examples
Configuring Gains in YAML
Edit config/quad.yaml (lines 24-34) to define platform-specific gains:
quadrotor:
mass: 2.0
gravity: 9.81
drag_coefficient: 0.02
pid_controller:
pos_gains:
kp: [10.0, 10.0, 15.0]
kd: [3.0, 3.0, 8.0]
ki: [0.1, 0.1, 0.1]
att_gains:
kp: [2.0, 2.0, 1.2]
kd: [0.2, 0.2, 0.15]
ki: [0.0, 0.0, 0.0]
pos_max_int: [15.0, 15.0, 15.0]
att_max_int: [1.0, 1.0, 1.0]
control_frequency: 400
Instantiating the Controller in Rust
The PIDController::new constructor in src/lib.rs (lines 62-69) accepts the gain matrices loaded from configuration:
use peng_quad::{PIDController, Config};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::from_yaml("config/quad.yaml")?;
let kpid_pos = [
config.pid_controller.pos_gains.kp,
config.pid_controller.pos_gains.kd,
config.pid_controller.pos_gains.ki,
];
let kpid_att = [
config.pid_controller.att_gains.kp,
config.pid_controller.att_gains.kd,
config.pid_controller.att_gains.ki,
];
let pid = PIDController::new(
kpid_pos,
kpid_att,
config.pid_controller.pos_max_int,
config.pid_controller.att_max_int,
config.quadrotor.mass,
config.quadrotor.gravity,
);
Ok(())
}
Running the Control Loop
Integrate the controller into your simulation loop using the methods defined in src/lib.rs:
let dt = 1.0 / config.simulation.control_frequency as f32;
let (thrust, desired_orientation) = pid.compute_position_control(
&Vector3::new(0.0, 0.0, 1.0),
&Vector3::zeros(),
0.0,
&quad.position,
&quad.velocity,
dt,
);
let torque = pid.compute_attitude_control(
&desired_orientation,
&quad.orientation,
&quad.angular_velocity,
dt,
);
quad.update_dynamics_with_controls_euler(thrust, &torque);
Summary
- PID gains in Peng are defined in
config/quad.yamlunderpid_controller.pos_gainsandpid_controller.att_gains, with separate proportional, derivative, and integral values for each axis - Tuning sequence matters: establish proportional gains first, add derivative to dampen oscillations, then introduce integral action with strict limits to eliminate steady-state error
- Physical parameters including mass and drag coefficients must be updated in the same YAML file to ensure the controller accounts for platform-specific dynamics
- Control frequency directly impacts stability; higher frequencies (400Hz) support more aggressive gains than lower frequencies (100Hz)
- Source locations: The core logic resides in
src/lib.rs(PIDControllerstruct, lines 21-38; control methods, lines 58-95), while configuration parsing happens insrc/config.rs
Frequently Asked Questions
Where are the PID gains stored in Peng?
The gains are stored in the config/quad.yaml file under the pid_controller section, specifically within pos_gains and att_gains subsections. Each subsection contains arrays for kp, kd, and ki corresponding to the x/y/z axes for position and roll/pitch/yaw for attitude.
How do I prevent integral windup when tuning?
Set appropriate values for pos_max_int and att_max_int in config/quad.yaml to clamp the maximum accumulated error. If the drone exhibits oscillatory behavior after reaching steady state, reduce the integral gain or lower these limits to restrict how much error the controller can accumulate.
Should I tune position or attitude gains first?
Always tune position gains first because the attitude controller tracks orientation setpoints generated by the position loop. If the inner attitude loop is too sluggish, the outer position loop cannot achieve accurate tracking regardless of its gains. Start with attitude gains at conservative values, optimize position response, then refine attitude gains for crisp orientation tracking.
How does control frequency affect PID tuning?
The control_frequency parameter in config/quad.yaml determines the discrete time step dt passed to compute_position_control and compute_attitude_control. Lower frequencies (e.g., 100Hz) require more conservative gains because the larger dt increases discretization error and delay. When increasing control frequency from 200Hz to 400Hz, you can typically raise proportional gains by 20-30% while maintaining equivalent stability margins.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →