A simple, user-friendly Python physics simulation library built on Manim.
Action lets you describe classical mechanical systems using physical components and connections, automatically derive their equations of motion, solve them numerically, and animate the resulting motion in Manim.
Build the mechanism. Define the physics. Let Action handle the equations.
- 🧩 Component-based mechanics — build systems from masses, rods, springs, and walls.
- 🌳 Branched mechanisms — model pendulum trees and other branched mechanical topologies.
- 🔗 Typed connections — connect components using
HingeandFixedconstraints. - ⚙️ Automatic equations of motion — Action constructs the system's Lagrangian from its physical configuration.
- 📐 Generalized coordinates — coordinates are automatically derived from the topology of the mechanism.
- 🧮 Numerical simulation — solve the resulting equations and cache the trajectory.
- 🎬 Manim integration — directly animate the simulated system in a normal Manim
Scene. - 🏷️ Physical labels and vectors — display velocities, accelerations, forces, and other useful quantities.
- 🎨 Customizable visualization — control the appearance of the simulation independently from its physical model.
Action is currently under active development.
For development installation:
python -m pip install -e ".[manim,test]"Once installed, Action can be imported directly:
from action import *A simple pendulum can be described without manually deriving its equations of motion:
from math import pi
from manim import Scene
from action import *
class Pendulum(Scene):
def construct(self):
with System() as system:
wall = Wall()
rod = Rod(length=2)
mass = Mass(m=1)
hinge = Hinge(wall, rod.start)
Fixed(rod.end, mass)
Gravity(g=9.81)
system.initial = {
hinge.rotation: pi / 4,
hinge.rotation.rate: 0,
}
self.add(system)
self.play(system.simulate(10))Action takes care of the rest:
- The physical components are registered with the
System. - The connections determine the system's topology.
- Generalized coordinates are generated automatically.
- The physical configuration is resolved in SI units.
- Kinetic and potential energies are constructed.
- The equations of motion are obtained.
- The system is numerically solved.
- The resulting trajectory is rendered through Manim.
The same physical model can therefore be used for both simulation and visualization.
Physical components are declared directly:
wall = Wall()
rod = Rod(length=2)
mass = Mass(m=1)Connections describe how those components interact:
Hinge(wall, rod.start)
Fixed(rod.end, mass)There is intentionally no generic connect() method. Connections have physical meaning, so Action represents them explicitly.
Action is not limited to simple chains.
A rod can support another rod, allowing systems such as:
- double pendulums
- pendulum trees
- branched mechanisms
- mechanisms with multiple masses
- systems where different branches contain different components
The topology of the mechanism determines its generalized coordinates.
For example, a hinged rod can introduce an angular coordinate, while a free mass can contribute translational coordinates.
This means you can describe increasingly complex mechanisms without manually constructing a coordinate system for every component.
Springs are first-class physical components.
with System() as system:
wall = Wall()
spring = Spring(k=10, rest_length=1)
mass = Mass(m=1)
Fixed(wall, spring.start)
Fixed(spring.end, mass)
system.initial = {
spring.extension: 0.3,
spring.extension.rate: 0,
}
self.add(system)
self.play(system.simulate(10))Spring extensions are derived from the physical geometry of their endpoints and contribute elastic potential energy to the system.
Multiple springs can act on the same mass:
with System() as system:
left = Wall()
right = Wall()
spring_left = Spring(k=10, rest_length=1)
spring_right = Spring(k=10, rest_length=1)
mass = Mass(m=1)
Fixed(left, spring_left.start)
Fixed(spring_left.end, mass)
Fixed(mass, spring_right.start)
Fixed(spring_right.end, right)Action checks that spring extensions and endpoint geometry remain physically consistent.
Action can display trajectory-driven physical vectors directly on the simulated system.
Velocity(mass)
Acceleration(mass)
Force(mass)By default:
- Velocity is blue
- Acceleration is red
- Force is green
Colors can be customized using normal Manim colors:
Velocity(mass, color=YELLOW)
Acceleration(mass, color=PURPLE)
Force(mass, color=ORANGE)These overlays are purely visual — they do not modify the physical model.
Action separates the physical model from its visual representation.
Physical dimensions are expressed in the same coordinate system as the simulation and are transformed into suitable Manim dimensions only when the system is rendered.
This means that changing the visual scale does not change the underlying physics.
Visual appearance can be customized through VisualStyle:
style = VisualStyle(
mass_radius=0.14,
rod_width=0.035,
spring_amplitude=0.08,
)
with System(visual_style=style) as system:
...This allows physical dimensions, colors, label sizes, vector appearance, and other visualization settings to be customized without modifying the physics implementation.
At its core, Action follows a simple pipeline:
Physical components
│
▼
Typed connections
│
▼
Mechanical topology
│
▼
Generalized coordinates
│
▼
Physical configuration
│
├───────────────┐
▼ ▼
Kinetic energy Potential energy
│ │
└───────┬───────┘
▼
Lagrangian
│
▼
Equations of motion
│
▼
Numerical solution
│
▼
Cached trajectory
│
▼
Manim
The important design principle is that the physical configuration is the source of truth.
The same configuration is used to:
- determine component positions,
- construct energies,
- generate equations of motion,
- solve the dynamics,
- and construct the visualization.
This keeps the simulation and animation synchronized by construction.
The repository contains several complete examples:
examples/
├── pendulum.py
├── double_pendulum.py
├── spring_mass.py
├── mass_between_springs.py
├── coupled_springs.py
├── rod_spring.py
├── rod_two_springs.py
└── vectors.py
Render an example using Manim:
manim -pql examples/pendulum.py PendulumFor example:
manim -pql examples/double_pendulum.py DoublePendulumRun the test suite with:
python -m pytestAction is currently evolving toward a more general and expressive mechanical modeling framework. Contributions, ideas, bug reports, and experiments are welcome.
Action is still in its early stages. Areas of ongoing development include:
- More mechanical components
- More connection types
- More complex branched mechanisms
- Improved visualization customization
- Better documentation and examples
- Expanded automated testing
- Performance improvements for larger systems
- Stable public API and PyPI release
Contributions are welcome!
If you have an idea for a new component, connection type, visualization feature, or physics capability, feel free to open an issue or pull request.
When contributing, please try to keep the distinction between:
physical model → simulation → visualization
clear. This separation is one of the core design principles of Action.
Action is open-source software. See LICENSE for the full license.
Action is built on top of Manim, the Python framework for creating mathematical animations.
Action
Simulate mechanics. Visualize the motion.