# How to Integrate RK4 vs Euler for Quadrotor Dynamics in Peng

> Compare RK4 vs Euler integration for quadrotor dynamics in the Peng simulator. Learn how to select and implement these methods for accurate state propagation in your projects.

- Repository: [Yang Zhou/peng](https://github.com/makeecat/peng)
- Tags: deep-dive
- Published: 2026-03-06

---

**Peng supports both explicit Euler and fourth-order Runge-Kutta (RK4) integration for quadrotor state propagation, selectable via boolean configuration flags in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs) that dispatch to either `update_dynamics_with_controls_euler` or `update_dynamics_with_controls_rk4` defined in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs).**

The `makeecat/peng` repository provides a Rust-based quadrotor simulator that lets you swap numerical integrators without refactoring physics code. Configuring these methods allows you to trade computational speed for integration accuracy depending on your simulation step size and real-time constraints.

## Understanding the Integration Methods

Peng implements two distinct numerical integrators for the `Quadrotor` state update, both residing in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs) and accepting identical control inputs.

**Euler integration** implements a first-order explicit step: `state_{n+1} = state_n + \dot state·Δt`. Found at lines 85‑100 in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs), this method requires minimal computation and is sufficient for high-frequency real-time loops or coarse-grained testing when Δt ≤ 1 ms.

**RK4 integration** implements the classic fourth-order Runge-Kutta algorithm at lines 203‑252 in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs). It evaluates the state derivative four times per step (`k1` through `k4`), combining them as `state_{n+1} = state_n + (Δt/6)*(k1 + 2k2 + 2k3 + k4)`. This yields significantly higher accuracy for stiff dynamics or larger step sizes, essential for trajectory optimization pipelines.

Both functions share the same signature, accepting `control_thrust: f32` and `control_torque: &Vector3<f32>`.

## Configuration Flags for Integrator Selection

The simulation behavior is governed by two boolean fields defined at lines 35‑38 in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs):

```rust
pub use_rk4_for_dynamics_control: bool,
pub use_rk4_for_dynamics_update: bool,

```

- **`use_rk4_for_dynamics_control`**: Toggles RK4 for the controlled dynamics update when thrust and torque inputs are present.
- **`use_rk4_for_dynamics_update`**: Toggles RK4 for uncontrolled state propagation when no control signal is applied.

These flags are typically read from [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml) and loaded via `Config::from_yaml`.

## Implementing the Selection Logic

