A robotic arm kinematics simulator. An interactive, web-based tool for forward and inverse kinematics of serial robotic arms, built to make the underlying math tangible. Move a joint or drag a target and watch the Denavit-Hartenberg transforms, the Jacobian, and the IK solver update live, in 2D and 3D.
The name says what it does: it lives in the space between joint space (the angles you control) and task space (where the tool ends up). Forward kinematics maps one way, inverse the other.
Built for the person teaching themselves robotics who found FK/IK painfully abstract, and didn't want to reach for MATLAB or ROS/Gazebo just to see it. Every number on screen is computed by small, readable Python you can open and tweak. Established robotics libraries are used only to test that math, never at runtime.
2D planar side view, with the editable DH table, live Jacobian + singularity measures, and the end-effector pose:
3D orbitable spatial arm (Z-up, RGB coordinate frames), joint controls, the trajectory planner, and the live per-joint transforms:
- (a) Build & drive any arm. Edit a full DH-parameter table (link length
a, twistα, offsetd, angleθ, revolute/prismatic, joint limits) or load a preset. The per-joint homogeneous transformsAᵢand their product⁰Tₙrender live as you move the joints. - (b) Inverse kinematics, unboxed. Drag a Cartesian target and the arm follows.
Then single-step the solver to watch the error
‖e‖fall to zero, with the live Jacobian and the joint stepΔqon show. Switch between damped least squares, pseudo-inverse, and Jacobian-transpose and feel the difference near a singularity. - (c) Workspace & singularities. Sample the reachable workspace as a point cloud, and drive the arm into a singularity, where it turns red and the manipulability, condition number, and singular values show the lost degree of freedom.
- (d) Trajectory playback. Capture waypoints, plan a path in joint space (smooth joints, curved tool path) or Cartesian space (straight tool line, may hit singularities), and play it back: the pick-and-place workflow.
Switch between a 2D planar view (SVG, annotation-rich) and a 3D view (Three.js, orbitable) at any time. Coordinate frames follow the robotics convention: X = red, Y = green, Z = blue, Z-up.
Browser (React + Three.js / SVG)
| WebSocket real-time: joint drags, IK target, solver steps, trajectory
| REST one-shot: presets, DH validate, batch FK/IK/Jacobian, workspace, trajectory plan
v
FastAPI -> kinematics engine (numpy) <- THE PRODUCT: clean, readable math
- Python is the single source of truth for all kinematics. The frontend never re-derives a pose, matrix, or Jacobian; it renders what the backend computed.
- Real-time interaction rides a WebSocket: outbound input is coalesced to one
message per animation frame (tagged with a monotonic
seq), and stale frames are dropped on the way in. That is what lets a Python backend feel instant. - Convention: standard (distal) DH,
Aᵢ = Rz(θ)·Tz(d)·Tx(a)·Rx(α), stated in the code and in the UI, because a silent convention mismatch is the #1 source of "my answer disagrees with the textbook" bugs.
Prerequisites: uv (Python 3.13, fetched
automatically) and Node.js 20.19 or newer.
# 1. Backend deps (creates .venv with Python 3.13)
uv sync
# 2. Frontend deps
cd frontend && npm install && cd ..
# 3. Run both together (FastAPI :8010 + Vite :5173)
./dev.shThen open http://localhost:5173. (The backend runs on port 8010 to avoid a
clash with other local services; the Vite dev server proxies /api and /ws to it.)
To run the pieces separately:
uv run uvicorn app.main:app --reload --app-dir backend --port 8010 # backend
cd frontend && npm run dev # frontend# Backend math + API (pytest): FK/IK/Jacobian, singularity, workspace, trajectory, WS/REST
uv run pytest
# Oracle validation against the modern_robotics library (independent PoE formulation)
uv sync --group oracle && uv run pytest backend/tests/test_oracle_modern_robotics.py
# Frontend unit tests (vitest): rAF coalescing, drop-stale, formatting
cd frontend && npm test
# End-to-end (Playwright): drives all four teaching surfaces against the real backend
cd frontend && npm run e2eThe backend math is anchored to closed-form ground truth (2-link planar FK & IK),
property-based FK/IK round-trips, an analytic-vs-finite-difference Jacobian check, and
agreement with modern_robotics.
backend/app/
kinematics/ # THE PRODUCT: small, readable numpy
transforms.py dh.py fk.py jacobian.py ik.py
singularity.py workspace.py trajectory.py robot.py presets.py
api/ # thin FastAPI layer over the engine
rest.py ws.py schemas.py session.py
main.py
backend/tests/ # unit + oracle + API tests
frontend/src/
viewport/ # Viewport2D (SVG) + Viewport3D (react-three-fiber)
panels/ # DH editor, matrices, Jacobian, IK + stepper, workspace, trajectory
net/ # ws.ts (real-time) + rest.ts
store/robotStore.ts # Zustand state
types.ts # wire-format types only, no math
dev.sh # run backend + frontend together
Backend: FastAPI · uvicorn · numpy · pydantic · scipy · pytest · ruff Frontend: React 19 · Vite 8 · TypeScript · react-three-fiber + three · zustand · KaTeX · vitest · Playwright
- FK (
fk.py): multiply each link's DH transform in order; return every intermediate frame. - Jacobian (
jacobian.py): geometric column formula, cross-checked against a finite-difference version. - IK (
ik.py): iterative; damped least squares by default (Δq = Jᵀ(JJᵀ+λ²I)⁻¹e), exposed as a generator that yields every iteration so the UI can step through it. Position-only by default (many arms cannot reach arbitrary orientations, surfaced rather than hidden). - Singularity (
singularity.py): manipulability, condition number, and singular values of the effective position Jacobian. - Workspace (
workspace.py): vectorized Monte-Carlo sampling of the reachable set. - Trajectory (
trajectory.py): joint-space and Cartesian-space interpolation with linear / cubic / quintic blend profiles.

