Pylinkage lets you design planar linkage mechanisms by specifying the motion you need. Tell it where you want a coupler point to go, and it finds mechanism dimensions automatically using classical synthesis theory (Burmester, Freudenstein) and metaheuristic optimization (PSO, differential evolution). You can then simulate, analyze, visualize, and export to DXF or STEP for fabrication.
from pylinkage.synthesis import path_generation
from pylinkage.visualizer import plot_kinematic_linkage
# "I need a coupler that passes through these four points"
result = path_generation([(0, 0), (1, 1), (2, 1), (3, 0)])
plot_kinematic_linkage(result.solutions[0])pip install pylinkage # Core only: define, simulate, and build linkages
pip install pylinkage[full] # Everything: all optional backends includedInstall only what you need:
| Extra | What it adds |
|---|---|
numba |
JIT-compiled solvers (1.5-2.5M steps/sec) |
scipy |
Differential evolution optimizer, synthesis solvers |
symbolic |
SymPy-based closed-form expressions and gradient optimization |
viz |
Matplotlib visualization and animation |
plotly |
Interactive HTML visualization |
svg |
Publication-quality SVG export via drawsvg |
Extras can be combined: pip install pylinkage[viz,scipy,numba]
For development:
git clone https://github.com/HugoFara/pylinkage.git
cd pylinkage
uv sync # or pip install -e ".[full,dev]"Define and Visualize a Four-Bar Linkage
Using the component-based API (recommended). Visualization requires pip install pylinkage[viz].
from pylinkage.components import Ground
from pylinkage.actuators import Crank
from pylinkage.dyads import RRRDyad
from pylinkage.simulation import Linkage
from pylinkage.visualizer import plot_kinematic_linkage
# Define ground pivots
O1 = Ground(0, 0, name="O1")
O2 = Ground(3, 0, name="O2")
# Create crank (motor-driven input)
crank = Crank(anchor=O1, radius=1.0, angular_velocity=0.31, name="crank")
# Create rocker via RRR dyad (circle-circle intersection)
rocker = RRRDyad(
anchor1=crank.output,
anchor2=O2,
distance1=3.0,
distance2=1.0,
name="rocker"
)
my_linkage = Linkage([O1, O2, crank, rocker], name="Four-Bar")
plot_kinematic_linkage(my_linkage)For a more mechanical engineering-oriented approach, use MechanismBuilder to define links with their lengths first, then connect them:
from pylinkage.mechanism import MechanismBuilder
# Define links by their lengths, then connect with joints
mechanism = (
MechanismBuilder("four-bar")
.add_ground_link("ground", ports={"O1": (0, 0), "O2": (4, 0)})
.add_driver_link("crank", length=1.0, motor_port="O1", omega=0.1)
.add_link("coupler", length=3.5)
.add_link("rocker", length=3.0)
.connect("crank.tip", "coupler.0")
.connect("coupler.1", "rocker.0")
.connect("rocker.1", "ground.O2")
.build()
)
# Joint positions are computed automatically from link lengths
for positions in mechanism.step():
print(positions)PSO is built-in (no extra needed).
import pylinkage as pl
@pl.kinematic_minimization
def fitness(loci, **_):
tip_locus = tuple(x[-1] for x in loci)
return pl.bounding_box(tip_locus)[0] # Minimize min_y
bounds = pl.generate_bounds(my_linkage.get_num_constraints())
ensemble = pl.particle_swarm_optimization(
eval_func=fitness, linkage=my_linkage, bounds=bounds, order_relation=min
)
best = ensemble.top(1)[0]
my_linkage.set_num_constraints(best.dimensions)Requires pip install pylinkage[symbolic]. Get closed-form trajectory expressions:
from pylinkage.symbolic import fourbar_symbolic, compute_trajectory_numeric
import numpy as np
linkage = fourbar_symbolic(ground_length=4, crank_length=1, coupler_length=3, rocker_length=3)
params = {"L1": 1.0, "L2": 3.0, "L3": 3.0}
trajectories = compute_trajectory_numeric(linkage, params, np.linspace(0, 2*np.pi, 100))The docs/notebooks/ directory contains hands-on tutorials that walk through each major feature:
| # | Notebook | What you'll learn |
|---|---|---|
| 01 | Straight-Line Synthesis | Design a mechanism that traces a straight line from scratch |
| 02 | Optimize a Coupler Curve | Use PSO to shape a four-bar coupler path |
| 03 | Tolerance Analysis | Monte Carlo analysis for manufacturing variation |
| 04 | Cam-Follower Timing | Design cam profiles with motion laws |
| 05 | Symbolic Coupler Curve | Closed-form trajectory expressions with SymPy |
| 06 | Function Generation | Match input/output angle relationships (Freudenstein) |
| 07 | Motion Generation | Guide a rigid body through specified poses (Burmester) |
| 08 | Velocity & Acceleration | Compute joint velocities and accelerations |
| 09 | Transmission Angle & DOF | Evaluate mechanism quality and mobility |
| 10 | Mechanism Builder | Link-first definition with MechanismBuilder |
| 11 | Multi-Objective Optimization | Pareto-optimal design with NSGA-II and scipy |
| 12 | Three Synthesis Problems | Side-by-side comparison of path, function, and motion synthesis |
| 13 | Population Abstractions | Batch simulation, ranking, and filtering of mechanism families |
| 14 | Topology Enumeration | Enumerate and synthesize across all valid topologies |
| 15 | Hypergraph Composition | Compose mechanisms hierarchically from reusable hypergraph components |
Pylinkage also supports velocity and acceleration analysis, cam-follower mechanisms with configurable motion laws, transmission angle evaluation, Monte Carlo tolerance analysis for manufacturing, multi-objective optimization (NSGA-II/III via pymoo), and export to DXF and STEP for CNC and CAD workflows. See the tutorials for details.
Level 0: Geometry → Pure math primitives (numba-accelerated when installed)
Level 1: Solver → Assur group solvers (numba-accelerated when installed)
Level 2: Components → Ground, Crank, RRRDyad, LinearActuator, cam-followers
Level 3: Simulation → Linkage orchestration, step(), step_fast()
Level 4: Applications → Optimization, Synthesis, Symbolic, Visualization
Performance: With the numba extra, step_fast() achieves 1.5-2.5M steps/sec (4-7x faster than step()). Without numba, the same code runs in pure Python/NumPy.
Full module reference
| Module | Purpose | Extras needed |
|---|---|---|
pylinkage.components |
Base components: Ground, Component |
— |
pylinkage.actuators |
Motor drivers: Crank, LinearActuator |
— |
pylinkage.dyads |
Assur groups: RRRDyad, RRPDyad, FixedDyad |
— |
pylinkage.simulation |
Linkage class for simulation via step() / step_fast() |
— |
pylinkage.mechanism |
Low-level Links+Joints model and MechanismBuilder |
— |
pylinkage.solver |
High-performance numba-compiled simulation backend | numba |
pylinkage.optimization |
PSO, differential evolution, grid search | scipy (DE only) |
pylinkage.synthesis |
Classical synthesis: function/path/motion generation | scipy |
pylinkage.symbolic |
SymPy-based symbolic computation and gradient optimization | symbolic |
pylinkage.visualizer |
Matplotlib, Plotly, SVG, DXF, and STEP export | viz, plotly, svg |
pylinkage.assur |
Assur group decomposition and graph representation | — |
pylinkage.hypergraph |
Hierarchical component-based linkage definition | — |
- Python >= 3.10
- Core: numpy, tqdm
- Optional (via extras): numba, scipy, sympy, matplotlib, plotly, drawsvg
- pylinkage-editor — Visual linkage design tool with an easy-to-use interface. Draw mechanisms interactively, run synthesis from the GUI, and export results.
- leggedsnake — Dynamic walking simulation built on pylinkage. Adds pymunk physics, genetic algorithm optimization, and walking-specific fitness evaluation.
Contributions welcome! Please see CONTRIBUTING.md and respect the CODE_OF_CONDUCT.md.