The dispatch pattern appears in [`src/main.rs`](https://github.com/makeecat/peng/blob/main/src/main.rs) at lines 140‑148, where the simulation loop checks the configuration and calls the appropriate method:

```rust
if config.use_rk4_for_dynamics_control {
    quad.update_dynamics_with_controls_rk4(thrust, &torque);
} else {
    quad.update_dynamics_with_controls_euler(thrust, &torque);
}

```

This branching applies identically to the uncontrolled update path when evaluating `use_rk4_for_dynamics_update`.

## Practical Configuration Examples

### Enabling RK4 via YAML

To activate RK4 for controlled dynamics without recompiling, edit your configuration file:

```yaml

# config/quad.yaml

use_rk4_for_dynamics_control: true   # Use RK4 when applying thrust/torque

use_rk4_for_dynamics_update: false  # Use Euler for passive propagation

```

After loading the configuration, the simulation driver automatically selects the specified integrator.

### Programmatic Runtime Switching

For applications requiring dynamic selection, implement a wrapper function that accepts a boolean flag:

```rust
fn step_quad(quad: &mut Quadrotor, thrust: f32, torque: &Vector3<f32>, use_rk4: bool) {
    if use_rk4 {
        quad.update_dynamics_with_controls_rk4(thrust, torque);
    } else {
        quad.update_dynamics_with_controls_euler(thrust, torque);
    }
}

```

You can toggle `use_rk4` based on command-line arguments, real-time performance metrics, or mission phase requirements.

### Complete RK4 Integration Example

The following snippet demonstrates initializing a quadrotor and performing a single RK4 step:

```rust
use nalgebra::Vector3;
use peng_quad::{Quadrotor, SimulationError};

fn main() -> Result<(), SimulationError> {
    let (dt, mass, g, drag) = (0.01, 1.3, 9.81, 0.01);
    let inertia = [0.0347563, 0.0, 0.0,
                   0.0, 0.0458929, 0.0,
                   0.0, 0.0, 0.0977];

    let mut quad = Quadrotor::new(dt, mass, g, drag, inertia)?;
    let thrust = mass * g;              // Hover thrust
    let torque = Vector3::zeros();     // No rotation

    // High-fidelity RK4 step
    quad.update_dynamics_with_controls_rk4(thrust, &torque);
    println!("Position after RK4: {:?}", quad.position);
    Ok(())
}

```

## When to Choose Each Method

Select the integrator based on your accuracy and performance constraints:

- **Use Euler** when running real-time demonstrations or when your simulation step is already very small (e.g., Δt ≤ 1 ms). The method at `src/lib.rs:85` minimizes CPU overhead for maximum frame rates.
- **Use RK4** for high-fidelity simulations, trajectory optimization, or when propagating states over larger time steps. The implementation at `src/lib.rs:203` reduces integration error accumulation in stiff rotational dynamics.

## Summary

- **Peng** implements both Euler and RK4 integrators in [`src/lib.rs`](https://github.com/makeecat/peng/blob/main/src/lib.rs) with identical function signatures for controlled updates.
- **Configuration flags** `use_rk4_for_dynamics_control` and `use_rk4_for_dynamics_update` in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs) (lines 35‑38) govern the selection without code changes.
- **Dispatch logic** in [`src/main.rs`](https://github.com/makeecat/peng/blob/main/src/main.rs) (lines 140‑148) branches between `update_dynamics_with_controls_euler` and `update_dynamics_with_controls_rk4` based on these booleans.
- **YAML configuration** in [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml) allows persistent integrator selection across simulation runs.
- **Euler** offers speed for real-time loops; **RK4** provides accuracy for larger steps or stiff dynamics.

## Frequently Asked Questions

### What is the difference between RK4 and Euler integration in Peng?

According to the `makeecat/peng` source code, **Euler** performs a single derivative evaluation per step (`state + derivative * dt`), while **RK4** performs four evaluations (`k1` through `k4`) and combines them with weighted averaging. This makes RK4 significantly more accurate for the same step size, particularly for the stiff rotational dynamics of quadrotors, at the cost of approximately four times the computation.

### How do I enable RK4 integration in the configuration?

Set `use_rk4_for_dynamics_control: true` in your YAML configuration file (e.g., [`config/quad.yaml`](https://github.com/makeecat/peng/blob/main/config/quad.yaml)). This flag is defined at line 36 in [`src/config.rs`](https://github.com/makeecat/peng/blob/main/src/config.rs) and is read by the simulation driver at startup. When true, the driver calls `update_dynamics_with_controls_rk4` instead of `update_dynamics_with_controls_euler` during the main simulation loop.

### Can I switch between integrators at runtime?

Yes, though the standard implementation reads the configuration at startup. You can implement runtime switching by passing a boolean parameter to a wrapper function that conditionally calls either `quad.update_dynamics_with_controls_rk4(thrust, &torque)` or `quad.update_dynamics_with_controls_euler(thrust, &torque)` based on your runtime conditions, as both methods are public and available on the `Quadrotor` struct.

### Which integrator should I use for real-time simulation?

For real-time applications where maintaining a high frame rate is critical, **Euler** integration is recommended, especially if your time step is small (≤ 1 ms). If you observe instability or accumulated drift in the quadrotor attitude, switch to **RK4** by setting `use_rk4_for_dynamics_control: true`, accepting the additional computational cost for improved numerical stability.