# Door robot arm: status Standalone project (the user: "this will be standalone project dont add on the ship yet"). The ship file is not touched. ## Coder stage 3: DONE (2026-10-16, 19:55-21:05) Summary (details under Progress below): - PART 1, the shape pass: the dark core as one mass, the drum shown as ref7 shows it, the turret / upper arm / wrist block rounded and layered, version A's beak fingers with ribbed sections. Real file rebuilt (backup v16). All checks 0, pose 0.056 mm / 0.014 deg. - PART 2: surfaces from real texture data with a baked 4096 atlas (AO / edges / crevices + bevel normal); 41 UCX hulls; 21 FBX files (skeletal per version with LOD1 50.5 % and LOD2 20.8 %, 4 door animations, statics with UCX, rail kits, fixtures, the chains with their animations), all re-imported and verified (ALL OK); `DoorRobotArm_layout.json`; Cycles renders in `previews/cycles/` (showroom at ref1-3 both and alone, close-ups like ref4-7, ship fit frames 1/12/30/48/90 both versions both doors, switch sheets, a comparison sheet); the light rig '90 STUDIO | lights (not part of the asset)' in the file; the file saved with the showroom active; `README.md`. - Final checks on the final file: rig_check pose 0.0558 mm (A) / 0.0549 mm (B), 0.014 deg, 0 crossings (arm parts, context, kit, chains, fixtures, curves), 0 limit breaks, pads 3.5 mm from the buffers, arm to the end wall 0.242 m (A) / 0.324 m (B), switch correct, 604 drivers simple and valid; geo_audit 0 n-gons / open edges / non-manifold / crossings (69 meshes with the hulls); geo_sweep 0 hits; verify_fbx ALL OK (21 files). - Triangles LOD0 A 187,707 / B 162,279 in the file (FBX with the cables: 189,547 / 164,119); LOD1 95,690 / 82,976; LOD2 39,342 / 34,268. - Not done: nothing tried in Unreal (import, root placement, Physics Asset, materials rebuilt there); the materials are Blender-only (table in `build/surf_report.json` and the layout json); the shells are still simpler than the sculpted reference model; the arm is not in the ship (the user's word). The coordinator's order (stage 2 accepted): PART 1 a shape pass before the bake, only these four: (1) the lower arm's dark core as one dark mass (ref5, ref1); (2) the shoulder drum shown as ref7 does (barrel and ribbed strip clearly between the side caps); (3) turret, upper arm and wrist block layered and sculpted like ref1-ref5; (4) version A's finger tips as ref6's curved beaks with ribbed sections. Then audit, sweep, rig_check, previews/geo, compare sheet. Triangle budget (the coordinator's decision): keep LOD0 as is; LOD1 about 50 %, LOD2 about 20 % at export (small parts dropped first, then reduced; the silhouette must hold). PART 2 stage 3: surf (real texture sets, UV in metres, baked AO/edge/crevice atlas), UCX hulls (hidden in the viewport), export (FBX per version with LODs, a verify script, DoorRobotArm_layout.json), Cycles renders (showroom at ref1-3 both and each alone, close-ups like ref4-7, ship fit frames 1/12/30/48/90 both versions), a light rig saved in a collection outside the asset, the file saved with the showroom active, README.md. Back up the .blend into versions/ before each rebuild. ### Progress - PART 1 scripts changed (20:00-20:25), checked in scratch files (audit 0, sweep 0, rig_check 0 crossings, pose 0.056 mm / 0.014 deg, 604 drivers simple and valid): 1. dark core: one dark mass (`CORE_MASS` 72 mm proud, half width 0.285, rounds 16 mm) with one raised face (`CORE_FACE`) carrying the bosses, in place of three thin plates (`dra_parts_arm.py`); 2. drum: the white inner shells start 0.315 m from J2 (`ROOT_CLEAR`), so the barrel with its hole rows and the ribbed strip shows between the side caps from behind; the side housings' rear ends are now an arc round the J2 cap (R 0.185, top Z 0.70 as ref1 measures), the drum stands 0.06 above them (ref7) (`dra_parts_turret.py`); 3. shells: turret housing rounds 26 mm (was 10), its panels set inside them, a lid on each cheek's top, a skirt ledge at its foot; upper arm rounds 32 mm (was 18) with a raised lid along the top under the spine; wrist block rounds 14-20 mm (was 4-10) and a stepped side panel kept out of the finger motors' sweep (`dra_parts_wrist.py`); 4. fingers (A): the distal links are curved beaks (centre line bowed outward, tapered 40 -> 14 mm, an oval slot, bored for their pin, the hook unchanged); the proximal's ribbed section is nine flat rib plates (ref6). Previews: ref5 now uses the critique's matched camera (front-left, from below). Triangles: A 187,707, B 162,279. - 20:05 the real file rebuilt (`versions/v16_before_stage3_shape/` holds the one before). Checks on it, all pass: rig_check (both doors, both versions, frames 1-120): pose 0.056 mm (A) / 0.055 mm (B), 0.014 deg; 0 crossings, 0 curve crossings, 0 limit breaks; pads 3.5 mm from the buffers; arm to end wall 0.242 (A) / 0.324 m (B); chains 0 crossings; switch correct; 604 drivers simple and valid; fixtures 0.001 mm. geo_audit 0 (n-gons, open edges, non-manifold, crossings); geo_sweep 0 hits. previews/geo re-rendered, `geo_compare_sheet.png` remade (now built by the preview stage itself). **PART 1 DONE.** - Next: PART 2 (surf, UCX, export with LODs, verify, layout json, Cycles renders, light rig, README). - 20:15-20:30 PART 2 step 1, surfaces (`build/dra_surf.py`, stages `surf` and `bake`). Fetched with curl into `source_polyhaven/` (manifest there; CC0): `blue_metal_plate` (2K, 4 maps, 4.2 MB) and the studio HDRI `studio_small_09` (2K, 6.3 MB, renders only). On the real file (backup `versions/v17_before_surf/`): one UV0 atlas for the 20 arm meshes of both versions (one texel density, 357 px/m, concave pack), materials dressed (white powder coat, orange, gunmetal, black metal for the carriage, bright steel, rubber, glass, lamp; kit and cable variants), the ship context's missing images given stand-in colours, the light rig '90 STUDIO | lights (not part of the asset)' saved in the ship-fit scene; the file saved with the showroom active. Bake (HIP GPU, 128 s): `textures/T_DoorArm_Masks.png` and `textures/T_DoorArm_BevelNormal.png` (4096). After any rebuild run `surf` then `bake` again. - 20:30 step 2, UCX (`build/dra_export.py`, stage `ucx`; backup `versions/v18_before_ucx/`): 41 convex hulls for the 20 links (k-means clusters of each link's vertices, at most 96 extreme points each, 23-93 vertices), parented to the showroom's link objects, collection `DoorArm | collision` with its eye off and hidden in renders. - 20:35 step 3, export (stage `export`, nothing saved) into `fbx/`, 21 files: SK_DoorRobotArm_A/B with _LOD1/_LOD2 (A 189,547 / 95,690 / 39,342 tris = 100 / 50.5 / 20.8 %; B 164,119 / 82,976 / 34,268), the door animations A_DoorRobotArm___OpenClose (frames 1-120), SM_DoorRobotArm_Links (20 statics + 41 UCX), the rail kits, fixtures (with UCX), and the energy chains (SK_DoorArm_Chain_ + their animations, 45 bones). `DoorRobotArm_layout.json` written. Verify (stage `verify_fbx`, `build/fbx_report.json`): ALL OK (bones, meshes, triangles, materials, UCX, bounds within 0.1 mm, skeletal files in cm with no scale on any node, animations 1-120 with the bones moving 5.1-6.3 m). - 20:40 the re-import showed the skeletal files' default pose was not their bind pose (the exporter read the pose before Blender re-evaluated the turned and scaled rest, so the mesh folded up on import). Fixed (`settle()` before writing); the verifier now checks the deformed mesh and the default pose too: ALL OK, default pose = bind pose (0.0). `previews/lods_A.png`, `lods_B.png`: LOD0 / LOD1 / LOD2 side by side from the re-imported files; the silhouette holds. - 20:45 `README.md` written (what it is in the user's words, opening and switching, scale and pivots, the rig, the rail, checks, textures and licences, FBX and LODs, what is not done, appending it to the ship later). - 20:50 step 4, Cycles renders (`build/dra_cycles.py`, stage `render`) into `previews/cycles/`. The first set showed the whites too clean and smooth (plastic) beside ref2/ref3 and the studio flat: a look pass in `dra_surf.py` (grey-white with the scan's scuffs, stronger relief and orange peel, a fine grain, satin roughness, more shade in crevices, a few more edge chips; the studio's fill and HDRI lower, the backdrop mid grey, `studio_look()`), then surf + bake again and the renders again. The atlas is now packed once per build (`atlas_packed`), so a later surf keeps the bake valid. - 21:00 look pass applied to the real file (backup `versions/v19_before_look_pass/`): surf (atlas packed again, flagged), bake again (134 s), then a visible powder-coat grain and faint smudges (surf again, the atlas kept). The close-up next to ref2 now reads as a satin grey-white powder coat with grain, not plastic. Final Cycles set rendering. - 21:00 final Cycles set done (37 pictures incl. sheets); the ref2 view showed the studio HDRI past the backdrop's edge: the world now lights with the HDRI and shows the camera a plain grey (`studio_look`, saved in the file), the showroom views rendered again. Final rig_check, geo_audit, export and verify_fbx on the final file (numbers in the summary above). `previews/cycles/cycles_compare_sheet.png`. **Stage 3 DONE.** - 21:05 the surf stage now stores every texture path relative to the file (checked: the scan, the HDRI and the baked maps load from `//source_polyhaven/...` and `//textures/...`); the file opens in the showroom, the collision collection has its eye off, the light rig is in the ship-fit scene, CONTROLS version 0 (A) and grip 1. ## Coder stage 2 (fixes, rig and fit): DONE (2026-10-16, 17:50-19:50, two power cuts on the way) Backup of the file and every build script before any change: `versions/v14_before_stage2/` (DoorRobotArm.blend, build/*.py, STATUS.md). The stage-1 file before the final build: `versions/v15_stage2_rig/`. ### What the file holds now (`DoorRobotArm.blend`, 19:33, made by `--stage build`) - Scene `DoorArm | Ship fit` (opens there, frame 1, version A shown): four arms `DoorArm_AFT_A`, `DoorArm_AFT_B`, `DoorArm_FORE_A`, `DoorArm_FORE_B` (root empties under the rails, turned 180 deg about x), in the collections `DoorArm | version A` / `DoorArm | version B` with their door fixtures and cable/hose curves; solver empties in `DoorArm | solver (hidden)`; `DoorArm | controls` holds `DoorArm | CONTROLS` with `version` (0 = A gripper, 1 = B plate) and `grip` (0 open .. 1 closed on the knob, default 1). Rail kits and the two 44-link energy chains in `DoorArm | rail kit`. Nothing is keyed: 604 drivers, every one a simple expression, all reading only the doors' location (the doors keep their own actions, frames 1-120). - Scene `DoorArm | Showroom`: both versions upright side by side on the floor rail, at rest (no drivers). - To switch versions: select `DoorArm | CONTROLS` and set its `version` property (Object properties, Custom Properties) to 0 or 1. A hidden version is not evaluated, so its objects keep old transforms until it is shown again; the export stage must switch `version` before it exports each version. ### Checks (all pass) - `build/rig_report.json` (frames 1-120 step 1, both doors, both versions; rig_check, 131 s): - pose of the end against the door: position 0.056 mm (A) / 0.055 mm (B), angle 0.014 deg (single precision); - 0 crossings: every arm object against every other one, against the context (deck, both rails, both end walls, hull lining, basin channel, aperture rim, both lamps and housings, both doors), the rail kit, the chain links and the fixtures; each arm's 4 curves (two elbow cables, two cylinder hoses) against the arm (except at their glands) and the context; - joints inside their limits (0 breaks). A: J1 32.7..82.4 (FORE 97.6..147.3), J2 -52.9..9.8, J3 -24.4..29.1, J4 -52.5..-10.8, J5 -74.4..-40.0, J6 11.5..52.3. B: J1 41.5..84.5 (FORE 95.6..138.5), J2 -60.4..-3.4, J3 -13.6..42.2, J4 -47.9..-7.6, J5 -66.4..-42.0, J6 8.0..49.1 deg (FORE mirrors J1, J4, J6); - J3 cylinder length A 0.716..1.245, B 0.591..1.147 m; piston end in the bore (-0.270..0.500): A -0.084..0.445, B -0.209..0.347; - carriage inside its travel (AFT -8.116..-3.014, FORE 9.114..14.216); strike pads 3.5-3.6 mm short of the buffers at both ends; carriage body 40 mm short of the rail's inner end; the arm to the pocket's end wall at least 0.243 m (A) / 0.324 m (B), the elbow cap at frame 48; - lowest clearances that are not a joint's own gap: chain bracket to the deck 6.5 mm, elbow cable to the looped hose 8.6 mm, J3 hose to the channel rungs 9.3 mm, A's hooks to the knob 12.5 mm, B's plate to the door 14.5 mm (the pad between, plate on pad by design), A to the door 110 mm; lining, basin channel, rim, lamps, end walls > 0.20 m; - joint gaps (running clearances by design): rollers on the rail 0.5-0.7 mm, trunnion stubs 0.5 mm, pins in eyes 1.2 mm, pinion in the rack 1.2 mm, rod in the barrel 1.4 mm, slewing ring 2 mm, wrist head in the cheeks 4.4 mm; faces in contact by design: tool on flange, plate on pad; - energy chains: 0 crossings (links with their neighbours, links with the tray), spacing 0.78 mm off the pitch on the bend (the chord), lowest to the tray 3.6 mm; door fixtures follow the doors to 0.001 mm, 0 deg; - version switch: 84 objects, A shown / B hidden, then B, then back to A, viewport and render: correct; - drivers in the saved file: 604, all `is_simple_expression` and `is_valid`. - `build/geo_report.json`: 0 n-gons, 0 open edges (markings apart), 0 zero-area, 0 duplicate faces, 0 non-manifold edges; 0 crossings within links, between the showroom objects, in the ship fit (rail kits, chains, fixtures, per version) and for the curves. Triangles (LOD0): arm A 184,311, arm B 161,139 (design budget 151,500 / 137,500: over by 22 % / 17 %, the critique's added detail); 85.7 % of arm A's faces are quads. Per mesh: lower arm 48,242, turret 37,870, carriage 24,980, upper arm 19,112, forearm 17,515, tool A hub 9,296, fingers 4 x (2,572 + 1,648), J3 cylinder 4,176, tool B 3,004, flange 2,112, piston 2,016, wrist head 1,440, pinion 672; rail kit 11,500 each, chain link 352 (x 44 per rail), fixture A 2,172 / B 672. - `build/geo_sweep.json`: 0 hits for both versions. Ranges = each version's door path +-3 deg (from `dra_ik.py`), J1 the whole circle, J3 with the cylinder and piston, J5 with J6 as the rig moves them, the grip closed on the knob. Information: J5 with J6 at 0 bends freely to -72.5 (A) / -77.5 (B); at the deepest bend (-74.4, A) J5 has 3 deg to spare with J6 on the path, about 0 if J6 were also 10 deg off it. ### Pictures - `previews/rig/` (Cycles, 96 samples, 1280 x 720, quick look; lights and cameras in the collection `DoorArm | render lights (not exported)`, made in the render session only; the ship's door material, whose images were already missing in the ship, gets a plain stand-in colour): `rig___f<001|012|030|048|090>.png` (one camera per frame for both versions, inboard under the deck), strips `rig___strip.png`, the switch `rig_switch_AFT.png` / `rig_switch_FORE.png` (A row over B row, same cameras), close-ups `rig_gripA_closed_on_knob.png`, `rig_plateB_on_pad.png`. - `previews/geo/` re-rendered from the final file: ref1 (and the overlay), ref2-ref5, ref6A/ref6B with ref6's camera, ref7 with the lower arm stood upright as in ref7, both, the ship views (now with the arms), the grip closed on the knob from the real meshes (CRITIQUE_1 item 11), and `geo_compare_sheet.png` (each reference beside its view). ### Compared with the references (honestly) - Done as CRITIQUE_1 asked: version B's short cone neck and plate (as the red sketch, ref6); the turret's long side housings with the J2 caps set in their rear ends, caps at |Y| 0.40, lower block in three tiers 0.60 wide; the perforated drum showing behind the caps (ref3) with the ribbed strip between the root straps; the forearm's rounded housing round the dial and the one-slope wrist wedge, J5 caps 0.19; curved, layered shells with raised rims and panels; the knee cap's size and notches; truss pockets, dark rod with collars, knurled knob with a dome; the sprocket and lug belt; the flat cable band; two cable loops and the looped hose; the flat-plate buckle; 0 non-manifold edges. - Still different: the lower arm's dark core reads as three stacked thin plates, not ref5's black mass; from behind, the turret cheeks hide more of the drum than ref7 shows; the turret, upper arm and wrist block are boxier than the sculpted references; the finger tips are not ref6's curved beaks (CRITIQUE_1 item 12, a "nice", not done). ref2 and ref3 turn the turret on a fixed rail, the previews move the camera instead. ### Not done (stage 3, the next Coder) Stages `surf` (real texture sets, bake), `export` (UCX hulls, FBX, layout json), `render` (Cycles beauty renders) and the README: `dra_build.py` has the stage table ready for them (`main()`). The triangle budget is a decision for the Designer/Critique (accept 184k / 161k or cut). ### History of this stage Plan: (1) fix CRITIQUE_1 must + should items in the geometry, (2) rig stage in `dra_build.py`, (3) version switch, (4) rig check -> `build/rig_report.json`, (5) renders -> `previews/rig/`. Decision on version B (critique item 1): neck 0.13 m (cone dia 0.154 -> 0.26), plate 0.55 x 0.55 x 0.044; its wrist centre is 0.326 m off the door face (A stays 0.63). So B has its own pose: B's IK ranges (closed form over the door path, AFT): J1 41.8..84.5, J2 -60.6..-3.8, J3 -13.2..42.7, J4 -47.8..-7.5, J5 -66.2..-42.0, J6 7.9..49.0 deg (A: J2 -52.9..9.8, J3 -24.4..29.1). Each door gets one arm per version (four arms), one control switches them. ### Power cut at about 18:47; a new Coder carries on (19:00) - What the cut left: `build/rig_drivers.json` was empty (zero bytes); the scratch files of the last minutes are not trusted and are made again. All `build/*.py` compile; the scripts changed last (render, sweep, arm, turret, wrist, base, audit) were read through and are complete. `DoorRobotArm.blend` is still the stage-1 file (16:56). - Plan from here: build geo + rig in a scratch file, rerun geo_audit, geo_sweep and rig_check, fix what fails, then back up and build the real file, check it, render. - 19:00-19:45, in scratch files: geo, audit (clean), rig (604 drivers, all simple and valid), rig_check (A and B, both doors, every frame: 0 crossings, pose 0.056 mm / 0.014 deg). The sweep with each version's real ranges (+3 deg) failed in two places, both fixed: - J3 at +45 deg (version B needs 42.2): the J3 barrel's gland (r 0.047) reached the truss plates (inner faces at |y| 0.040). The plates' inner faces moved out to |y| 0.052 (spacers on the knob pin longer); the truss looks the same from outside. (`dra_parts_arm._truss`) - J5 with J6 held at 0: the top finger's motor meets the wrist wedge at -73 deg (A needs -74.4, but the door path has J6 at 45-52 deg there; the wedge is shaped for that). The sweep now turns the wrist as the rig does: J5 past the path's ends at the path's J6, and J6 +-10 deg along the path (one margin at a time). Both pass. Reported as information: J5 alone is free to -72.5 (A) / -77.5 (B); at the deepest bend J5 has 3 deg to spare at the path's J6, about 0 if J6 were also 10 deg off the path. New: `build/dra_ik.py` (the closed-form IK in plain Python, for the sweep). The rig check now also measures the carriage's end gaps, the arm to the end wall, the energy chains, the fixtures following the doors, the version switch and recounts every driver in the saved file; clearances are split into joint gaps and all others. The ship-fit renders frame each shot on both versions' arms and the door round the hold (camera inboard under the deck); ref6 previews use the critique's ref6 camera; ref7 stands the lower arm upright as ref7 shows it. - 19:33 the real file: `--stage build --name stage2_rig` backed up the stage-1 file to `versions/v15_stage2_rig/` and built geo + rig into `DoorRobotArm.blend` (604 drivers, all simple and valid, `build/rig_drivers.json`). - 19:35 checks on the real file, all pass: `build/rig_report.json` (both doors, both versions, frames 1-120 step 1), `build/geo_report.json`, `build/geo_sweep.json`. The audit's ship-fit part now skips the rigged arms (the rig check's job) and checks each version's fixtures with that version switched on: a hidden version is not evaluated, so its objects keep stale transforms until it is switched on (the export stage must switch versions too). - 19:36 a second power cut; after it all scripts and reports were read back and are complete. The stray empty file `ship` (18:57, made while this session read the files) was moved out to the scratchpad. - 19:41-19:50 renders into `previews/rig/` and `previews/geo/` (see Pictures above); this note marked DONE. ### Progress (17:50 -> 18:47, before the cut) - Geometry fixes written (scripts only; the real .blend is not rebuilt yet, iterations go to the scratchpad): item 2 turret rebuilt in a new module `build/dra_parts_turret.py` (long side housings X -0.50..+0.515, Z 0.345..0.742, cheeks |Y| 0.215..0.30 round the drum, J2 caps faces at |Y| 0.398, three-tier lower block 0.60 wide); item 3 drum 0.40 long with a bulge, 2 x 32 barrel holes + 2 x 32 side holes, root straps + ribbed strip on the lower arm (`_root_band`); item 5 lower arm S-curved front edge, raised rim, 16 mm panel steps, three stacked dark core plates; upper arm convex top, dark lower strip, raised panels; item 6 knee cap 0.41/0.30 with round-ended notches and a castellated ring; item 7 truss with rim and five pockets, dark rod dia 0.058 with collars, knurled knob with a dome, bore deepened to -0.270 (B's shortest cylinder length 0.591); item 8 belt drive (sprocket + wide lug belt inboard of the white motor) and a flat seven-cable band with clips; item 9 two different cable loops + the looped hose on the gland; item 10 buckle of flat plates with pin bosses; item 4 forearm housing round the dial, keyhole dark plate, wrist block silhouette one 20 deg slope (central wedge |y| <= 0.085; cheeks stay low because the side fingers' motors sweep there at q5 -68..-74), J5 caps dia 0.19; item 1 tool B neck 0.13 m cone. - Rig written: `build/dra_rig.py` (stage `rig`, or `build` = geo + rig), check `build/dra_rigcheck.py` (stage `rig_check`). First full checks (scratch file): 604 drivers, all simple and valid; A and B, both doors, every frame: 0 crossings, pose error 0.056 mm / 0.014 deg, joints inside limits, carriage inside its travel, piston in the bore. - Audit (scratch): 0 n-gons, 0 open edges, 0 non-manifold (now in the summary), 0 crossings within links, between objects, ship fit, curves. Triangles A 184,311 / B 161,139 (design budget 151,500 / 137,500: over by 22 %, the critique's added detail). - Next: geo_sweep with the new ranges, the render stage (`build/dra_render.py`), the final build into DoorRobotArm.blend, the final rig_check into build/rig_report.json, previews. ## Design stage: DONE (Designer, 2026-10-16) `DESIGN.md`, `design.json` (made by `build/design_make_json.py`), proof scripts `build/design_*.py`, `build/check_*.json`, `build/proto_*.json`, posed proxy pictures `previews/design_pose_AFT_A_*.png`. ## Coder stage 1, geometry: DONE (2026-10-16) Entry point `build/dra_build.py`, one stage per headless call (each takes seconds): "E:\Steam\steamapps\common\Blender\blender.exe" -b --factory-startup --python build/dra_build.py -- --stage geo ... -- --stage geo_audit -> build/geo_report.json ... -- --stage geo_sweep -> build/geo_sweep.json ... -- --stage geo_preview -> previews/geo/geo_*.png (Workbench; --views ref1,ref2,... to pick) `--stage geo` backs up `DoorRobotArm.blend` to `versions/vNN_/` first (`--name` names it). `versions/v01..v13` are this stage's intermediate states (the file is rebuilt by script; they can go when the user wishes). Stage 2 added `rig`, `build`, `rig_check`, `rig_render`; `surf`, `export`, `render` are still to come (stage 3). ### Modules (`build/`) - `dra_lib.py` primitives (lathe, rbox with real bevels and recessed/raised panels, slab with quad caps, tube, knurl, star_slab, holed_surface with real blind holes, outlines from signed distances by marching squares), the `Link` builder (every piece has a part id and the parts it may sit in), `finish()` (mesh, origin on the joint), `uv_tile()`. - `dra_shapes.py` small shapes (screws, hex bolts, domes, holed plates, gears, notched discs, slotted heads, boots...). - `dra_rigdata.py` the links table (name, parent, joint point in arm frame A, builder, tool A/B), finger joint points, and `instantiate(collection, prefix, root_matrix, meshes, tools)` which makes one arm's object hierarchy at rest. **Stage 2 should use it for the AFT/FORE arms** (root matrix = translation (c, -5.795, -4.182) @ rotation 180 deg X). - `dra_parts_base.py` carriage, carriage pinion (its old turret is unused: stage 2 moved the turret to `dra_parts_turret.py`). `dra_parts_arm.py` lower arm, J3 cylinder, J3 piston, upper arm, and `add_curves()` (cable pair over the elbow, two cylinder hoses: Bezier curves parented to the lower arm). `dra_parts_wrist.py` forearm, wrist head, flange, tool A hub, 8 finger links, tool B. `dra_parts_scene.py` showroom, rail kits, chain links (placed with the design's chain driver expressions at frame 1), door fixtures (conformal pads ray-cast onto the door). `dra_audit.py`, `dra_sweep.py`, `dra_preview.py`. ### The file `DoorRobotArm.blend` - Scene `DoorArm | Showroom`: `Showroom | arm A` (gripper, fingers open) at x -1.9 and `Showroom | arm B` (plate) at x +1.8946 (151 rack teeth from A, so both pinions mesh), turntable face at z 1.012, on `Showroom | floor rail` (the ship rail turned over with flanges and rack, on posts); cyclorama, three area lights, world grey. Collections `Showroom | arms` (`... | arm A`, `... | arm B`) and `Showroom | studio`. Objects `Showroom | arm A | `, all at rest: rotation 0, scale 1, origins on the joints (custom property `link`, `version`). - Scene `DoorArm | Ship fit` (frames 1-120, 30 fps, markers CLOSED / RETRACTED INBOARD / OPEN / CLOSE): `00 CONTEXT | from the ship (reference, not part of the asset)` (19 objects copied from `source/ship_context_2026-10-16.blend` with the doors' actions; the user's placeholder carriages hidden; every object has `reference_only`), `DoorArm | rail kit` (`DoorArm_AFT | rail kit`, `DoorArm_FORE | rail kit`, chain trays and 2 x 44 `chain link NN` at frame 1, linked duplicates of `DoorArm | chain link`), `DoorArm | door fixtures` (`DoorArm_ | door fixture ` at the closed doors, origin on the attach point, rotation 0, property `version` and `attach_local`). No arms in the ship and no drivers yet (stage 2 added them, see above). - Meshes `DoorArm | ` (one per moving link, several material slots), shared by both showroom arms. Every mesh stores `parts`, `seats`, `decals` (per part id) and `joint_A`; the upper arm and lower arm store `gland_U08` / `gland_L17` (cable ends, link coordinates). - Materials `M_DoorArm_PaintWhite, _Gunmetal, _Steel, _Rubber, _Orange, _Glass, _Lamp`: plain colours now (stage 3 dresses them). Markings are thin floating geometry (0.4 mm proud) in `M_DoorArm_Orange`, no text anywhere, so no decal atlas is needed (the design's `M_DoorArm_Decals` is not used). - UVs on every mesh: UV0 `UVMap` (smart project per mesh; the bake repacks them into one atlas), UV1 `UV_Tile` (box projection in metres). ### Checks (all pass) - `build/geo_report.json`: 0 n-gons, 0 open edges (except on the floating markings, counted apart), 0 zero-area faces, 0 duplicate faces, 0 non-manifold edges; crossings in the rest pose: 0 between parts inside a link (a part may sit 1-2 mm in its declared seat), 0 between the objects of each showroom arm and the floor rail, 0 for the cable/hose curves (ends in their glands), 0 in the ship scene (rail kits, chains, fixtures against each other and the ship context). - `build/geo_sweep.json`: each joint turned through more than the door animation's range, others at rest, real meshes: J1 -180..180, J2 -58..+15 (needs -53..+10), J3 -30..+35 (with the cylinder turned and the piston slid as the rig will), J4 -60..60, J5 -80..+5 (needs -74.4..-40), J6 -60..60, and the grip closed 0..1 with the door's knob fixture on the tool axis: 0 crossings for both versions. Closed, the hooks wrap behind the knob's head 13 mm clear (`previews/geo/geo_gripA_closed_on_knob.png`). This is not the rig's check: stage 2 still runs all joints together along the real IK path. ### Triangles (LOD0, stage 1; stage 2's numbers are in its section above) Arm A (gripper) 159,075, arm B (plate) 136,479 (design budget 151,500 / 137,500). Arm A: 73,395 quads and 12,285 triangle faces (86 % of the faces are quads, 0 n-gons). | mesh | tris | quads | tri faces | |---|---|---|---| | lower arm | 35,586 | 16,477 | 2,632 | | turret | 31,890 | 14,814 | 2,262 | | carriage | 23,324 | 10,782 | 1,760 | | forearm | 16,499 | 7,502 | 1,495 | | upper arm | 16,144 | 7,300 | 1,544 | | tool A hub | 9,296 | 4,160 | 976 | | J3 cylinder / piston | 4,176 / 1,056 | | | | tool B | 3,580 | 1,562 | 456 | | each finger proximal / distal (x4) | 2,572 / 1,648 | | | | flange / wrist head / pinion | 2,112 / 1,440 / 672 | | | | rail kit (each) | 11,500 | | | | chain link (x 44 per rail) | 352 | | | | door fixture A / B (each door) | 2,172 / 672 | | | Triangle faces come from fans at the poles of turned parts, the two ends of column-filled caps, non-convex flat caps (triangle fill joined back into quads where possible) and where a loop cut meets a bevel. ### Changes to the design made in the geometry (and why) - Shoulder: drum dia 0.49 (design 0.594): a 0.594 drum on J2 cuts 22 mm into the turret's front housing (its back face is 0.253 from J2). The white ring round the drum in ref1 is a fixed collar on the turret (r 0.252..0.302); the ears are motor pods within 0.27 m of J2 (ref1's pods are that size), caps scaled to ref1 (bezel 0.24, design 0.363); the housing's back moved 8 mm forward. - Lower arm in layers: a narrow beam (inner shells |y| 0.075..0.175 round a dark core and the cylinder's channel) from the drum to the crotch; wide outer shells (|y| 0.17..0.451; cheeks 0.275..0.451 above the crotch) only beyond 0.40 m from J2, so the arm can lean 58 deg forward past the housing and the pods (the door needs 53). - J3 cylinder: middle trunnion = collar with two stub pins in bosses on the channel walls (no pin through the barrel); the barrel has a blind bore the rod slides in. Knob pin 0.046 (the design's 0.11 is larger than the eye's 0.05 bore). Channel floor drops from 0.095 to 0.150 under the rod axis beyond the knee (the cylinder turns 5.2 deg toward it). - Carriage: channel ceiling at the top plate (z -0.044) so the pinion fits over the rack; motor along y beside the pinion (the design's dia-0.12 motor did not fit); side guide rollers run on the rail's side faces; strike pads 5 mm proud (5 mm short of the buffers). The pinion (module 8, 10 teeth, one tooth pointing at the rack at rest) is its own object `DoorArm | carriage pinion`: **stage 2 must turn it with the carriage** (rotation about its axis = carriage travel from frame 1 / 0.040 m, sign so the teeth roll along the rack) to keep it in mesh. The ship racks are phased so it meshes at frame 1 (c = -3.0143 AFT, 9.1143 FORE). - Wrist: head drum r 0.090 (design 0.1045, it reached the flange's knurl); knurl x' 0.0925..0.121, flange face 0.121..0.132. Wrist block body stops 0.198 behind WC (the design's proof proxy); its middle slice (|y| < 0.046) is cut back at the front top where the top finger's motor passes at q5 -62..-80 deg. Fork cheeks (lobes R 0.120) and two wedge blocks (|y| 0.088..0.163) carry ref1/ref6's sloping top; their top line keeps clear of the hub to q5 -80. Finger drive motors dia 0.052, 0.08 long, on the design's line 0.051 from the knuckle (clear of the finger's eye). - Fixture A: stem dia 0.06 (the finger proof used 0.06; the parts list said 0.08). Pads sit 0.5 mm off the door face. - Showroom rail at z 0.505..0.840 (the design's 0.25..0.585 put it under the carriage; the carriage wraps the rail's top 0.255 m as it does in the ship). - Energy chain links are joggled (outer plates on one half, inner plates on the other) so neighbours overlap without touching on the bend; the fixed-end bracket sits past the last link at frame 1. ### Compared with the references (`previews/geo/geo_compare_sheet.png`, ref1 also as `geo_ref1_overlay.png`) In the ref1 overlay (same scale and origin) the joints lie on the reference's joints; the shells did not (CRITIQUE_1 items 2-6 and 9, reworked in stage 2). ref2-ref7 matched in parts and layout. What I could not match, honestly: - The references are dense subdivided render models with layered, sculpted panels; mine are bevelled quad shells with real grooves and raised panels, closer to a game asset. The turret's lower block, the upper arm's hump and the forearm's dial housing are simpler and boxier than in the pictures. - Kinematics win over looks in three places: the drum is smaller and the shoulder ring is a fixed collar; the lower arm's wide shells start 0.40 m from J2 (ref1 shows the white shells nearer the drum); the wrist block is a narrow body with cheeks and side wedges, not ref6's full-width wedge (a full wedge would be hit by the top finger's motor at the door's wrist bend). - The rail of ref1-3 is a thin square tube; the showroom rail is the ship's rail (0.458 x 0.335) with the added running flanges and rack, because that is what the carriage rides in the ship. - Fine reference glyph text is replaced by abstract chevrons, dots and stripes (no text by rule). ## Next (stage 2, rig): done in stage 2 (section above) - Make `DoorArm_AFT` / `DoorArm_FORE` with `dra_rigdata.instantiate()` in the Ship fit scene; solver empties and drivers from `design.json` "drivers"; pinion driver; fixture location drivers (the fixtures already carry `attach_local`); chain link drivers (objects exist, named as in the design); version switch (`DoorArm | CONTROLS`); hooks on the curves made by `dra_parts_arm.add_curves()`; the rig check (all joints along the IK path, every frame). ## Critique 1 of the geometry stage: DONE (Critique, 2026-10-16) `CRITIQUE_1.md`: 5 must, 6 should, 1 nice. Extra views, side-by-side crops and the read-only check scripts are in `previews/critique1/` (the .blend was not saved). Must: (1) version B's neck is 0.434 m, ref6's sketch shows about 0.10-0.15 m (B then needs its own IK offset); (2) turret front housing is a box and the J2 caps sit on pill-shaped pods, ref1-4 show one long side housing ending round each cap, and the shoulder is about 40 % wider than ref7; (3) the perforated drum and its ribbed strip are hidden; (4) forearm and wrist block are boxes, ref1/ref6 show a rounded housing and one sloped wedge; (5) upper and lower arm are straight-edged plates with groove lines, the pictures show curved, layered shells. Also: the forearm has 14 non-manifold edges (F09), not 0. Next: fix the must items (the Designer for item 1's IK offset), rerun geo_audit and geo_sweep, then stage 2. (Done in stage 2: every must and should item; the nice item 12 is not done.)