-
-
Notifications
You must be signed in to change notification settings - Fork 40
Animation and movies
Live animation and movie recording are two independent things in bdsim:
-
Live animation (
animation=True,+a) updates the display window during a run, one frame per integration step or clock tick. -
Movie recording (
movie=on a block, or--movies DIR/-m DIRglobally) writes MP4 output at a steady frame rate, and works whether or not you're watching a live window — including fully headless, on a server with no display at all.
Two ways to enable it:
-
Globally:
--movies DIR/-m DIR(default.if no directory is given) automatically assigns a movie file to every graphics block in the diagram, named after the block. -
Per block: any
GraphicsBlocksubclass (SCOPE,SCOPEXY,ANIMATION, ...) acceptsmovie="filename.mp4"directly, eg.bd.ANIMATION(init=..., update=..., movie="out.mp4").
Some things worth knowing:
- Requires
ffmpegonPATH— bdsim raises a clear error ("cannot save movie, please install ffmpeg") rather than failing silently if it's missing. - Frame rate follows the
animation_rateoption (default 20 Hz, see Runtime options). If movies are enabled and you haven't setdtexplicitly, bdsim sets it to1/animation_rateautomatically so output samples land cleanly on the frame grid. This same rate also paces how often the integrator gets interrupted and restarted — see Time stepping for the mechanism and why a needlessly high rate costs real integrator overhead. -
--movies/movie=implygraphics=True— they can't be combined with-g/graphics=False. - Pass
timestamp=Trueto any graphics block to burn the simulation time into each rendered frame.
You don't need a live animated window to record a movie — useful on a server with no display, or in
CI. Set a non-interactive Matplotlib backend (backend="Agg" in code, --backend Agg on the command
line, or MPLBACKEND=Agg in the environment) and bdsim drives the frame-grab loop at
animation_rate even with animation=False:
import bdsim
sim = bdsim.BDSim(backend="Agg", animation=False, hold=False)
bd = sim.blockdiagram()
# ... build the diagram ...
anim = bd.ANIMATION(init=my_init, update=my_update, movie="out.mp4")
# ... connect it ...
bd.compile()
sim.run(bd, T=10, dt=1 / 20)
bd.done() # flush and finalize the movie writerHeadless movie recording without a live window — exactly this pattern — was broken until PR #36 (thanks, @PhotonicVelocity), which also fixed several related frame-timing bugs: a missing t=0 frame, duplicated/missing timestamps around long runs, and an MP4 frame-rate mismatch that made a 5 s simulation render as a 6.9 s video. If movie output looks off in timing or frame count, make sure that fix has landed.
Don't use BDSIM_NO_GRAPHICS=1 for this — see Environment variables. That
variable unconditionally forces graphics=False, animation=False and movies=None, killing movie
output along with everything else. It's for CI runs that want no graphical output whatsoever, not for
headless movie generation — use backend="Agg" instead.
examples/cartpole.py drives an ANIMATION block with a custom init/update pair — a cart-pole
rendered with Matplotlib patches and transforms. See it running here: cart-pole animation
video. To render a movie
instead of (or as well as) watching it live, add movie="cartpole.mp4" to its ANIMATION(...) call.
- Notebook animation for how live animation and the notebook-specific display path work.
-
Graphics blocks for
GraphicsBlockinternals (_start_movie, lifecycle hooks) if you're writing a custom animated block. - Runtime options for the full CLI options table.
Copyright (c) Peter Corke 2020-
- Home
- API reference (Sphinx)
- Block catalog
- Control Systems Magazine article
- Adding blocks to your model
- Block path
- Connecting blocks
- Compiling
- Running
- Watching a simulation variable
- Simulation results
- Runtime options
- Environment variables
- Discrete-time blocks
- Subsystems
- Figures
- Notebook animation
- Animation and movies
- PID control
- Coding patterns
- Block methods and attributes
- Time stepping: integration, animation & events
- Blocks, wires and plugs
- Graphics blocks
- Evaluation
- Runtimes and simulator state
- Creating a new block
- Related packages
Under development on feat/realtime branch, planned for release before end of 2026.