How to Configure Control Frequency vs Simulation Frequency in Peng
In Peng, you configure control frequency and simulation frequency in config/quad.yaml under the simulation section; the control loop executes every simulation_frequency / control_frequency physics steps as implemented in the main simulation loop.
Peng is an open-source quadrotor physics simulator written in Rust that decouples high-rate physics updates from lower-rate control evaluations. The relationship between these frequencies is defined in YAML configuration and enforced through integer division in the main simulation loop. Understanding how to configure control frequency vs simulation frequency in Peng allows you to balance computational load against controller responsiveness.
Understanding the Frequency Architecture
The frequency relationship is defined in the SimulationConfig struct declared in src/config.rs at lines 54–59. This structure stores both the physics update rate and the control evaluation rate as discrete integer values representing hertz.
The fields are:
control_frequency: How many times per second the PID controller computes actuator commandssimulation_frequency: How many times per second the physics engine updates the vehicle state
Where to Configure Frequencies
Peng loads runtime parameters from config/quad.yaml using the Config::from_yaml method called at startup in src/main.rs (lines 20–21). To modify the timing behavior:
- Open
config/quad.yaml - Locate the
simulationblock - Adjust
control_frequencyandsimulation_frequencyvalues
Example configuration:
simulation:
# Number of control loop executions per second (Hz)
control_frequency: 250 # e.g., 250 Hz
# Number of physics simulation steps per second (Hz)
simulation_frequency: 2000 # e.g., 2000 Hz
log_frequency: 20
duration: 90.0
How the Simulation Loop Applies Control
The main simulation loop in src/main.rs (specifically at line 38) implements a decoupled update strategy using modulo arithmetic. The control step triggers only when the current step index satisfies:
i % (config.simulation.simulation_frequency / config.simulation.control_frequency) == 0
This means the PID controller runs only once every N physics ticks, where N is the integer ratio of simulation_frequency divided by control_frequency. For example, with a 2000 Hz simulation and 250 Hz control, the controller updates every 8 physics steps.
Calculating the Step Interval Programmatically
You can verify the effective control interval in Rust:
let control_interval = config.simulation.simulation_frequency
/ config.simulation.control_frequency;
println!("Apply control every {} simulation steps", control_interval);
Logging Runtime Frequencies
To confirm the configuration at runtime:
let sim_hz = config.simulation.simulation_frequency;
let ctrl_hz = config.simulation.control_frequency;
log::info!(
"Simulation running at {} Hz, control loop at {} Hz (ratio {}:1)",
sim_hz,
ctrl_hz,
sim_hz / ctrl_hz
);
Summary
- Configuration location: Edit
control_frequencyandsimulation_frequencyinconfig/quad.yamlunder thesimulationsection - Source definitions: The
SimulationConfigstruct insrc/config.rs(lines 54–59) declares the frequency fields - Runtime logic: The main loop in
src/main.rs(line 38) applies control using modulo arithmetic with the ratiosimulation_frequency / control_frequency - Loading mechanism:
Config::from_yamlparses the YAML at startup insrc/main.rs(lines 20–21) - Ratio constraint: The control frequency should evenly divide the simulation frequency for consistent timing intervals
Frequently Asked Questions
What happens if control_frequency does not divide evenly into simulation_frequency?
When the ratio produces a remainder, the control loop executes at irregular intervals due to integer truncation in the modulo operation at line 38 of src/main.rs. For consistent controller behavior, ensure simulation_frequency % control_frequency == 0.
Can I set control_frequency higher than simulation_frequency?
Technically the YAML accepts any value, but setting control_frequency higher than simulation_frequency causes the modulo expression to evaluate to 0 or 1, resulting in control updates every step or causing division errors. The control loop should always run at or below the physics rate.
Where does Peng load the YAML configuration?
Peng loads config/quad.yaml at startup through the Config::from_yaml function call in src/main.rs at lines 20–21. Changes to the configuration file require a restart to take effect; there is no hot-reload mechanism.
How do I verify the actual frequencies at runtime?
Log the configuration values using the code snippet shown in the examples above, or inspect the initialization logs. The SimulationConfig struct values defined in src/config.rs are accessible throughout the application after loading.
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 →