diff --git a/docs/PAGES.md b/docs/PAGES.md index ee56ed5..a287191 100644 --- a/docs/PAGES.md +++ b/docs/PAGES.md @@ -26,12 +26,39 @@ Open in `EXHIBIT_MODE=dev`; password-protected in `EXHIBIT_MODE=final` | `/admin/characters.html` | Characters | Per-ghost visuals: model, part placement, gradient colours, opacity, height, scale, face/torso textures. | | `/admin/landing.html` | Landing Page | Visitor landing screen: title, logo, background, accent colour, about text, disclaimer. | | `/admin/preview.html` | Virtual Viewport | Live orbit view of whatever ghosts are currently active, straight off the same WebSocket feed as the exhibit. Ground truth when the AR view disagrees. | +| `/admin/testsheet.html` | A3 Test Rig | Printable A3 calibration/evaluation sheet, and a one-click load of the matching scene + playlist. See below. | | `/admin/plan.html` | Placement Plan | Measured plan for physically positioning crests and models on the real table. | | `/admin/print.html` | Print Crests | Generates printable ArUco markers ("Newbury Crests") at the configured `sizeMM`. | | `/admin/calibrate.html` | Calibrate | Camera/marker calibration helper. Detects crests **without** filtering against the scene, so it's the quickest way to prove a printed crest is readable at all. | | `/admin/errors.html` | Client Errors | Errors reported by visitor devices (JS errors, unhandled rejections, ghost build and scene-fetch failures). First stop when something works on one phone but not another. | | `/admin/login.html` | Login | Only relevant in final mode. | +## The A3 test rig + +`/admin/testsheet.html` is a self-contained test environment for evaluating +tracking, occlusion and lighting without the LEGO town in the way. + +- **Print A3 landscape at 100% ("Actual size"), never "Fit to page."** Check the + 100 mm scale bar first: if it doesn't measure 100 mm, every crest is the wrong + size and every pose is scaled with it. +- The sheet *is* the table — A3 landscape is exactly 42.0 × 29.7 cm. Origin is + the front-left corner, matching the exhibit's world frame. +- **6 crests** at 60 mm, spread 38.7 cm corner to corner (the spread is what + makes the joint solve well-conditioned). +- **Cylinder occluder**: stand an 85 mm ⌀ × 160 mm tall object on the dashed + circle at centre. +- **Static ghost** at (21, 22) cm, deliberately *behind* the cylinder from the + front — walk around it and the ghost should disappear behind the post. +- **Walking ghost** on an 18 × 12 cm rectangular loop around the cylinder; + 60 cm perimeter, ~40 s per lap at the default 1.5 cm/s. +- "Load this layout onto the server" writes both the scene and the playlist, + built from the same constants that drew the sheet, so print and config can + never drift apart. It **replaces** the live scene and playlist — save your + current layout first. + +Known gap: the layout editor doesn't understand cylinder occluders, so opening +and saving this layout there will drop the cylinder. + ## Useful API endpoints Read-only ones are handy to open directly in a phone browser while debugging; @@ -50,15 +77,25 @@ the rest need auth in final mode. | `/api/client-errors` | Reported client errors (auth in final mode) | | `/ws` | WebSocket: `scene`, `active`, `spawn`, `despawn`, `characters`, `pong` | -## Gotcha worth remembering +## Gotchas worth remembering -Detection filters camera detections against the marker IDs in the **active -scene**. A crest that isn't an anchor in the current layout is detected and then -discarded, which used to look exactly like "the camera can't see anything". +**Detection filters against the active scene.** A crest that isn't an anchor in +the current layout is detected and then discarded, which used to look exactly +like "the camera can't see anything". -- The scene is now fetched over HTTP at start, so a down or flapping WebSocket - no longer breaks tracking. +- The scene is fetched over HTTP at start, so a down or flapping WebSocket no + longer breaks tracking. - The HUD reports `scene N anchors` (or `NOT LOADED`) and `markers 1/2 seen [0,7]` — usable over raw — so a filtered-out crest is visible at a glance. - The tracking chip says "Crest N not in this layout" rather than "Point at a Newbury Crest" when this happens. + +**Motion amounts live on the server.** `playlist.js` sends explicit `bobAmp`, +`radius`, `speed` values with every spawn, so the client's defaults never apply +to a real ghost. Tune motion in the playlist config (`behaviors.bobAmp`, +`wanderRadius`, `pathSpeed`), not in `behavior.js`. + +**An upstream proxy can override cache headers.** The app sends `no-cache` for +JS and HTML, but openresty in front has been seen replacing it with a daily +`expires`. If a deploy doesn't reach a device, check the response headers and +test in a private tab.