Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

Burmester

A differentiable linkage synthesizer.
Draw a path. Get a mechanism whose coupler point traces it.

▶ Live demo · How it works · CI

Burmester synthesizing a four-bar linkage that traces an egg-shaped target curve to within 1.8%


What this is

Path-generation synthesis is a classic, genuinely hard problem in mechanism design: you want a linkage — say a four-bar — whose coupler point (a point rigidly fixed to the floating link) traces a prescribed curve as the input crank turns. A straight line for a film advance. A D-shape for a knee. A figure-eight for a mixing blade. Ludwig Burmester laid the geometric groundwork for this in 1888, and it is still not easy.

Burmester (the tool) lets you freehand-draw the target curve and then solves for the entire mechanism — every ground-pivot coordinate, every link length, the coupler-point offset, the crank phase — by gradient descent through a fully differentiable kinematic model, wrapped in multi-start basin-hopping to escape local minima. It runs in the browser, off the main thread, and shows you the mechanism converging onto your drawing in real time.

The autodiff engine, the position solver, and the optimizer are all written from scratch in dependency-free TypeScript (~2k lines). The only runtime primitive is the browser's 2-D canvas.

A Stephenson-III six-bar linkage synthesized to trace a heart-shaped curve
A Stephenson-III six-bar tracing a heart — the extra loop buys curl a four-bar cannot produce.

Why it's different

Tool Simulate Synthesize a path Target input Method
PMKS+ / MechAnalyzer / Linkage (Rectorsquid) forward kinematics only
GIM, SAM, classical Freudenstein ⚠️ 3–5 precision points click points solve polynomial systems
DiffTaichi / Brax / Warp ✅ (rigid/soft dynamics) code differentiable physics, Python, research
Burmester whole freehand curve draw it end-to-end differentiable position analysis + Adam + basin-hopping, in the browser

Precision-point methods hit a handful of exact points and let the curve do whatever it likes in between. Differentiable-physics frameworks target integrated dynamics, not closed-loop position synthesis, and live in Python notebooks. A browser-native tool that differentiates straight through an unrolled Newton position solver to fit a hand-drawn curve did not appear to exist. That's the contribution.

How the math works

Synthesis pipeline: numeric trace, similarity alignment, one differentiable Newton step per sample, Chamfer loss, backward pass, Adam update

1. Position analysis (the assembly problem). For a given crank angle θ and a set of design parameters, the moving joints sit wherever every rigid bar keeps its length. Stack the unknown joint coordinates into q and each bar (a,b,L) contributes one equation

g_k(q) = |p_a − p_b|2 − L2 = 0

For a well-constrained 1-DOF linkage there are exactly 2·(#free joints) equations, so the system is square and solved by Newton–Raphson with an analytic Jacobian, warm-started from the previous crank angle to stay on one assembly circuit.

2. Differentiating through the solver. Unrolling every Newton iteration onto the autodiff tape is wasteful and noisy. Instead we converge in plain floats, then take exactly one Newton step under automatic differentiation from the converged point q*:

q_diff = q* − J(q*, p)−1 g(q*, p)

with q* held constant and the parameters p live. Since g(q*, p) ≈ 0 in value but not in derivative, this reproduces the implicit-function-theorem result dq/dp = −J−1 (∂g/∂p) in a single small linear solve — cheap, exact to first order, and stable. (Full derivation in docs/THEORY.md.)

3. The loss. The traced coupler curve is aligned to the target by a closed-form similarity fit (Procrustes + a few ICP iterations, re-fit every iteration) and compared with a symmetric Chamfer distance — no correspondence or arc-length matching needed, so it copes with open curves, uneven crank speed, and self-intersections. Soft penalties keep the linkage Grashof (input crank fully rotating), keep link lengths sane, and stop the curve collapsing to a point. Every term is a differentiable scalar; one backward pass gives the gradient with respect to all ~10 (four-bar) or ~16 (six-bar) parameters.

4. The optimizer. From-scratch Adam with gradient clipping and cosine learning-rate decay, inside multi-start basin-hopping: sample several random feasible linkages, polish each, then perturb-and-repolish the incumbent. Seeded RNG, so a given seed reproduces a given mechanism.

Quick start

npm install
npm run dev # http://localhost:5173

Then:

  1. Draw a target on the canvas (or pick one from the gallery).
  2. Choose Four-bar or Six-bar and a quality level.
  3. Hit Synthesize and watch it converge.
  4. Drag any pivot to explore; Export the mechanism as JSON or an SVG.
npm test # 33 tests: gradient checks, kinematics, mechanism recovery
npm run build # production bundle in dist/
npm run typecheck

Using the engine as a library

The core is UI-free and works in Node:

import { synthesize } from "./src/synthesis/optimize.js";
const target = [/* [x, y] points, open or closed */];
const result = synthesize(target, {
 topology: "fourbar", // or "stephenson3"
 seed: 7,
 restarts: 8,
});
console.log(result.placedSpec); // the mechanism, positioned on the target
console.log(result.grashof.crankRotates); // does the input crank fully rotate?
console.log(Math.sqrt(result.parts.chamfer)); // fit error, in target units

Lower-level pieces are exported too:

import { Value, checkGrad } from "./src/autodiff/index.js"; // reverse-mode AD
import { fourBar, grashof } from "./src/kinematics/factories.js"; // build a mechanism
import { traceCoupler } from "./src/kinematics/trace.js"; // trace its coupler curve

Layout

src/
 autodiff/ Value (reverse-mode AD scalar), Vec2, gradient + finite-difference checks
 kinematics/ mechanism model, Newton position solver, differentiable trace, factories
 synthesis/ curve alignment, Chamfer objective, Adam + basin-hopping
 app/ canvas renderer, pointer interaction, worker, control panel
docs/ THEORY.md and figures

Limitations

  • Planar, single-DOF, kinematics only. No spatial linkages, no multi-input mechanisms, no forces or dynamics.
  • Local minima. Basin-hopping mitigates but cannot eliminate them. Different seeds find different mechanisms; some targets a four-bar simply cannot trace well (try the six-bar, or accept the closest fit).
  • Assembly-mode discontinuities. When a linkage passes through a dead configuration the coupler curve can jump between circuits. The tracer detects and reports this; it does not fully solve it.
  • The similarity alignment means the synthesized mechanism reproduces the shape of your drawing at whatever position and scale fits best. Turn off "allow rescaling" to pin the drawn size.

References

  • L. Burmester, Lehrbuch der Kinematik (1888).
  • R. S. Hartenberg & J. Denavit, Kinematic Synthesis of Linkages (1964).
  • J. M. McCarthy & G. S. Soh, Geometric Design of Linkages, 2nd ed. (2011).
  • F. Freudenstein, "Approximate synthesis of four-bar linkages" (1955).
  • D. P. Kingma & J. Ba, "Adam: A Method for Stochastic Optimization" (2014).

License

MIT — see LICENSE.

About

A differentiable linkage synthesizer — freehand-draw a path and gradient-descend a planar mechanism whose coupler point traces it. Browser-native, dependency-free TypeScript.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /