# Door robot arm: design Designer, 2026-10-16. A standalone project (the user: *"this will be standalone project dont add on the ship yet"*). The ship file is not touched; the doors, rails and pocket come from `source/ship_context_2026-10-16.blend` as reference only. Every number the builder needs is in `design.json` (made by `build/design_make_json.py`; do not edit the JSON by hand, edit the scripts and run them again). Metres, Z up, the ship's world coordinates. What the user asked: model the white rail robot of the seven pictures, *"rig it accordingly and mechanically"*, fit it to the moon pool doors' open/close animation, *"also consider the rail"*, make two versions (with the grab limbs, and the red-sketch plate without them) *"side by side so I can change when I want"*, and *"dont miss details"*. ## 1. Reading the pictures: the mechanism Measured on ref1 (a near-orthographic side view) with a 50 px grid (`reference/crops/r1_grid_*.png`). Arm frame **A** at rest (rest = the ref1 pose, all joint angles 0): origin at the turntable face centre, +X forward (toward the tool), +Y the arm's left (ref1 shows the left side), +Z up. Image to A: X = 1000 - x_img, Z = 1550 - y_img (2000 px original). | joint | what the pictures show | axis | where (ref1 px, A) | metres (A) | |---|---|---|---|---| | J1 turret yaw | the turntable between carriage and turret | +Z | x_img 1000 | origin | | J2 shoulder pitch | the perforated drum, with an orange-ring motor cap on each turret ear, coaxial with it | lateral | (1155, 1315): 155 px BEHIND the J1 axis, 235 px up | (-0.341, 0, 0.517) | | J3 elbow pitch | the black elbow cap with the straight slot ("minus" screw head), on both sides | lateral | (1550, 720) | (-1.210, 0, 1.826) | | J4 forearm roll | the ringed roll section between the upper arm's front block and the forearm (a thin black bearing ring) | along the forearm | x_img 1025-1045 | axis at Z 2.0614 | | J5 wrist pitch | the wrist's round cap with concentric rings, on both sides of the wrist block's front fork | lateral | (565, 613) = wrist centre WC | (0.957, 0, 2.061) | | J6 flange roll | the knurled neck ring in front of the wrist; the gripper hub (or the plate neck) turns on it | tool axis | WC + 60 px = flange face | WC + 0.132 | J4, J5 and J6 meet at the wrist centre: a spherical wrist, so the inverse kinematics splits into position (J1-J3) and orientation (J4-J6) and has a closed form. Three pitch joints (J2, J3, J5), two rolls (J4, J6), one yaw (J1). Round caps that are **not** joints: - the big **slotted cap at the knee** of the lower arm (1393, 1165), with radial slots, orange ring and bolt, on both sides: the bearing caps of the **J3 cylinder's trunnion pin** (see below); - the **big orange-ring cap** on the upper arm (1262, 565), both sides: a gearbox cover (J4 drive), not an axis; - the **black dial with the cross** on the forearm's dark side plate (910, 590), both sides: the J5/J6 drive cover; - the **knurled knob** at the end of the truss (1762, 888): the pin of the cylinder's rod eye; - the orange-ring caps on the turret ears: the J2 motors (coaxial with J2). **The truss and its rod are the elbow's actuator, a hydraulic cylinder.** The "ANN" truss with triangular cut-outs is a lever fixed to the upper arm behind the elbow (two plates in the arm's middle plane). The black rod runs from the truss knob down into a channel on the lower arm's back. Its line points at the knee cap's centre within 4 degrees in ref1 (knob to cap -369,+277 px; the rod -242,+162 px), and it narrows at a collar part way along (ref1, ref3, ref5): a barrel with a gland and a piston rod. If it were a fixed-length parallel link, its lower end would sit on a crank at the shoulder and show below the lower arm, which no view shows. So: a double-acting cylinder on a middle trunnion at the knee (the slotted caps cover the trunnion pin), rod eye on the knob pin. Its length follows J3 (0.716-1.245 m over the whole animation); it is driven, not a separate joint. (The brief asked for "parallel links that really stay parallel"; the pictures show an actuator, not a parallelogram. What that requirement protects is kept: the rod's eye stays on the knob pin at every frame, proven to 0.002 mm.) **ref7 is a back view**, not a front view: no belt drive, cable bundle or forearm is in front of the turret, the turret's back shows screws and a latch, and the cylinder's barrel rises in the middle of the lower arm's back above a channel with cross rungs (the "ribbed centre strip"). Its turret is turned 90 degrees to the rail (the rail runs across the picture). The belt drive and the 7-cable bundle are on the turret's FRONT (under the forearm in ref1). **The gripper (version A)**: four fingers at 90 degrees round the hub (top, bottom, left, right). ref1 shows top, bottom and the near side finger, with the far side finger peeking under it; ref2 and ref6 show the near finger foreshortened toward the camera. Each finger: a bracket on the hub's front rim, a knuckle pin (round caps), a knurled drive motor fixed to the bracket pointing back and outward 20 degrees (r1: from the knuckle at WC+(107, 79) px to (47, 99) px), a proximal link with a ribbed rubber boot and a threaded tendon rod, a distal pin, and a distal link ending in a hook turned inward. Two finger joints, driven together by one grip control. **Lateral sizes**: from ref7 (scale to ref1 about 1:2 at the turret's depth) and ref2/3/6. The lower arm's root is narrower (Y +-150) between the turret ears and widens to +-205 beyond 0.38 m from J2; the upper arm sits between the lower arm's two yoke cheeks. ## 2. Scale One scale for the whole arm: **0.0022 m per ref1 pixel**. It was chosen by search (`build/design_search*.py`, `design_variants2.py`): smaller arms open the elbow past the truss's limit and need a longer cylinder stroke; larger arms fold the elbow tighter and fill the pocket. Main sizes at this scale: | | ref1 px | metres | |---|---|---| | carriage (along rail x across x height) | 390 x 390 x 185 | 0.858 x 0.858 x 0.407 | | turntable | dia 260 | 0.57 | | J2 behind / below the turntable face | 155 / 235 | 0.341 / 0.517 | | lower arm J2-J3 (dog-leg through the knee) | 714 | 1.571 | | forearm axis length J3-WC (along / offset) | 985 / 107 | 2.167 / 0.235 | | wrist centre to flange face | 60 | 0.132 | | gripper hub dia x length | 125 x 75 | 0.275 x 0.165 | | upright height of the whole arm (carriage foot to the upper arm top) | 1265 | 2.78 | | reach J2 to wrist centre, max | 1705 | 3.75 | ## 3. Version B (ref6's red sketch) The red X strikes out the hub and the four fingers. In their place the user drew two lines spreading from the wrist to a large quadrilateral: a **flared neck** and a **flat square plate** perpendicular to the tool axis. The quadrilateral is near-square on the page while the forearm behind it is strongly foreshortened: ref6 looks almost along the tool axis, so the plate's face is toward the camera and the neck shows short. Reading: the wrist (J5 cap) and the J6 flange stay; a trumpet-shaped neck (dia 0.154 at the flange to 0.29 at the plate) carries a square plate 0.55 x 0.55 x 0.044 m (2.0 x the hub's diameter, as drawn). **How the plate sits on the curved door.** The door's inner face is a cylinder-like curve of radius about 8.6 m. Over the plate's 0.55 m the face falls away by only 4.4 mm (sagitta), so the plate stays flat (as drawn) and bolts to a **conformal pad** 0.60 x 0.60 m on the door: its underside follows the face (ray-cast), its top is flat, 0.018-0.023 m thick. The pad is a door fixture, not part of the arm. Eight bolts through the plate into the pad. **Why the neck is 0.434 m long.** With that length the plate's door face lands exactly where version A's knob is held: both versions share **one wrist centre and one arm pose**. Switching versions then only swaps the tool and the door fixture; the arm does not move, the rig has one set of drivers, and one proof covers both. The neck is straight for 60% of its length and flares over the last 40%, which reads like the sketch from the sketch's own viewpoint. ## 4. Fit to the scene ### The arm hangs The pocket's rail is a plain box (0.458 x 0.335 m) whose top 0.08 m is buried in the deck; 0.255 m of it shows. Nothing can pass over it, so the reference carriage is turned over: the arm hangs **upside down** from a carriage that wraps the rail's visible part from below. Rig root `DoorArm_AFT` at (0, -5.795, -4.182), rotated 180 degrees about X; the carriage's turntable face is its underside at z -4.182, its cheek tops 20 mm under the deck (z -3.775). ### The rail problem The door slides 6.14 m; the rail gives 6.49 m between the end wall and its inner end. A carriage of the reference's proportions is 0.858 m long, and the hanging arm is about 1 m wide across its joints, so it must also stand off the end wall. Solution: - **travel**: the carriage runs 5.10 m, from x -8.116 (end-wall side) to -3.014 (rail's inner end) on the AFT rail; FORE mirrored in x = 3.05 (9.114 to 14.216); - **schedule**: it runs at 0.831 of the door's speed, `c = -3.198458 + 0.830925 * door_x` (AFT), so it reaches each end exactly when the door does; the arm's joints take up the remaining 1.04 m smoothly over the slide (no jolt when the carriage stops); during frames 1-12 and 108-120 the door moves 1.22 m inboard/out while the carriage stands at its inner end: the arm takes all of that; - **running gear** (rollers on which faces): the user's rail has no face that looks up, so the asset ADDS two **running flanges** (steel bars 0.05 x 0.03 m) along both side faces at the rail's bottom. Four **load wheels** (dia 0.10) roll on the flanges' tops (they carry the weight), four **counter-rollers** (dia 0.06) under the flanges hold the arm's tipping moment, four **side guide rollers** on vertical axles run on the flanges' outer edges. A **rack** (module 12) under the rail's bottom face and a pinion on the carriage's drive motor move it; - **end stops**: steel blocks with rubber buffers under the rail at both travel ends; the carriage stops 10 mm short of them in normal running (they are safety stops); - **energy chain**: the moving carriage needs power. A 44-link chain (3.30 m, bend radius 0.15) lies on its side in a tray hung under the deck inboard of the rail (y -5.28..-4.88), fixed at mid-travel, its moving end on a bracket on the carriage's inboard cheek. The tray's well-side end is cut on a slant to stay clear of the moon pool well's rounded edge. The links are rigid objects driven from the carriage position (they never stretch: proven, see 7). The user's rail object is not changed: everything above is an added part of this asset (`DoorArm_ | rail kit`). ### Where the arm holds the door On the door's inner face, **0.90 m in from its pocket-side end and 1.10 m lower than its top edge**: door-local (-2.10, -2.2178, 1.7179) on the AFT door, (+2.10, -2.2178, 1.7179) on the FORE door; the face normal there is (0, 0.9089, 0.4171). The tool's axis is the face's normal (into the door). Why there: - the carriage cannot follow the door past the rail's inner end (x -2.545) while the closed door lies over the moon pool well (x -2.78..3.05), so the hold must be near the door's pocket end; - high on the face the normal points mostly inboard, so the wrist centre (0.63 m off the face) stays 0.74 m or more off the J1 axis: no shoulder singularity, the turret turns only 50 degrees in the whole animation; - higher holds fold the elbow tighter and bring the forearm into the turret's front cable bundle at the open door; lower holds bring the wrist centre nearer the J1 axis, so the turret turns more (65-85 degrees) and the wrist margin shrinks; - the 0.60 m pad and the knob's 0.32 m base both fit on the face with room to the edges. ### Joint ranges over the whole animation (both doors, both versions; FORE mirrors J1, J4, J6) | joint | AFT (deg) | FORE (deg) | limit set (deg) | |---|---|---|---| | J1 | 32.7 .. 82.4 | 97.6 .. 147.3 | -170 .. 170 | | J2 | -52.9 .. 9.8 | same | -95 .. 45 | | J3 | -24.4 .. 29.1 | same | -40 .. 55 | | J4 | -52.5 .. -10.8 | 10.8 .. 52.5 | -170 .. 170 | | J5 | -74.4 .. -40.0 | same | -120 .. 120 (never within 40 of 0) | | J6 | 11.5 .. 52.3 | -52.3 .. -11.5 | -170 .. 170 | Elbow inner angle 38-92 degrees (the reference pose has 63); reach 36-73% of the arm's full reach; the fastest joint moves 4.1 degrees per frame (J3). The J3 cylinder turns only -5.2..+1.3 degrees inside its channel. The wrist always bends to the forearm's +Z side (q5 < 0). On that side only the two cheek lobes (R 0.121 m round the wrist centre) reach forward; the wrist block's body ends 0.198 m behind the wrist centre (the proof's proxy; the finger motors pass it with 29-34 mm), and the small top cylinder F15 sits 0.29 m away. The hub's or the neck's back face, 0.132 m out on the flange, clears the lobes by 9-11 mm at any bend. ## 5. Rig and inverse kinematics ### Decision: object hierarchy, armature only for the export Each moving part is its own object with its origin on its axis, rotation 0 and scale 1 at rest (rest = the ref1 pose). Drivers sit on the objects' channels. This is what the user's Blender runs without Python (simple expressions), what the project's other rigs do, and it keeps every part inspectable. For Unreal the export stage builds a deform armature from the same hierarchy (one bone per object, rigid weights, the elbow cables blended) and bakes the 120 frames into an animation (see 9). Hierarchy per arm: rig root (static) > carriage (location.x) > turret (rot z = q1) > lower arm (rot y = -q2) > { J3 cylinder (rot y = -cyl) > J3 piston (location x, z) ; upper arm (rot y = -q3) > forearm (rot x = q4) > wrist head (rot y = q5) > flange (rot x = q6) > { tool A hub > 4 x (finger proximal > finger distal) ; tool B } }. The door fixtures are world objects whose location follows the door (the door never turns). Objects, origins and channels: `design.json` "objects", "kinematics.joints". ### Closed-form inverse kinematics Frame C = the hanging arm's base frame (world turned 180 degrees about x, origin at the turntable face centre). Door location d (from the door object), carriage c = A + B d_x. Wrist centre in C: X = (1 - B) d_x + (w_x - A), Y = (y_b - w_y) - d_y, H = (z_b - w_z) - d_z with w = the wrist centre's door-local offset (attach point + 0.63 m along the normal), y_b = -5.795, z_b = -4.182. q1 = atan2(Y, X) (the arm turns to face the wrist centre) R = sqrt(X^2 + Y^2) + j2r, Hh = H - j2h (j2r = 0.341: J2 is behind J1; j2h = 0.517) phi_l = atan2(Hh, R) + acos((L2^2 - L3^2 + R^2 + Hh^2) / (2 L2 sqrt(R^2 + Hh^2))) elbow up, as in ref1 q2 = phi_l - phi_l0 (phi_l0 = 2.156857 rad, the ref1 lower-arm direction) phi_f = atan2(Hh - L2 sin phi_l, R - L2 cos phi_l) - beta (beta = atan2(a3, d4) = 0.108205) q3 = phi_f - phi_l + phi_l0 Spherical wrist: R3 = [x3 y3 z3] with x3 = cos(phi_f) X_T + sin(phi_f) Z_T, y3 = Y_T, z3 = cos(phi_f) Z_T - sin(phi_f) X_T, X_T = (cos q1, sin q1, 0), Y_T = (-sin q1, cos q1, 0), Z_T = (0, 0, 1). With the tool axes (x_t, y_t, z_t) in C (constants per door): M11 = x3.x_t, M21 = y3.x_t, M31 = z3.x_t, M12 = x3.y_t, M13 = x3.z_t, and (roll-pitch-roll Rx(q4) Ry(q5) Rx(q6), branch q5 < 0): q5 = -acos(M11), q4 = atan2(-M21, M31), q6 = atan2(-M12, -M13) J3 cylinder (lower-arm frame): knob k = (J3 - J2) + Ry(-q3) (knob - J3), trunnion t: L = |k - t|, cyl = atan2(k_z - t_z, k_x - t_x) - beta_c0; the piston slides along the rod axis by L - 1.0151. ### Driver plan (simple expressions only) Seven solver empties per arm carry custom properties; each reads only earlier empties (no property reads its own object), so one frame change evaluates the chain in order: | empty | properties | reads | |---|---|---| | IK1 target | c, X, Y, H | the door's location | | IK2 yaw | q1, R, Hh | IK1 | | IK3 shoulder | phi_l, q2 | IK2 | | IK4 elbow | phi_f, q3 | IK2, IK3 | | IK5 wrist matrix | M11, M21, M31, M12, M13, kx, kz | IK2, IK4 | | IK6 wrist angles | q4, q5, q6, L, cyl | IK5 | | chain solver | M, a, bx | IK1 | The exact expressions (168 per arm: 33 for the solver and the joints, 135 for the energy chain; all under Blender's 256-character limit) are in `design.json` "drivers" for each door, ready to apply; the switch, grip and fixture drivers are specified in "controls" and "fingers". Joint drivers: carriage location.x = c, turret rotation_euler.z = q1, lower arm .y = -q2, upper arm .y = -q3, forearm .x = q4, wrist head .y = q5, flange .x = q6, J3 cylinder .y = -cyl, J3 piston location.x / .z = rest + u (L - L0). Energy-chain link i: location x, y and rotation z from the chain solver (straight moving run, half-circle bend, straight fixed run; conditionals `a if c else b`). Grip (version A): `DoorArm | CONTROLS["grip"]` g in 0..1; proximal turn 14.7 degrees and distal 41.0 degrees toward the tool axis (top/bottom fingers on rotation y, left/right on rotation z, signs in `design.json` "fingers"). Closed, the hooks sit 6 mm behind the knob's head and 17 mm above its stem; the closing path clears the head by 6 mm or more. Cables over the elbow: Bezier curves with hooks (ends on each arm part, the middle point on an empty halfway between them by two Copy Transforms constraints, influence 1.0 then 0.5: no Python). All other cables have both ends on one part and are plain meshes. ## 6. Two versions: switching and side by side - **Switch**: one empty `DoorArm | CONTROLS` with `version` (0 = A gripper, 1 = B plate). Drivers on `hide_viewport` and `hide_render`: A parts `v > 0.5`, B parts `v < 0.5` (both arms, tools and door fixtures). The arm pose does not change. - **Side by side**: a second scene `DoorArm | Showroom`: both versions upright on one floor rail like the references (the ship rail turned over, on short posts), A at x -1.9, B at x +1.9, made of linked duplicates of the arm meshes at rest (the ref1 pose, fingers open), in a light grey cyclorama studio with key, fill and rim lights. ## 7. Proof (run before handing over) `build/design_ik_check.py` (headless, frames 1-120 step 1, both doors, both versions; `build/check_*.json`) and `build/design_driver_proto.py` (builds the actual driver chain in Blender; `build/proto_*.json`): | check | AFT A | AFT B | FORE A | FORE B | |---|---|---|---|---| | frames | 120 | 120 | 120 | 120 | | tool point on the door target (formula FK) | 0.0014 mm | 0.0014 mm | 0.0020 mm | 0.0020 mm | | tool axes (single-precision floor) | 0.03 deg | 0.03 deg | 0.03 deg | 0.03 deg | | joint limits | inside | inside | inside | inside | | min abs(q5) / elbow inner | 40.0 / 38-92 deg | same | same | same | | wrist centre from J1 axis, min | 0.74 m | 0.74 m | 0.74 m | 0.74 m | | carriage inside its travel | yes | yes | yes | yes | | J3 cylinder: length, piston, barrel rear | 0.716-1.245 m; -0.084..0.445 in barrel; rear 0.12 m inside the lower arm | same | same | same | | lowest clearance to the ship and rail kit (proxies) | 0.107 m turret / inner end stop, f120 | plate 0.017 m above the door = the pad (by design) | 0.107 m | 0.019 m (pad) | | lowest self clearance (proxies) | 0.009 m hub / wrist lobe (design gap) | 0.011 m neck / wrist lobe (design gap) | 0.009 m | 0.011 m | Next lowest real clearances: turret side cables to the end stops 0.118 m, fingers to the door 0.142 m, elbow and yoke to the end wall 0.19-0.20 m, truss to the lower arm's back 0.081 m, knee caps to the turret ears 0.091 m. Driver prototype (Blender's own evaluation after ONE frame_set per frame, AFT and FORE): 172 drivers, **all simple and valid**; tool point error 0.055 mm, axes 0.000 deg, joint values within 0.003 deg of the Python solution, piston eye on the knob within 0.002 mm, energy chain spacing exact (0.78 mm chord on the bend), first link at the carriage, all links inside the tray; the version switch hides and shows as it should, viewport and render. Honest limits: the clearance proxies are boxes and prisms at the design's sizes, not the final meshes; the Coder's check stage repeats this with the real meshes (BVH overlap of every moving mesh against everything, every frame). The proxies are deliberately generous except at the wrist, where the 9-11 mm gap between the hub/neck and the wrist lobes is a designed clearance that the modelled parts must keep. Pictures of the proxies in pose: `previews/design_pose_AFT_A_*.png`. ## 8. Materials, markings, bake, triangles | material | parts | source | |---|---|---| | M_DoorArm_PaintWhite | all white shells | `pd_look.paint(grey=(0.80,0.80,0.78), metallic 0, rough 0.38-0.55, wear 0.25, grime 0.18, dust 0.10, coat 0.30)` on the Poly Haven `blue_metal_plate` scan already on disk (its light/dark, roughness and relief only): satin off-white powder coat with fine orange peel, few chips (the ship is clean) | | M_DoorArm_Gunmetal | carriage, drum, cap rings, side plates, dials, wrist head, fingers, plate B, rail kit, fixtures | pd_look "gunmetal" style; the carriage with more edge wear (r1-3 show scratched edges) | | M_DoorArm_Steel | screws, pins, piston rod (rough 0.12), gland, knurls, wheels, rack, flanges, buckle | `pd_look.steel` + the ModSci pack's `T_Metal_Brushed_N.png` | | M_DoorArm_Rubber | cables, hose, belt, finger boots, buffers, chain links | `pd_look.dark`, rough 0.62-0.78 | | M_DoorArm_Orange | the thin orange rings in the cap stacks, the hose band | safety orange (0.93, 0.36, 0.08) under the masks | | M_DoorArm_Glass | the big caps' dark recessed discs | dark glossy, coat 1.0 | | M_DoorArm_Lamp | indicator lights, the light slot | faint cool white emission (an indicator, not a light source) | | M_DoorArm_Decals | the flat markings | `T_DoorArm_Decals.png`, 1024, made by script from vector shapes | Markings (all orange, shapes only, **no letters, numbers, logos or maker text**): hexagon outline and small triangle on the lower arm's left side; hatch stripes in a frame on both sides of the turret's front housing; a striped square on its lower block; 2x3 dot grids on the forearm; triangles and dots on the wrist block; abstract chevrons in place of the reference's glyphs on the upper arm; corner ticks on plate B. Full list: `design.json` "markings". Bake: UV0 = one 4096 atlas per arm (about 512 px per metre on the large shells): `T_DoorArm_Masks` (R occlusion, G convex edges, B cavities) and `T_DoorArm_BevelNormal` (bevel shader, radius 4 mm), the way `models/docking-arm/build/surfaces.py` does it; UV_Tile in metres for the tiling scans (paint 1.25 m, gunmetal 0.70, steel 0.50, rubber 0.40). Each bake in its own call. Triangles (LOD0): about 152k per arm with the gripper, 138k with the plate, plus 7k per rail kit and 5.5k for the chain. The reference is a dense subdivided render model; ours keeps its silhouette with 2-segment chamfers that the bevel-normal bake rounds, 32-48 sides on caps over 0.2 m, 16-24 on small round parts. Per-link budget: `design.json` "tri_budget". ## 9. Objects, collections, build, export, renders - Names: `DoorArm_ | `, shared `DoorArm | ...`, showroom `Showroom | ...`. Collections: `DoorArm | AFT`, `DoorArm | FORE`, `DoorArm | solver (hidden)`, `DoorArm | rail kit`, `DoorArm | door fixtures`, `DoorArm | collision`, `CONTEXT | ship (reference only)` (never exported), `Showroom | arms`, `Showroom | studio`. Scenes: `DoorArm | Ship fit` (1-120, 30 fps, the door markers) and `DoorArm | Showroom`. - Each link's static parts are joined into the link's one mesh (several material slots). No booleans, quads, UV0 + UV_Tile on every mesh. `UCX_` hulls per link from the clearance proxies (`build/design_parts.py` PROXIES). - Build: one entry `build/build.py -- `: context, parts, rig, check, surfaces, showroom, ucx, export, renders (each call under 9 minutes; bakes and renders separate). Back up `DoorRobotArm.blend` to `versions/vNN_/` before overwriting it. - Export (Unreal): `fbx/SK_DoorRobotArm_A.fbx` and `_B.fbx` (one skeleton; the armature made from the hierarchy at export, rigid weights, cables blended, the chain links as bones), animations `A_DoorRobotArm_AFT_OpenClose.fbx`, `..._FORE_OpenClose.fbx` (frames 1-120) and `A_DoorRobotArm_Grip.fbx`; door fixtures and rail kit as static meshes; per-link static parts with UCX for a Blueprint build if wanted. In Unreal the door's timeline and the arm's animation play together. - Renders (Cycles, GPU): showroom views matching ref1, ref2, ref3, ref4, ref5, ref6 (A and B from the same camera), ref7, and both side by side; in-scene frames 1, 12, 30, 48, 90 for both versions with both arms, lit (the pocket is dark: area lights under the deck and a fill from the well). List and cameras: `design.json` "renders". - Checks the build must pass: `design.json` "checks". ## 10. Open points and risks - The fold of the elbow (38 degrees inner angle at the open door) puts the upper arm between the lower arm's yoke cheeks; the yoke's crotch must stay 0.55 of the knee-to-elbow length below J3 (as the proxies assume). - The wrist block must keep the swing zone on its upper front free (0.25 m from the wrist centre); the reference's wrist top is sloped this way, but the modelled details (fin, top cylinder, orange marks) must respect it. - The arm is large (2.8 m tall upright, reach 3.75 m): this is what reaching a door 2-3 m away from a rail under the deck needs with the reference's proportions. The pocket is big enough (proven), but it will dominate the pocket in renders. - The ship's door material has four missing images (an old absolute path in the ship): not ours to fix; the context renders will show the door without its textures. - The design reads the doors, rails and pocket from the context copy of 2026-10-16. If the ship's doors or rails change, rerun `design_probe*.py`, `design_make_json.py`, `design_ik_check.py` and `design_driver_proto.py`. ## 11. Parts list (every part, per link) Sizes and positions in metres in each object's own frame (A axes at rest unless the row says otherwise). `refs`: r1-r7 are the seven references; `added` = needed by the mechanism but not seen in the pictures. Shapes: box, rbox (rounded box: x, y, z, radius), cyl (dia, length), ring (outer dia, inner dia, thickness), stack (rings: dia, height, material, from the face outward), plate2d (side outline in the link's X-Z plane, extruded across Y), tube (dia; path points), U (bent-tube handle), knurl, cone, decal. Source of truth: `design.json` "parts_m".