Simulation Run Modes¶
SimulationTimingConfig defines rates and time intervals. SimulationRunConfig
defines how an externally stepped loop relates those intervals to wall time.
The supported run modes are:
Mode |
Rendering |
Wall-clock wait |
Catch-up |
Primary use |
|---|---|---|---|---|
|
Disabled |
No |
No |
RL training and benchmarks |
|
Offscreen, on request |
No |
No |
Image capture, evaluation, and datasets |
|
Human window |
Yes |
No |
Wall-clock-paced policy playback (real-time pace) |
Wall-clock wait means that a step finishing faster than its configured
step_dt waits for the remaining real-world time. Catch-up means executing
multiple steps after a delay to recover the difference between simulation time
and wall-clock time. PACED waits when it is ahead but does not catch up when it
falls behind.
Create an explicit policy with:
run_config = ke.SimulationRunConfig(mode="paced")
KELab defaults¶
DirectRLEnv chooses a mode from Gym’s render_mode when no explicit
run_config is supplied:
render_mode=None -> HEADLESS_FAST
render_mode="human" -> PACED
render_mode="rgb_array" -> OFFSCREEN_FAST
Each mode has one rendering configuration. HEADLESS_FAST requires
render_mode=None, OFFSCREEN_FAST requires render_mode="rgb_array", and
PACED requires render_mode="human". Human rendering is performed
automatically after each reset and environment step. RGB array rendering
occurs without wall-clock waiting when the caller invokes env.render().
PACED renders per environment step, not per physics substep:
environment step
├─ apply action
├─ physics step x decimation
├─ observations, rewards, termination, and reset
├─ render latest state
└─ wait until step_dt has elapsed
The environment rates are:
physics_hz = 1 / sim.dt
step_dt = sim.dt * decimation
step_hz = control_hz = 1 / step_dt
Current task examples:
Task |
Physics rate |
Decimation |
PACED target |
|---|---|---|---|
|
120 Hz |
2 |
60 Hz |
|
1000 Hz |
20 |
50 Hz |
SimulationPacer waits only when processing finishes ahead of the next
deadline. If policy inference, physics, or rendering exceeds step_dt, the
loop does not issue multiple catch-up steps; playback becomes slower than wall
time. This matches the MimicKit-style playback behavior and avoids catch-up
bursts in an externally stepped loop.
Native App scheduling¶
SimulationRunConfig does not select the native App scheduler. App.start()
uses FixedStepClock, which accumulates wall time and may invoke
fixed_update() zero or more times per rendered frame. This is appropriate for
interactive simulations whose physics should remain independent of rendering.
Do not use SimulationPacer inside an App fixed_update() callback. Keep App
physics in fixed_update() and let FixedStepClock schedule it.
renderFrameOnce() is supported for manually driven rendering. Despite its
name, it currently processes input and advances App frame scheduling in
addition to drawing. Do not treat it as a render-only function or call it from
inside fixed_update().