A live, in-browser companion to the SST Robotics & Automation course. Every
core concept from lectures and labs is a thing you can poke at: drag sliders,
click targets, watch arms swing, masks bloom, layers stack, ultrasonic pulses
fly out and bounce back. Thirteen interactive sections on index.html, plus a
full 2-link arm simulator in capstone/.
The visualizations draw on canvas, but the math behind the headline concepts
is extracted into small, framework-free ES modules under src/ — no DOM, no
canvas, no dependencies — and covered by Node's built-in test runner. The
capstone arm imports these modules directly, so the page and the test suite run
the exact same code.
| Module | What it computes | Proven by the tests |
|---|---|---|
src/kinematics.js |
2-link planar forward kinematics (joint angles → end-effector position) and closed-form inverse kinematics (target → joint angles, both elbow branches) | Zero angles extend the arm fully along the base axis; known angles hit hand-computed points; IK→FK round-trips back to a reachable target within 1e-7; unreachable targets are reported (reachable:false, finite angles, never NaN) and clamped onto the reachable annulus |
src/pid.js |
A discrete parallel-form PID controller (u = Kp·e + Ki·∫e + Kd·de/dt, with anti-windup) plus first-order and mass-damper plant simulators |
Drives steady-state error to ~0 on a constant setpoint; raising Kp increases the initial response; the integral term removes a steady-state offset that pure-P leaves under a constant load |
src/planner.js |
A* grid path planning, 8-connected, with weighted Euclidean heuristic (diagonal cost √2) | Finds a valid path on an open grid; reports none when the goal is walled off or the grid is split; every returned path is connected start→goal through 8-adjacent, obstacle-free cells |
These cores are faithful extractions of the on-page implementations:
capstone/app.js (FK/IK + PID) and js/planning.js (A*). The capstone now
imports src/kinematics.js instead of carrying its own copy.
Requires Node 18+ (developed on Node 24 — uses node:test + node:assert, no
npm install needed):
node --test✔ FK: zero angles extend the arm fully along the +x base axis
✔ FK: known angles place the end-effector at the hand-computed point
✔ IK then FK round-trips to a reachable target within tolerance
✔ IK: both elbow branches are distinct yet both reach the target
✔ IK: unreachable targets are reported, not returned as NaN garbage
✔ reach radii match link geometry
✔ PID drives steady-state error to ~0 on a constant setpoint
✔ raising Kp increases the initial response
✔ integral term removes a steady-state offset that P alone leaves
✔ reset clears integral and derivative history
✔ finds a valid path on an open grid
✔ path is connected: every step moves to an 8-neighbor
✔ returns no path when the goal is walled off
✔ returns no path when a full wall divides the grid
✔ start or goal on a wall yields no path
✔ heuristic weight still returns a connected start->goal path
ℹ tests 16
ℹ pass 16
ℹ fail 0
| Section | Interaction | Math / system being shown |
|---|---|---|
| 01 Kinematics | sliders for θ₁, θ₂, L₁, L₂; click target for IK; double-click to flip elbow | 2-link planar FK + closed-form IK |
| 02 Degrees of Freedom | link count, motion amplitude/speed | N-link manipulator with tip-trail workspace exploration |
| 03 Workspace | joint-limit sliders | Sampled reachable set vs. ideal annulus |
| 04 Vision | per-color HSV sliders (H/S/V min–max) | RGB→HSV thresholding, three masks |
| 05 ROS | publish rate, message drop, click nodes/edges | Animated nodes + topics graph |
| 06 PID Control | Kp/Ki/Kd, disturbance; drag setpoint on chart | Discrete PID on a mass-damper |
| 07 Gripper | servo angle slider, object width, auto-cycle | Rack & pinion mechanism |
| 08 3D Printing | layer height, infill %, print speed | Layer-by-layer FDM toolpath visualisation |
| 09 Electronics | voltage + 3 resistor band selectors | Ohm's law V=IR, LED brightness, burn-out at >30 mA |
| 10 Ultrasonic Sensor | drag obstacle, beam angle, speed of sound | HC-SR04 echo time + cone, scrolling distance plot |
| 11 Differential Drive | left + right wheel speeds, wheelbase | Mobile-robot pose integration v=(vR+vL)/2, ω=(vR-vL)/L |
| 12 Path Planning | drag start/goal, click walls, heuristic weight | Live A* with explored-frontier overlay |
| 13 Cobot HRI | drag human, drag gaze, tune personal space | Proxemics + gaze state machine |
The capstone (capstone/index.html) is a focused 2-link arm: FK by sliders,
IK by clicking a target (with elbow-up/down and an unreachable indicator), and a
PID mode that drives the joints to the IK solution while plotting joint error.
Pure static HTML/CSS/JS. Because the capstone loads ES modules, serve the folder
over HTTP (don't open it from file://):
python -m http.server 8000 # or: npx serve .Then visit http://localhost:8000.
The included .github/workflows/pages.yml deploys automatically on every push to
main. In Settings → Pages → Build and deployment set the source to
GitHub Actions. The site goes live at https://<you>.github.io/<repo>/.
The .nojekyll file disables Jekyll so the src/ modules and any future
_-prefixed filenames are served as-is.
.
├── index.html # 13 interactive sections
├── course.html # editorial course overview
├── project.html # editorial project write-up
├── styles.css
├── src/ # tested, DOM-free algorithm cores
│ ├── kinematics.js # 2-link FK + IK
│ ├── pid.js # PID controller + plant sims
│ └── planner.js # A* grid path planning
├── test/ # node:test specs (run with `node --test`)
│ ├── kinematics.test.js
│ ├── pid.test.js
│ └── planner.test.js
├── js/ # on-page canvas/SVG visualizations
│ ├── kinematics.js dof.js workspace.js vision.js ros.js
│ ├── control.js gripper.js printing.js electronics.js
│ └── sensor.js drive.js planning.js cobot.js
├── capstone/ # 2-link arm simulator (imports src/kinematics.js)
├── package.json # "type":"module", "test":"node --test"
├── .nojekyll
└── .github/workflows/pages.yml