@operato/scene-manufacturing 10.0.0-beta.2 → 10.0.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robot-arm-3d.js","sourceRoot":"","sources":["../src/robot-arm-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Robot arm 3D — articulated chain renderer.\n *\n * Build pipeline:\n * 1. Resolve chain (state.chain | preset | default 6-axis-industrial).\n * 2. Resolve style (state.style preset, with per-property overrides).\n * 3. Resolve joint values (state.joints array OR object map; missing\n * entries default to 0 and clamp to chain[i].range).\n * 4. If state.target is present, run CCDIK to solve joint values\n * reaching that target; commit the solved values back via the\n * smoothing controller (next tick converges to them).\n * 5. Forward-kinematics walk → emit one Object3D per joint frame,\n * each carrying its joint housing mesh + the link mesh extending\n * along local +Z to the next frame.\n * 6. Add gripper at the end-effector frame.\n * 7. Optional reach sphere (wireframe).\n *\n * Joint frames are real Object3D children, so the rotation set via\n * `frame.rotation.<axis> = jointValue` on each frame produces the right\n * world-space pose without explicit matrix math at render time. CCDIK\n * runs in matrix math (separate from this scene-graph walk) when needed.\n */\n\nimport * as THREE from 'three'\nimport {\n RealObjectGroup,\n resolveMaterial3d,\n applyMaterial3dProps,\n type Component,\n type Material3D\n} from '@hatiolab/things-scene'\nimport {\n STYLES,\n CHAIN_PRESETS,\n DEFAULT_GRIPPER,\n type RobotArmStyle,\n type StyleName,\n type ChainPresetName,\n type GripperConfig,\n type LinkShape,\n type JointHousing\n} from './robot-arm-styles.js'\nimport {\n forwardKinematics,\n solveCCDIK,\n maxReach,\n isSixAxisZYYZYZ,\n resolveBaseYaw,\n analyticalIk6Axis,\n type ChainElement,\n type JointAxis\n} from './robot-arm-ik.js'\n\nconst _AXIS_VEC: Record<JointAxis, THREE.Vector3> = {\n x: new THREE.Vector3(1, 0, 0),\n y: new THREE.Vector3(0, 1, 0),\n z: new THREE.Vector3(0, 0, 1)\n}\n\nconst DEG2RAD = Math.PI / 180\nconst RAD2DEG = 180 / Math.PI\n\n/**\n * Length (chain-local units) of the virtual end-extension used to bias\n * CCDIK toward \"gripper pointing world-down\". Longer = stronger orientation\n * bias but reduces effective reach; shorter = closer to position-only.\n * 30 is a moderate default that handles typical pick-and-place poses\n * without sacrificing reach for normal-sized arms.\n */\nconst DESCENT_BIAS = 30\n\n/** Raycast no-op — assigned to non-interactive helper meshes (e.g. the\n * reach-sphere visualization) so clicks pass through to the real body. */\nconst NO_RAYCAST: THREE.Object3D['raycast'] = () => {}\n\nexport class RobotArm3D extends RealObjectGroup {\n private _smoothing?: { current: number[]; target: number[]; speed: number }\n private _animFrame?: number\n private _isAnimating = false\n private _chain: ChainElement[] = []\n private _jointFrames: THREE.Object3D[] = []\n\n build() {\n super.build()\n\n const state = this.component.state as any\n // Geometry mapping (per user contract):\n // width × height = robot footprint (the base pedestal occupies this)\n // depth = robot height (= max reach when fully extended up)\n //\n // The chain preset's lengths are treated as PROPORTIONS — we scale them\n // so the sum matches `effectiveDepth` (with a small base-height\n // reservation). User can still override by passing absolute lengths via\n // `state.chain[i].length`; the same scale is applied so `depth` stays\n // the source of truth for overall robot height.\n const baseHeight = this._baseHeight(state)\n const targetReach = Math.max(this.effectiveDepth - baseHeight, 1)\n const chain = this._resolveChain(state, targetReach)\n const style = this._resolveStyle(state)\n let joints = this._resolveJoints(chain, state)\n\n // If a target is set, solve IK and use the solved joint values as the\n // smoothing-controller's new target. CCDIK works in radians; convert\n // both the input joints and the output back to user-facing units\n // (degrees for revolute) before storing.\n //\n // CRITICAL: IK starts from smoothing.current (the visual joint pose\n // mid-transit) when present, NOT from state-derived joints. CCDIK is\n // path-dependent — different start poses converge to different valid\n // solutions reaching the same TCP. If a rebuild happens DURING transit\n // (e.g. `set('gripper', state:1)` closing the gripper after pick),\n // re-solving from state joints (typically 0,0,0...) would produce a\n // *different* solution than the path the arm was already on, snapping\n // smoothing.target onto a new joint configuration. The arm — and any\n // carried box — would then race toward that alternate solution,\n // sometimes hitting `allReached` almost instantly (if the alternate\n // happens to be close to current), which fires `tcp-reached`\n // prematurely and makes pickAndPlace reparent the carrier to the\n // place holder long before the arm has actually traveled there.\n const target = state.target\n if (target && Number.isFinite(target.x) && Number.isFinite(target.y) && Number.isFinite(target.z)) {\n const targetVec = new THREE.Vector3(target.x, target.y, target.z)\n const targetYaw = Number.isFinite(target.yaw) ? (target.yaw as number) : undefined\n const ikStart = this._smoothing?.current?.slice() ?? joints\n const radJoints = this._toRadians(chain, ikStart)\n const ikValues = this._solveIkDescent(chain, radJoints, targetVec, targetYaw)\n const solvedUser = this._fromRadians(chain, ikValues)\n this._smoothing = {\n current: ikStart.slice(),\n target: solvedUser.slice(),\n speed: this._jointSpeed(state)\n }\n // visible position = current (interpolated by tick)\n joints = ikStart.slice()\n } else if (this._smoothing) {\n // no target — freeze where we are, NOT animate toward stale state\n // joints (which may be 0,0,0... and unrelated to the visual pose).\n this._smoothing.target = this._smoothing.current.slice()\n }\n\n this._chain = chain\n this._buildArm(chain, style, joints, baseHeight)\n this._buildGripper(chain, style, state)\n this._buildReachSphere(chain, state, baseHeight)\n this._buildBase(state, style, baseHeight)\n\n // Animation lifecycle (smooths joint values toward solved target).\n this._stopAnimation()\n if (this._smoothing) {\n this._startAnimation()\n }\n\n // Re-mount any Carriable child whose object3d was orphaned by the\n // build's `clear()`. Without this, ANY structural change while a\n // carrier is held (most commonly the gripper-close `set('gripper',\n // {state:1})` inside pickAndPlace) tears down `_endFrame` along with\n // the carrier mounted onto it — the box vanishes mid-flight.\n //\n // The component-side child list survives a 3D rebuild (only the\n // scene-graph was reset), so we walk it and re-execute the holder's\n // attach-point policy. Uses `add()` (not `attach()`) because the\n // orphaned object3d's matrixWorld is stale; we want the explicit\n // localPosition/localRotation, not whatever world pose was last\n // computed on the old gripper frame.\n this._remountCarriers()\n }\n\n private _remountCarriers() {\n const holder = this.component as any\n if (typeof holder.attachPointFor !== 'function') return\n const children: Component[] =\n holder.components ?? holder.children ?? []\n for (const child of children) {\n if (!(child as any)?.isCarriable) continue\n const obj3d = (child as any)._realObject?.object3d\n if (!obj3d) continue\n const point = holder.attachPointFor(child)\n if (!point?.attach) continue\n point.attach.add(obj3d)\n const lp = point.localPosition ?? { x: 0, y: 0, z: 0 }\n obj3d.position.set(lp.x, lp.y, lp.z)\n if (point.localRotation) {\n obj3d.rotation.set(point.localRotation.x, point.localRotation.y, point.localRotation.z)\n } else {\n obj3d.quaternion.identity()\n }\n }\n }\n\n /**\n * IK with a \"point gripper downward\" bias.\n *\n * CCDIK is position-only — it solves for joint values that put the\n * end-effector at the target, without constraining the gripper's\n * orientation. With no orientation constraint, valid solutions\n * include twisted poses (gripper sideways / upside-down) — typical\n * pick-and-place tasks then look broken: the box gets gripped at a\n * wrong angle, or after release the carrier \"launches\" off because\n * the gripper was facing some weird direction at the moment of\n * release. The arm can also visibly \"lock\" near joint limits trying\n * to satisfy a position-only target through a contorted path.\n *\n * Trick — augment the chain with a virtual rigid extension along the\n * last frame's +Z, length L. When CCDIK puts this extended end at\n * `target + L * (-Ẑ_chainLocal)` (i.e. the original target shifted\n * downward by L in chain-local), the only way the chain can satisfy\n * both placements simultaneously is by orienting the last frame's +Z\n * to point in the chain-local -Z direction = world -Y direction =\n * gripper pointing straight DOWN. Best-effort even when CCDIK can't\n * fully converge — the solver pushes the chain in the right\n * orientation, which matches what a real pick-and-place arm does.\n */\n \n private _gripperTcpZ(style: RobotArmStyle, state: any): number {\n const cfg: GripperConfig = {\n ...DEFAULT_GRIPPER,\n ...((state.gripper as GripperConfig) ?? {}),\n ...(state.gripperType ? { type: state.gripperType } : {})\n }\n if (cfg.type === 'none') return 0\n const linkRadius = style.linkRadius\n switch (cfg.type) {\n case 'parallel': {\n const stroke = cfg.stroke ?? linkRadius * 1.8\n const fingerWidth = cfg.fingerWidth ?? linkRadius * 0.45\n const fingerLength = stroke * 1.2\n return fingerWidth * 1.8 + fingerLength\n }\n case 'three-finger': {\n const stroke = cfg.stroke ?? linkRadius * 1.5\n const fingerWidth = cfg.fingerWidth ?? linkRadius * 0.4\n const fingerLength = stroke * 1.2\n return fingerWidth * 1.5 + fingerLength\n }\n case 'suction': {\n const diameter = cfg.diameter ?? linkRadius * 2.4\n return diameter * 0.9\n }\n case 'magnetic': {\n const diameter = cfg.diameter ?? linkRadius * 2.6\n return diameter * 0.25\n }\n }\n return 0\n }\n\n private _solveIkDescent(\n chain: ChainElement[],\n radJoints: number[],\n targetVec: THREE.Vector3,\n targetYaw?: number\n ): number[] {\n const state = this.component.state as any\n const style = this._resolveStyle(state)\n const tcpZ = this._gripperTcpZ(style, state)\n\n const augChain = chain.map((c, i) =>\n i === chain.length - 1 ? { ...c, length: c.length + tcpZ } : c\n )\n\n // Fast path: analytical IK for the standard 6-axis Z-Y-Y-Z-Y-Z chain\n // (industrial + cobot presets). CCDIK is greedy and produces twisted\n // poses; analytical IK is closed-form, deterministic, and gives the\n // natural \"elbow up, gripper straight down\" pose every time.\n //\n // The implementation lives in `./robot-arm-ik.js` so the unit tests\n // exercise THE SAME code that runs at scene-time. (An earlier version\n // of this file kept a private duplicate, which silently drifted from\n // the tested implementation — easy to introduce subtle bugs that\n // tests miss.)\n if (isSixAxisZYYZYZ(augChain)) {\n const analytical = analyticalIk6Axis(augChain, targetVec, radJoints, targetYaw)\n if (analytical) return analytical\n }\n\n const radChain = augChain.map((c, i) => {\n const isLast = i === chain.length - 1\n const radRanges =\n c.type === 'revolute'\n ? ([c.range[0] * DEG2RAD, c.range[1] * DEG2RAD] as [number, number])\n : c.range\n return {\n ...c,\n length: isLast ? c.length + DESCENT_BIAS : c.length,\n range: radRanges\n }\n })\n // Shift target downward (chain-local -Z = world -Y) by the bias length.\n const augTarget = new THREE.Vector3(targetVec.x, targetVec.y, targetVec.z - DESCENT_BIAS)\n\n // ── Lock joint 0 (base yaw) at the right value, run CCDIK on the rest ──\n //\n // CCDIK has two compounding weaknesses with joint 0 (base yaw, axis\n // = chain-local Z):\n //\n // (a) Singularity when chain is straight along Z: v1 = tip - origin\n // is parallel to the joint axis, projects to zero length on the\n // perpendicular plane, and CCDIK SKIPs the joint entirely.\n //\n // (b) Even with the chain bent, CCDIK walking end→base may settle\n // on a contorted solution where downstream joints (typically\n // the wrist) compensate for an under-rotated joint 0 — the arm\n // \"self-pierces\" reaching backwards over its own base instead\n // of cleanly rotating to face the target.\n //\n // Fix: split into two phases.\n // 1. Compute the base yaw analytically: `atan2(target.y, target.x)`\n // — the unique angle that points the chain's pitch plane through\n // the target.\n // 2. Run CCDIK on the SUB-chain (joints 1..N-1) with a baseMatrix\n // that already includes joint 0's rotation + the first link\n // translation. Joint 0 is fixed — CCDIK can't unwind it.\n //\n // Result: base yaw is always correctly oriented, and the remaining\n // joints handle pitch + wrist + descent bias on top of that.\n const seedJoint0 =\n chain.length > 0 && chain[0].type === 'revolute' && chain[0].axis === 'z'\n ? resolveBaseYaw(targetVec, radChain[0].range, radJoints[0] ?? 0)\n : null\n\n if (seedJoint0 === null) {\n // Chain doesn't have a Z-axis joint at index 0 (e.g. SCARA, prismatic\n // first joint) — fall back to plain CCDIK on the full chain. The\n // singularity above doesn't apply when joint 0 isn't around Z.\n return solveCCDIK(radChain, radJoints, augTarget, undefined, {\n maxIterations: 40,\n damping: 0.5\n }).values\n }\n\n // Build base matrix: rotate around Z by seedJoint0, then translate\n // along Z by chain[0].length (joint 0's link). This places the\n // sub-chain's origin at frame 1.\n const baseMatrix = new THREE.Matrix4()\n .makeRotationZ(seedJoint0)\n .multiply(new THREE.Matrix4().makeTranslation(0, 0, radChain[0].length))\n\n const subChain = radChain.slice(1)\n const subSeed = radJoints.slice(1)\n const result = solveCCDIK(subChain, subSeed, augTarget, baseMatrix, {\n maxIterations: 40,\n damping: 0.5\n })\n return [seedJoint0, ...result.values]\n }\n\n // NOTE: `analyticalIk6Axis` and `resolveBaseYaw` previously lived as\n // private duplicates here. They've been hoisted to `./robot-arm-ik.ts`\n // so the unit tests in `test/ik-unit.test.mjs` exercise the same\n // implementation that runs at scene-time. Don't reintroduce private\n // copies — drift between \"tested\" and \"shipping\" code was a real\n // source of bugs in this file's history.\n\n // ─── Resolution helpers ──────────────────────────────────────────────\n\n private _resolveChain(state: any, targetReach: number): ChainElement[] {\n let raw: ChainElement[]\n if (Array.isArray(state.chain) && state.chain.length > 0) {\n raw = state.chain\n } else {\n const presetName = (state.chainPreset ?? '6-axis-industrial') as ChainPresetName\n raw = CHAIN_PRESETS[presetName] ?? CHAIN_PRESETS['6-axis-industrial']\n }\n // Scale every link.length proportionally so the chain's total reach\n // matches the requested depth. Preserves preset proportions (a SCARA\n // stays SCARA-shaped at any depth). Prismatic ranges scale too —\n // their travel distance is in the same length units.\n const nominal = raw.reduce((s, c) => s + (c.length || 0), 0)\n if (nominal <= 0) return raw\n const scale = targetReach / nominal\n return raw.map(c => ({\n ...c,\n length: c.length * scale,\n range: c.type === 'prismatic' ? ([c.range[0] * scale, c.range[1] * scale] as [number, number]) : c.range\n }))\n }\n\n /**\n * Base pedestal height — small reservation at the bottom of `depth` so\n * the chain doesn't start at z=0 (which would clip into the floor).\n * About 12% of depth, clamped to a sane range.\n */\n private _baseHeight(state: any): number {\n const depth = this.effectiveDepth\n return Math.max(2, Math.min(depth * 0.12, 30))\n }\n\n /**\n * Color resolution priority (high → low):\n * 1. `state.fillStyle` → main link color (overrides style preset)\n * 2. `state.color` → legacy / explicit hex int\n * 3. style preset color\n * Same for accent: state.strokeStyle → state.accentColor → preset accent.\n * This way the user can keep a SCARA's box-link shape but recolor it via\n * the standard fillStyle property without dropping into custom presets.\n */\n private _resolveStyle(state: any): RobotArmStyle {\n const baseStyle = STYLES[(state.style ?? 'industrial') as StyleName] ?? STYLES.industrial\n return {\n linkShape: (state.linkShape as LinkShape) ?? baseStyle.linkShape,\n jointHousing: (state.jointHousing as JointHousing) ?? baseStyle.jointHousing,\n color: pickColorish(state.fillStyle, state.color, baseStyle.color),\n accentColor: pickColorish(state.strokeStyle, state.accentColor, baseStyle.accentColor),\n linkRadius:\n typeof state.linkRadius === 'number' && Number.isFinite(state.linkRadius) && state.linkRadius > 0\n ? state.linkRadius\n : baseStyle.linkRadius\n }\n }\n\n /**\n * Resolution priority for each joint i:\n * 1. state.jointN (e.g. state.joint0, state.joint1, ...) — written\n * by the property panel's per-joint number inputs (one row per\n * joint, range-clamped slider).\n * 2. state.joints[i] — array form, useful for programmatic batch set.\n * 3. state.joints[i] — object form ({0: v, 1: v, ...}).\n * 4. 0 — fallback.\n * Final value is range-clamped against the joint's own limits.\n */\n private _resolveJoints(chain: ChainElement[], state: any): number[] {\n const out: number[] = []\n const src = state.joints\n for (let i = 0; i < chain.length; i++) {\n let v: number | undefined\n const flatKey = state[`joint${i}`]\n if (Number.isFinite(flatKey)) {\n v = flatKey\n } else if (Array.isArray(src) && Number.isFinite(src[i])) {\n v = src[i]\n } else if (src && typeof src === 'object' && Number.isFinite(src[i] ?? src[String(i)])) {\n v = Number(src[i] ?? src[String(i)])\n } else {\n v = 0\n }\n if (!Number.isFinite(v)) v = 0\n v = Math.max(chain[i].range[0], Math.min(chain[i].range[1], v as number))\n out.push(v)\n }\n return out\n }\n\n private _jointSpeed(state: any): number {\n // Degrees per second the joint can travel during smoothing.\n // Length-unit prismatic joints reuse this value as units/sec —\n // typical smoothing speed scales similarly for both axis types.\n //\n // Default 45 deg/s — chosen to feel like a real industrial arm\n // executing a careful pick-and-place rather than a fly-by. Higher\n // speeds (90+) read as \"rushed / unsafe\" in a 3D scene where the\n // viewer expects measured motion. User can override via\n // `state.jointSpeed`.\n const v = Number(state.jointSpeed ?? 45)\n return Number.isFinite(v) && v > 0 ? v : 45\n }\n\n /** Convert revolute joint values from degrees → radians. Prismatic\n * values pass through untouched. */\n private _toRadians(chain: ChainElement[], joints: number[]): number[] {\n return joints.map((v, i) => (chain[i].type === 'revolute' ? v * DEG2RAD : v))\n }\n\n /** Inverse of `_toRadians` — radians → degrees for revolute. */\n private _fromRadians(chain: ChainElement[], joints: number[]): number[] {\n return joints.map((v, i) => (chain[i].type === 'revolute' ? v * RAD2DEG : v))\n }\n\n // ─── Geometry builders ───────────────────────────────────────────────\n\n /**\n * Build the chain as a tree of nested Object3Ds. Each link extends\n * along its parent's +Z by `length` — applying the joint rotation BEFORE\n * the translation. This way `rotateAround joint axis = rotate the\n * downstream subtree`, which matches real arm kinematics.\n */\n private _buildArm(chain: ChainElement[], style: RobotArmStyle, joints: number[], baseHeight: number) {\n const state = this.component.state as any\n const resolved = resolveMaterial3d(state.material3d as Material3D | undefined)\n const alpha = clamp(numOr(state.alpha, 1), 0, 1)\n\n const linkMat = new THREE.MeshStandardMaterial({\n color: style.color,\n metalness: 0.45,\n roughness: 0.45,\n transparent: alpha < 1,\n opacity: alpha\n })\n applyMaterial3dProps(linkMat, resolved)\n const housingMat = new THREE.MeshStandardMaterial({\n color: style.accentColor,\n metalness: 0.55,\n roughness: 0.4,\n transparent: alpha < 1,\n opacity: alpha\n })\n applyMaterial3dProps(housingMat, resolved)\n\n // Three.js convention is +Y up — but our forward kinematics + CCDIK\n // module is +Z up (matches IK math conventions). Wrap the whole arm\n // in a group rotated -90° around X so chain-local +Z maps to world +Y.\n // Lift by baseHeight so the chain origin sits ON TOP of the pedestal.\n const armRoot = new THREE.Group()\n armRoot.rotation.x = -Math.PI / 2\n armRoot.position.y = -this.effectiveDepth / 2 + baseHeight\n this.object3d.add(armRoot)\n // Cache for worldToChainLocal — IK targets must be in this frame.\n this._armRoot = armRoot\n\n this._jointFrames = []\n let currentParent: THREE.Object3D = armRoot\n\n for (let i = 0; i < chain.length; i++) {\n const link = chain[i]\n // Joint frame — sits at the start of link i, rotates by jointValue.\n const frame = new THREE.Object3D()\n currentParent.add(frame)\n this._jointFrames.push(frame)\n this._applyJointValue(frame, link, joints[i])\n\n // Joint housing at the joint origin (frame's local origin).\n const housing = this._buildJointHousing(style.jointHousing, style.linkRadius, housingMat)\n if (housing) frame.add(housing)\n\n // Link mesh extends along local +Z by link.length. We mount it as a\n // child of the frame so it inherits the joint rotation. The link\n // itself sits with its base at z=0 and grows toward +Z.\n const linkMesh = this._buildLinkMesh(style.linkShape, style.linkRadius, link.length, linkMat)\n if (linkMesh) frame.add(linkMesh)\n\n // The next frame's parent is a translation forward by link.length.\n const next = new THREE.Object3D()\n next.position.set(0, 0, link.length)\n frame.add(next)\n currentParent = next\n }\n\n // Save the end-effector parent so the gripper builder can mount onto it.\n // Also exposed via `getGripperFrame()` so CarrierHolder.attachPointFor\n // can return it — making any Carriable child mount onto the moving\n // gripper TCP and follow IK automatically.\n ;(this as any)._endFrame = currentParent\n }\n\n /**\n * Frame at the gripper TCP (Tool Center Point) — the working point of\n * the gripper, NOT the wrist. For jaw grippers this is the mid-point\n * between finger tips; for suction/magnetic it's the contact face.\n * Carriers held by the arm parent here so they sit at the gripping\n * interface, not buried inside the gripper meshes.\n *\n * Falls back to `_endFrame` (wrist) until `_buildGripper` has run.\n */\n getGripperFrame(): THREE.Object3D | undefined {\n return this._tcpFrame ?? ((this as any)._endFrame as THREE.Object3D | undefined)\n }\n\n /**\n * Convert a world-space point to the IK module's chain-local frame.\n *\n * Why this matters: CCDIK + forwardKinematics operate in `armRoot`'s\n * local space (base joint at origin, +Z up — the IK math convention).\n * `state.target` is interpreted in *that* frame. If a caller hands in\n * a world position from another component (a parcel sitting somewhere\n * in the scene), it must be projected through `armRoot`'s inverse\n * world matrix first, otherwise the arm reaches toward \"as if the\n * world coords were base-relative\" — a totally wrong direction once\n * the robot itself isn't at the world origin.\n *\n * Returns the same `{x, y, z}` shape `state.target` accepts, which is\n * already in chain-local space (no further conversion needed by\n * pickAndPlace).\n */\n worldToChainLocal(worldX: number, worldY: number, worldZ: number): { x: number; y: number; z: number } {\n if (!this._armRoot) return { x: 0, y: 0, z: 0 }\n this._armRoot.updateWorldMatrix(true, false)\n const v = new THREE.Vector3(worldX, worldY, worldZ)\n v.applyMatrix4(new THREE.Matrix4().copy(this._armRoot.matrixWorld).invert())\n return { x: v.x, y: v.y, z: v.z }\n }\n\n private _armRoot?: THREE.Object3D\n\n /**\n * Apply a joint value to its scene-graph frame. `value` is in *user\n * units* (degrees for revolute, scene units for prismatic) — convert\n * to radians at the math boundary.\n */\n private _applyJointValue(frame: THREE.Object3D, link: ChainElement, value: number) {\n if (link.type === 'revolute') {\n const ax = _AXIS_VEC[link.axis]\n frame.quaternion.setFromAxisAngle(ax, value * DEG2RAD)\n } else {\n frame.position.copy(_AXIS_VEC[link.axis]).multiplyScalar(value)\n }\n }\n\n /** Cheap path: just refresh joint orientations without rebuilding the\n * geometry tree. Used when only joint values changed. */\n private _refreshJointPoses(joints: number[]) {\n for (let i = 0; i < this._chain.length; i++) {\n const frame = this._jointFrames[i]\n if (frame) this._applyJointValue(frame, this._chain[i], joints[i])\n }\n }\n\n private _buildJointHousing(kind: JointHousing, r: number, mat: THREE.Material): THREE.Mesh | null {\n const radius = r * 1.15\n switch (kind) {\n case 'disk': {\n const geo = new THREE.CylinderGeometry(radius, radius, r * 0.7, 24)\n // disk axis = local Y by default; we want it perpendicular to the\n // link's growth direction. Leaving it on local Y reads as a \"wrist\n // band\" between two link segments — which is what cobot disks do.\n return new THREE.Mesh(geo, mat)\n }\n case 'sphere': {\n const geo = new THREE.SphereGeometry(radius, 16, 12)\n return new THREE.Mesh(geo, mat)\n }\n case 'knuckle': {\n // Asymmetric box — wider in two axes, narrow in third. Reads as\n // industrial cast joint.\n const geo = new THREE.BoxGeometry(radius * 2.1, radius * 1.4, radius * 1.8)\n return new THREE.Mesh(geo, mat)\n }\n case 'none':\n default:\n return null\n }\n }\n\n private _buildLinkMesh(\n shape: LinkShape,\n radius: number,\n length: number,\n mat: THREE.Material\n ): THREE.Mesh | null {\n if (length <= 0.5) return null\n let geo: THREE.BufferGeometry\n switch (shape) {\n case 'cylinder':\n geo = new THREE.CylinderGeometry(radius, radius, length, 16)\n break\n case 'tapered':\n geo = new THREE.CylinderGeometry(radius * 0.7, radius, length, 16)\n break\n case 'tube':\n geo = new THREE.CylinderGeometry(radius * 0.5, radius * 0.5, length, 12)\n break\n case 'box':\n geo = new THREE.BoxGeometry(radius * 1.6, radius * 1.6, length)\n break\n case 'gltf':\n // Placeholder — full GLTF link replacement is a v2 feature.\n // Fall back to cylinder so the chain doesn't break visually.\n geo = new THREE.CylinderGeometry(radius, radius, length, 16)\n break\n default:\n geo = new THREE.CylinderGeometry(radius, radius, length, 16)\n }\n // Three.js cylinder/box default axis = local +Y. Rotate to grow along\n // local +Z (the chain-forward direction) and shift so the BASE sits at\n // z=0 (rather than centered).\n if (shape !== 'box') {\n geo.rotateX(Math.PI / 2)\n }\n geo.translate(0, 0, length / 2)\n const mesh = new THREE.Mesh(geo, mat)\n mesh.castShadow = true\n return mesh\n }\n\n // ─── Gripper ──────────────────────────────────────────────────────────\n\n /**\n * Build the gripper meshes onto `_endFrame` and place a TCP frame at\n * the gripper's working point (between the finger tips for jaw types,\n * at the cup/disk distal face for surface types). Carriers held by the\n * arm mount onto this TCP frame, NOT onto `_endFrame` — `_endFrame` is\n * the wrist (chain end-of-link) and the gripper extends from it in +Z,\n * so a carrier at `_endFrame` origin would visually overlap the gripper\n * meshes (the fingers/cup would pierce through the box).\n */\n private _buildGripper(chain: ChainElement[], style: RobotArmStyle, state: any) {\n const endFrame = (this as any)._endFrame as THREE.Object3D | undefined\n if (!endFrame) return\n\n // TCP frame — added unconditionally (even for gripper.type='none' or\n // missing gripper) so carrier mount logic always has a stable target.\n // Default at wrist (z=0); per-type builders override below.\n const tcp = new THREE.Object3D()\n endFrame.add(tcp)\n this._tcpFrame = tcp\n\n const cfg: GripperConfig = {\n ...DEFAULT_GRIPPER,\n ...((state.gripper as GripperConfig) ?? {}),\n // gripperType nature property is a shortcut for {gripper: {type}} —\n // expose it so the property panel's <select> works without nested object editing.\n ...(state.gripperType ? { type: state.gripperType } : {})\n }\n if (cfg.type === 'none') return\n\n const color = pickColorish(cfg.color, style.accentColor)\n const resolved = resolveMaterial3d(state.material3d as Material3D | undefined)\n const alpha = clamp(numOr(state.alpha, 1), 0, 1)\n const mat = new THREE.MeshStandardMaterial({\n color,\n metalness: 0.55,\n roughness: 0.4,\n transparent: alpha < 1,\n opacity: alpha\n })\n applyMaterial3dProps(mat, resolved)\n\n let tcpZ = 0\n switch (cfg.type) {\n case 'parallel':\n tcpZ = this._buildParallelGripper(endFrame, cfg, mat, style.linkRadius)\n break\n case 'three-finger':\n tcpZ = this._buildThreeFingerGripper(endFrame, cfg, mat, style.linkRadius)\n break\n case 'suction':\n tcpZ = this._buildSuctionGripper(endFrame, cfg, mat, style.linkRadius)\n break\n case 'magnetic':\n tcpZ = this._buildMagneticGripper(endFrame, cfg, mat, style.linkRadius)\n break\n }\n tcp.position.z = tcpZ\n }\n\n private _tcpFrame?: THREE.Object3D\n\n /**\n * Each gripper sub-builder returns its TCP z-offset (in `_endFrame`'s\n * local coordinates) — the point in space where a held carrier's grip\n * face should land. The caller positions `_tcpFrame` at that z so\n * carriers attach there directly.\n */\n private _buildParallelGripper(\n parent: THREE.Object3D,\n cfg: GripperConfig,\n mat: THREE.Material,\n linkRadius: number\n ): number {\n // Default sizes scale with linkRadius so the gripper looks proportional\n // to the arm. A heavy industrial 6-axis (linkRadius ~10) gets a chunky\n // gripper; a slim cobot wrist (linkRadius ~3) gets a small one. User\n // can still override via cfg.stroke / cfg.fingerWidth.\n const stroke = cfg.stroke ?? linkRadius * 1.8\n const fingerWidth = cfg.fingerWidth ?? linkRadius * 0.45\n const fingerLength = stroke * 1.2\n const closure = THREE.MathUtils.clamp(cfg.state ?? 0, 0, 1) // 0 = open, 1 = closed\n // Wrist plate\n const plate = new THREE.Mesh(\n new THREE.BoxGeometry(stroke * 1.6, fingerWidth * 1.2, fingerWidth * 1.8),\n mat\n )\n plate.position.set(0, 0, fingerWidth * 0.9)\n parent.add(plate)\n // Two fingers, opening width = stroke when state=0, fingerWidth when state=1\n const halfOpen = (stroke / 2) * (1 - closure) + (fingerWidth / 2) * closure\n for (const sign of [-1, 1]) {\n const finger = new THREE.Mesh(\n new THREE.BoxGeometry(fingerWidth, fingerWidth, fingerLength),\n mat\n )\n finger.position.set(sign * halfOpen, 0, fingerWidth * 1.8 + fingerLength / 2)\n parent.add(finger)\n }\n // TCP = finger-tip plane (carrier's top face docks against it).\n return fingerWidth * 1.8 + fingerLength\n }\n\n private _buildThreeFingerGripper(\n parent: THREE.Object3D,\n cfg: GripperConfig,\n mat: THREE.Material,\n linkRadius: number\n ): number {\n const stroke = cfg.stroke ?? linkRadius * 1.5\n const fingerWidth = cfg.fingerWidth ?? linkRadius * 0.4\n const fingerLength = stroke * 1.2\n const closure = THREE.MathUtils.clamp(cfg.state ?? 0, 0, 1)\n const radius = (stroke / 2) * (1 - closure) + (fingerWidth / 2) * closure\n // Wrist hub\n const hub = new THREE.Mesh(\n new THREE.CylinderGeometry(stroke * 0.55, stroke * 0.55, fingerWidth * 1.5, 16),\n mat\n )\n hub.rotation.x = Math.PI / 2\n hub.position.set(0, 0, fingerWidth * 0.75)\n parent.add(hub)\n // Three fingers around the axis\n for (let i = 0; i < 3; i++) {\n const angle = (i / 3) * Math.PI * 2\n const finger = new THREE.Mesh(\n new THREE.BoxGeometry(fingerWidth, fingerWidth, fingerLength),\n mat\n )\n finger.position.set(Math.cos(angle) * radius, Math.sin(angle) * radius, fingerWidth * 1.5 + fingerLength / 2)\n parent.add(finger)\n }\n return fingerWidth * 1.5 + fingerLength\n }\n\n private _buildSuctionGripper(\n parent: THREE.Object3D,\n cfg: GripperConfig,\n mat: THREE.Material,\n linkRadius: number\n ): number {\n const diameter = cfg.diameter ?? linkRadius * 2.4\n // Mounting stem\n const stem = new THREE.Mesh(\n new THREE.CylinderGeometry(diameter * 0.25, diameter * 0.25, diameter * 0.5, 12),\n mat\n )\n stem.rotation.x = Math.PI / 2\n stem.position.set(0, 0, diameter * 0.25)\n parent.add(stem)\n // Suction cup (cone, narrow end at the stem)\n const cup = new THREE.Mesh(\n new THREE.CylinderGeometry(diameter / 2, diameter * 0.3, diameter * 0.4, 24, 1, true),\n mat\n )\n cup.rotation.x = Math.PI / 2\n cup.position.set(0, 0, diameter * 0.5 + diameter * 0.2)\n parent.add(cup)\n // TCP = cup distal face (suction surface contacts the carrier here).\n return diameter * 0.9\n }\n\n private _buildMagneticGripper(\n parent: THREE.Object3D,\n cfg: GripperConfig,\n mat: THREE.Material,\n linkRadius: number\n ): number {\n const diameter = cfg.diameter ?? linkRadius * 2.6\n // Disk magnet at the end\n const disk = new THREE.Mesh(\n new THREE.CylinderGeometry(diameter / 2, diameter / 2, diameter * 0.25, 24),\n mat\n )\n disk.rotation.x = Math.PI / 2\n disk.position.set(0, 0, diameter * 0.125)\n parent.add(disk)\n // TCP = disk distal face (magnet contacts the carrier here).\n return diameter * 0.25\n }\n\n // ─── Reach sphere visualization ──────────────────────────────────────\n\n private _buildReachSphere(chain: ChainElement[], state: any, baseHeight: number) {\n if (!state.showReachSphere) return\n const reach = maxReach(chain)\n if (reach <= 0) return\n const geo = new THREE.SphereGeometry(reach, 24, 16)\n const wire = new THREE.WireframeGeometry(geo)\n const mat = new THREE.LineBasicMaterial({\n color: 0x44aacc,\n transparent: true,\n opacity: 0.18\n })\n const wireMesh = new THREE.LineSegments(wire, mat)\n // Center on the base joint (top of pedestal), in world-space y.\n wireMesh.position.y = -this.effectiveDepth / 2 + baseHeight\n // Visualization-only — must not catch raycasts. The reach sphere\n // surrounds the arm in 3D and would intercept clicks meant for the\n // actual robot body. NO_RAYCAST keeps it visible but click-through.\n wireMesh.raycast = NO_RAYCAST\n this.object3d.add(wireMesh)\n geo.dispose()\n }\n\n // ─── Base / pedestal ─────────────────────────────────────────────────\n\n /**\n * Pedestal — sized from `state.width × state.height` (the 2D footprint).\n * Cylindrical base whose radius fills ~90% of the smaller footprint\n * dimension; a flared bottom (1.2× radius) gives the visual weight of\n * a real industrial robot anchor.\n */\n private _buildBase(state: any, style: RobotArmStyle, baseHeight: number) {\n const w = Math.max(Math.abs(numOr(state.width, 100)), 1)\n const h2d = Math.max(Math.abs(numOr(state.height, 100)), 1)\n const r = (Math.min(w, h2d) / 2) * 0.9\n const resolved = resolveMaterial3d(state.material3d as Material3D | undefined)\n const alpha = clamp(numOr(state.alpha, 1), 0, 1)\n const mat = new THREE.MeshStandardMaterial({\n color: style.accentColor,\n metalness: 0.6,\n roughness: 0.4,\n transparent: alpha < 1,\n opacity: alpha\n })\n applyMaterial3dProps(mat, resolved)\n const base = new THREE.Mesh(new THREE.CylinderGeometry(r, r * 1.2, baseHeight, 24), mat)\n base.position.set(0, -this.effectiveDepth / 2 + baseHeight / 2, 0)\n base.castShadow = resolved.castShadow\n base.receiveShadow = resolved.receiveShadow\n this.object3d.add(base)\n }\n\n // ─── Animation: smooth joint values toward solved target ─────────────\n\n private _startAnimation() {\n this._isAnimating = true\n let lastTime = performance.now()\n const tick = () => {\n if (!this._isAnimating || !this._smoothing) return\n const now = performance.now()\n const dt = Math.min((now - lastTime) / 1000, 0.1) // clamp for stability\n lastTime = now\n const { current, target, speed } = this._smoothing\n const maxStep = speed * dt\n let allReached = true\n for (let i = 0; i < current.length; i++) {\n const diff = (target[i] ?? 0) - current[i]\n if (Math.abs(diff) > 1e-4) allReached = false\n const step = Math.sign(diff) * Math.min(Math.abs(diff), maxStep)\n current[i] += step\n // apply to live frame\n const frame = this._jointFrames[i]\n const link = this._chain[i]\n if (frame && link) this._applyJointValue(frame, link, current[i])\n }\n this.component.invalidate?.()\n if (allReached) {\n this._stopAnimation()\n // Notify external code (pickAndPlace, custom scripts) that the\n // gripper has reached its target. Component.trigger fires the\n // standard things-scene event bus so consumers can subscribe via\n // `component.on('tcp-reached', handler)`.\n ;(this.component as any).trigger?.('tcp-reached', { component: this.component })\n return\n }\n this._animFrame = requestAnimationFrame(tick)\n }\n this._animFrame = requestAnimationFrame(tick)\n }\n\n private _stopAnimation() {\n this._isAnimating = false\n if (this._animFrame !== undefined) {\n cancelAnimationFrame(this._animFrame)\n this._animFrame = undefined\n }\n }\n\n /**\n * Re-run IK toward a new target without rebuilding the scene graph.\n *\n * Mirrors the IK block of `build()` but operates on the *existing*\n * joint frames and meshes. Critically does NOT call `update()` /\n * `clear()` — those tear down `this.object3d`'s children, which would\n * also detach the gripper frame and any Carriable currently mounted\n * onto it. A pickAndPlace operation would lose its held carrier the\n * instant the place target is committed.\n *\n * Falls back to a full `update()` only when the cached chain hasn't\n * been built yet (build pre-condition).\n */\n private _retargetIk() {\n if (this._chain.length === 0 || this._jointFrames.length !== this._chain.length) {\n this.update()\n return\n }\n\n const state = this.component.state as any\n const chain = this._chain\n const target = state.target\n const speed = this._jointSpeed(state)\n\n // Starting pose for IK = where smoothing currently is (mid-flight)\n // or the resolved joint values from state. Using mid-flight values\n // makes consecutive `pnp` calls chain smoothly without snap-back.\n const previous = this._smoothing?.current?.slice() ?? this._resolveJoints(chain, state)\n\n if (target && Number.isFinite(target.x) && Number.isFinite(target.y) && Number.isFinite(target.z)) {\n const targetVec = new THREE.Vector3(target.x, target.y, target.z)\n const targetYaw = Number.isFinite(target.yaw) ? (target.yaw as number) : undefined\n const radJoints = this._toRadians(chain, previous)\n const ikValues = this._solveIkDescent(chain, radJoints, targetVec, targetYaw)\n const solvedUser = this._fromRadians(chain, ikValues)\n this._smoothing = {\n current: previous,\n target: solvedUser.slice(),\n speed\n }\n // Snap visible pose to the smoothing's \"current\" (= previous IK\n // position). Without this, if external code mutated joint frames\n // between ticks, the first tick would jump.\n this._refreshJointPoses(previous)\n this._stopAnimation()\n this._startAnimation()\n } else {\n // Target cleared — stop animating, freeze where we are.\n if (this._smoothing) {\n this._smoothing.target = this._smoothing.current.slice()\n this._smoothing.speed = speed\n }\n this._stopAnimation()\n }\n }\n\n updateDimension() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n // Structural changes — full rebuild.\n if (\n 'style' in after ||\n 'chainPreset' in after ||\n 'chain' in after ||\n 'linkShape' in after ||\n 'jointHousing' in after ||\n 'linkRadius' in after ||\n 'color' in after ||\n 'accentColor' in after ||\n 'fillStyle' in after ||\n 'strokeStyle' in after ||\n 'alpha' in after ||\n 'material3d' in after ||\n 'gripper' in after ||\n 'gripperType' in after ||\n 'showReachSphere' in after ||\n 'width' in after ||\n 'height' in after ||\n 'depth' in after\n ) {\n this.update()\n return\n }\n // Target change → re-run IK + restart smoothing on the EXISTING\n // scene graph. Critically NOT a full rebuild — `update()` calls\n // `clear()` which detaches every child of `this.object3d`, including\n // any Carriable currently mounted on the gripper frame. A pickAndPlace\n // call would invisibly drop the held carrier the moment we set the\n // place target, leaving no mesh between pick and place.\n if ('target' in after || 'jointSpeed' in after) {\n this._retargetIk()\n return\n }\n // Joint value change (state.joint0, state.joint1, ... or state.joints\n // batch) — fast path: just refresh joint poses on the existing scene\n // graph. NO mesh rebuild. This is what makes property-panel slider\n // edits feel live. The match must be done explicitly because dynamic\n // joint property names (joint0, joint1, ...) aren't in any static list.\n const hasJoint = 'joints' in after || Object.keys(after).some(k => /^joint\\d+$/.test(k))\n if (hasJoint) {\n const state = this.component.state as any\n // chain might be empty if build hasn't run yet (e.g. component just\n // attached). Defer to a full update in that case.\n if (this._chain.length === 0 || this._jointFrames.length !== this._chain.length) {\n this.update()\n return\n }\n const joints = this._resolveJoints(this._chain, state)\n this._refreshJointPoses(joints)\n // smoothing's \"current\" should track the user's manual edits so the\n // next IK target solves from where the user left things.\n if (this._smoothing) this._smoothing.current = joints.slice()\n return\n }\n super.onchange(after, before)\n }\n\n dispose() {\n this._stopAnimation()\n super.dispose()\n }\n\n updateAlpha() {}\n}\n\n/** Returns `v` if a finite number, otherwise `dflt`. */\nfunction numOr(v: unknown, dflt: number): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : dflt\n}\n\nfunction clamp(v: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, v))\n}\n\n/**\n * Pick the first valid color in priority order. Accepts both color strings\n * (CSS / hex) and hex int numbers — both are valid `THREE.ColorRepresentation`.\n * Treats 'transparent' / empty strings as \"skip me\".\n */\n/** Returns a number-or-string color (StyleColor). Both flavors are valid\n * THREE.ColorRepresentation, so they pass through to MeshStandardMaterial\n * without conversion. */\nfunction pickColorish(...candidates: unknown[]): number | string {\n for (const c of candidates) {\n if (typeof c === 'string' && c && c !== 'transparent') return c\n if (typeof c === 'number' && Number.isFinite(c)) return c\n }\n return 0x888888\n}\n"]}
@@ -0,0 +1,115 @@
1
+ import * as THREE from 'three';
2
+ export type JointAxis = 'x' | 'y' | 'z';
3
+ export interface ChainElement {
4
+ /** 'revolute' (rotates) or 'prismatic' (slides). PoC supports revolute. */
5
+ type: 'revolute' | 'prismatic';
6
+ /** axis of rotation/sliding in the joint's local frame */
7
+ axis: JointAxis;
8
+ /** length of the link that follows this joint, along local +Z */
9
+ length: number;
10
+ /** [min, max] joint value, in radians for revolute / units for prismatic */
11
+ range: [number, number];
12
+ }
13
+ /**
14
+ * Forward kinematics: given joint values, compute every joint's world
15
+ * position + orientation. Index 0 = base, index N = end-effector frame
16
+ * (where the gripper is mounted).
17
+ *
18
+ * Convention: each joint's local frame starts coincident with its parent's
19
+ * end frame; the joint applies its rotation/translation, then the link
20
+ * extends along local +Z by `length`.
21
+ */
22
+ export declare function forwardKinematics(chain: ChainElement[], jointValues: number[], baseMatrix?: THREE.Matrix4): {
23
+ positions: THREE.Vector3[];
24
+ quaternions: THREE.Quaternion[];
25
+ };
26
+ export interface SolveOptions {
27
+ maxIterations?: number;
28
+ threshold?: number;
29
+ /** how aggressively each iteration nudges (0..1). 0.5 = damped, less jitter. */
30
+ damping?: number;
31
+ }
32
+ /**
33
+ * Solve IK for `targetWorld` and return new joint values. Does not mutate
34
+ * the input array.
35
+ *
36
+ * Returns `{ values, reached }`. `reached` is true if the end-effector
37
+ * came within `threshold` of the target — false if the target is outside
38
+ * reachable workspace or the solver gave up.
39
+ */
40
+ export declare function solveCCDIK(chain: ChainElement[], jointValues: number[], targetWorld: THREE.Vector3, baseMatrix?: THREE.Matrix4, options?: SolveOptions): {
41
+ values: number[];
42
+ reached: boolean;
43
+ };
44
+ /**
45
+ * Cheap reachability estimate — sum of all link lengths. Doesn't account
46
+ * for joint-range restrictions, so a bit optimistic; good enough for
47
+ * "show me a workspace sphere" visualization.
48
+ */
49
+ export declare function maxReach(chain: ChainElement[]): number;
50
+ /**
51
+ * True if `chain` has the canonical 6-axis Z-Y-Y-Z-Y-Z structure.
52
+ * Industrial / cobot presets match. This unlocks closed-form analytical
53
+ * IK; other chain shapes fall back to CCDIK.
54
+ */
55
+ export declare function isSixAxisZYYZYZ(chain: ChainElement[]): boolean;
56
+ /**
57
+ * Pick the base-yaw angle that points the chain toward the target's
58
+ * XY direction. Returns null if the target is on the Z axis (no XY
59
+ * direction defined). Unwraps to the multiple-of-2π closest to
60
+ * `currentYaw` (then clamps to range), so a small physical motion in
61
+ * world space doesn't produce a giant joint swing across ±π.
62
+ *
63
+ * `range` and `currentYaw` are in RADIANS.
64
+ */
65
+ export declare function resolveBaseYaw(target: {
66
+ x: number;
67
+ y: number;
68
+ }, range: [number, number], currentYaw: number): number | null;
69
+ /**
70
+ * Closed-form analytical IK for the canonical 6-axis Z-Y-Y-Z-Y-Z chain.
71
+ *
72
+ * Inputs and outputs are in RADIANS. Chain ranges are in DEGREES (the
73
+ * editor's user-facing convention) — converted internally. Returns null
74
+ * if the target is unreachable; caller should fall back to CCDIK.
75
+ *
76
+ * Strategy:
77
+ * 1. Joint 0 = base yaw to face target's XY direction.
78
+ * 2. Try strict descent (gripper straight down, α = π).
79
+ * 3. If wrist would be beyond reach, relax α to the value closest to
80
+ * π that puts the wrist on the reach boundary.
81
+ * 4. 2-link IK (cosine law) on upper + lower for shoulder/elbow.
82
+ * 5. Wrist pitch ψ4 = α - ψ1 - ψ2 to realize the chosen α.
83
+ * 6. Joints 3, 5 (Z-axis wrist roll / tool roll) = 0.
84
+ *
85
+ * Joint values are clamped to chain ranges; if a clamp activates the
86
+ * gripper won't be perfectly oriented, but the rest of the pose is
87
+ * still natural — and the visual TCP will then deviate from the
88
+ * commanded target by the clamp residual.
89
+ */
90
+ export declare function analyticalIk6Axis(chain: ChainElement[], target: {
91
+ x: number;
92
+ y: number;
93
+ z: number;
94
+ }, currentJointsRad: number[],
95
+ /**
96
+ * Optional carrier/place-holder yaw (radians, around world +Y) at the
97
+ * target. When provided, joint 5 (tool roll) is set so the gripper's
98
+ * "side" axes align with the carrier's — preventing a visible rotation
99
+ * snap when the carrier reparents to the gripper at pick / off the
100
+ * gripper at place.
101
+ *
102
+ * Derivation: with cumulative pitch ψ1+ψ2+ψ4 = π, the end-frame's
103
+ * world axes are determined by joint 0 (j0) and joint 5 (θ5):
104
+ * end_X = (-cos(j0 - θ5), 0, sin(j0 - θ5))
105
+ * Carriable's localRotation x:-π/2 makes carrier_world = TCP_world ∘ R_x(-π/2);
106
+ * for carrier_world to land at the carrier's pre-reparent yaw γ, we
107
+ * need TCP_world = R_y(γ) ∘ R_x(π/2), which gives:
108
+ * end_X = (cos γ, 0, -sin γ)
109
+ * Solving end_X equation vs. this target: j0 - θ5 = π + γ
110
+ * → θ5 = j0 - π - γ
111
+ * Wrapped to [-π, π] then clamped to chain[5].range.
112
+ *
113
+ * If omitted, joint 5 stays at 0 (no yaw alignment).
114
+ */
115
+ targetYaw?: number): number[] | null;
@@ -0,0 +1,313 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * CCDIK (Cyclic Coordinate Descent Inverse Kinematics) for an arbitrary
5
+ * articulated chain.
6
+ *
7
+ * Why CCDIK over analytical IK or Jacobian methods:
8
+ * - Generalizes to arbitrary chain length / axis combinations without
9
+ * re-deriving closed-form solutions per geometry.
10
+ * - Trivial to implement in ~120 lines, no matrix inversion.
11
+ * - Visually pleasing convergence (each iteration nudges the closest
12
+ * joint to the end-effector toward the target — naturally produces
13
+ * "elbow leads, wrist follows" motion that mimics real arms).
14
+ * - Adequate for animation use; not a replacement for high-precision
15
+ * analytical IK in a real motion-planning context.
16
+ *
17
+ * Algorithm (one iteration):
18
+ * For each joint i from end → base:
19
+ * 1. tip = world position of end-effector under current joint angles
20
+ * 2. pivot = world position of joint i
21
+ * 3. v1 = (tip - pivot) — current direction
22
+ * v2 = (target - pivot) — desired direction
23
+ * 4. project v1 and v2 onto the plane normal to joint i's axis
24
+ * 5. θ = signed angle between projections (around the axis)
25
+ * 6. jointValues[i] += θ, clamp to range
26
+ * Repeat until tip-target distance < threshold or maxIterations reached.
27
+ *
28
+ * The chain is fixed (no link insertion/removal during a solve), and the
29
+ * solver mutates a copy of jointValues — caller decides whether to commit.
30
+ */
31
+ import * as THREE from 'three';
32
+ const _AXES = {
33
+ x: new THREE.Vector3(1, 0, 0),
34
+ y: new THREE.Vector3(0, 1, 0),
35
+ z: new THREE.Vector3(0, 0, 1)
36
+ };
37
+ /**
38
+ * Forward kinematics: given joint values, compute every joint's world
39
+ * position + orientation. Index 0 = base, index N = end-effector frame
40
+ * (where the gripper is mounted).
41
+ *
42
+ * Convention: each joint's local frame starts coincident with its parent's
43
+ * end frame; the joint applies its rotation/translation, then the link
44
+ * extends along local +Z by `length`.
45
+ */
46
+ export function forwardKinematics(chain, jointValues, baseMatrix = new THREE.Matrix4()) {
47
+ const positions = [];
48
+ const quaternions = [];
49
+ const m = baseMatrix.clone();
50
+ const tmpQ = new THREE.Quaternion();
51
+ const tmpT = new THREE.Vector3();
52
+ const linkOffset = new THREE.Vector3();
53
+ // Joint 0 sits at the base.
54
+ positions.push(new THREE.Vector3().setFromMatrixPosition(m));
55
+ quaternions.push(new THREE.Quaternion().setFromRotationMatrix(m));
56
+ for (let i = 0; i < chain.length; i++) {
57
+ const link = chain[i];
58
+ const value = jointValues[i] ?? 0;
59
+ if (link.type === 'revolute') {
60
+ tmpQ.setFromAxisAngle(_AXES[link.axis], value);
61
+ const rotM = new THREE.Matrix4().makeRotationFromQuaternion(tmpQ);
62
+ m.multiply(rotM);
63
+ }
64
+ else {
65
+ // prismatic: slide along axis by `value` (PoC support — most common
66
+ // in real manipulators is revolute, but keeping the door open).
67
+ linkOffset.copy(_AXES[link.axis]).multiplyScalar(value);
68
+ m.multiply(new THREE.Matrix4().makeTranslation(linkOffset.x, linkOffset.y, linkOffset.z));
69
+ }
70
+ // Then translate along +Z by link.length to reach the next joint frame.
71
+ m.multiply(new THREE.Matrix4().makeTranslation(0, 0, link.length));
72
+ tmpT.setFromMatrixPosition(m);
73
+ positions.push(tmpT.clone());
74
+ quaternions.push(new THREE.Quaternion().setFromRotationMatrix(m));
75
+ }
76
+ return { positions, quaternions };
77
+ }
78
+ /**
79
+ * Solve IK for `targetWorld` and return new joint values. Does not mutate
80
+ * the input array.
81
+ *
82
+ * Returns `{ values, reached }`. `reached` is true if the end-effector
83
+ * came within `threshold` of the target — false if the target is outside
84
+ * reachable workspace or the solver gave up.
85
+ */
86
+ export function solveCCDIK(chain, jointValues, targetWorld, baseMatrix = new THREE.Matrix4(), options = {}) {
87
+ const maxIterations = options.maxIterations ?? 12;
88
+ const threshold = options.threshold ?? 0.5;
89
+ const damping = options.damping ?? 0.7;
90
+ const values = jointValues.slice();
91
+ // Pre-allocate scratch vectors to avoid per-iteration GC churn.
92
+ const v1 = new THREE.Vector3();
93
+ const v2 = new THREE.Vector3();
94
+ const axisWorld = new THREE.Vector3();
95
+ const cross = new THREE.Vector3();
96
+ for (let iter = 0; iter < maxIterations; iter++) {
97
+ const fk = forwardKinematics(chain, values, baseMatrix);
98
+ const tip = fk.positions[fk.positions.length - 1];
99
+ // Early out: already close enough.
100
+ if (tip.distanceTo(targetWorld) < threshold) {
101
+ return { values, reached: true };
102
+ }
103
+ // Walk joints from the one nearest the tip toward the base.
104
+ for (let i = chain.length - 1; i >= 0; i--) {
105
+ if (chain[i].type !== 'revolute')
106
+ continue;
107
+ // Joint i's pivot = positions[i] (frame BEFORE applying joint i).
108
+ // After applying joint i and link i, we get positions[i+1].
109
+ const pivot = fk.positions[i];
110
+ const tipNow = forwardKinematics(chain, values, baseMatrix).positions[chain.length];
111
+ v1.subVectors(tipNow, pivot);
112
+ v2.subVectors(targetWorld, pivot);
113
+ if (v1.lengthSq() < 1e-6 || v2.lengthSq() < 1e-6)
114
+ continue;
115
+ // Joint axis in world space at this joint frame.
116
+ axisWorld.copy(_AXES[chain[i].axis]).applyQuaternion(fk.quaternions[i]);
117
+ axisWorld.normalize();
118
+ // Project v1, v2 onto the plane perpendicular to the axis.
119
+ const v1p = v1.clone().projectOnPlane(axisWorld);
120
+ const v2p = v2.clone().projectOnPlane(axisWorld);
121
+ if (v1p.lengthSq() < 1e-6 || v2p.lengthSq() < 1e-6)
122
+ continue;
123
+ v1p.normalize();
124
+ v2p.normalize();
125
+ // Signed angle around `axisWorld` from v1p to v2p.
126
+ let angle = Math.acos(THREE.MathUtils.clamp(v1p.dot(v2p), -1, 1));
127
+ cross.crossVectors(v1p, v2p);
128
+ if (cross.dot(axisWorld) < 0)
129
+ angle = -angle;
130
+ angle *= damping;
131
+ values[i] = clamp(values[i] + angle, chain[i].range[0], chain[i].range[1]);
132
+ }
133
+ }
134
+ // Final check after exhausting iterations.
135
+ const finalTip = forwardKinematics(chain, values, baseMatrix).positions[chain.length];
136
+ return { values, reached: finalTip.distanceTo(targetWorld) < threshold };
137
+ }
138
+ /**
139
+ * Cheap reachability estimate — sum of all link lengths. Doesn't account
140
+ * for joint-range restrictions, so a bit optimistic; good enough for
141
+ * "show me a workspace sphere" visualization.
142
+ */
143
+ export function maxReach(chain) {
144
+ return chain.reduce((sum, c) => sum + (c.length || 0), 0);
145
+ }
146
+ /**
147
+ * True if `chain` has the canonical 6-axis Z-Y-Y-Z-Y-Z structure.
148
+ * Industrial / cobot presets match. This unlocks closed-form analytical
149
+ * IK; other chain shapes fall back to CCDIK.
150
+ */
151
+ export function isSixAxisZYYZYZ(chain) {
152
+ if (chain.length !== 6)
153
+ return false;
154
+ const expected = ['z', 'y', 'y', 'z', 'y', 'z'];
155
+ for (let i = 0; i < 6; i++) {
156
+ if (chain[i].type !== 'revolute')
157
+ return false;
158
+ if (chain[i].axis !== expected[i])
159
+ return false;
160
+ }
161
+ return true;
162
+ }
163
+ /**
164
+ * Pick the base-yaw angle that points the chain toward the target's
165
+ * XY direction. Returns null if the target is on the Z axis (no XY
166
+ * direction defined). Unwraps to the multiple-of-2π closest to
167
+ * `currentYaw` (then clamps to range), so a small physical motion in
168
+ * world space doesn't produce a giant joint swing across ±π.
169
+ *
170
+ * `range` and `currentYaw` are in RADIANS.
171
+ */
172
+ export function resolveBaseYaw(target, range, currentYaw) {
173
+ const xy = Math.hypot(target.x, target.y);
174
+ if (xy < 1e-3)
175
+ return null;
176
+ const a = Math.atan2(target.y, target.x);
177
+ const TAU = Math.PI * 2;
178
+ let best = a;
179
+ let bestDist = Math.abs(a - currentYaw);
180
+ for (const k of [-2, -1, 1, 2]) {
181
+ const candidate = a + k * TAU;
182
+ const d = Math.abs(candidate - currentYaw);
183
+ if (d < bestDist) {
184
+ best = candidate;
185
+ bestDist = d;
186
+ }
187
+ }
188
+ return clamp(best, range[0], range[1]);
189
+ }
190
+ /**
191
+ * Closed-form analytical IK for the canonical 6-axis Z-Y-Y-Z-Y-Z chain.
192
+ *
193
+ * Inputs and outputs are in RADIANS. Chain ranges are in DEGREES (the
194
+ * editor's user-facing convention) — converted internally. Returns null
195
+ * if the target is unreachable; caller should fall back to CCDIK.
196
+ *
197
+ * Strategy:
198
+ * 1. Joint 0 = base yaw to face target's XY direction.
199
+ * 2. Try strict descent (gripper straight down, α = π).
200
+ * 3. If wrist would be beyond reach, relax α to the value closest to
201
+ * π that puts the wrist on the reach boundary.
202
+ * 4. 2-link IK (cosine law) on upper + lower for shoulder/elbow.
203
+ * 5. Wrist pitch ψ4 = α - ψ1 - ψ2 to realize the chosen α.
204
+ * 6. Joints 3, 5 (Z-axis wrist roll / tool roll) = 0.
205
+ *
206
+ * Joint values are clamped to chain ranges; if a clamp activates the
207
+ * gripper won't be perfectly oriented, but the rest of the pose is
208
+ * still natural — and the visual TCP will then deviate from the
209
+ * commanded target by the clamp residual.
210
+ */
211
+ export function analyticalIk6Axis(chain, target, currentJointsRad,
212
+ /**
213
+ * Optional carrier/place-holder yaw (radians, around world +Y) at the
214
+ * target. When provided, joint 5 (tool roll) is set so the gripper's
215
+ * "side" axes align with the carrier's — preventing a visible rotation
216
+ * snap when the carrier reparents to the gripper at pick / off the
217
+ * gripper at place.
218
+ *
219
+ * Derivation: with cumulative pitch ψ1+ψ2+ψ4 = π, the end-frame's
220
+ * world axes are determined by joint 0 (j0) and joint 5 (θ5):
221
+ * end_X = (-cos(j0 - θ5), 0, sin(j0 - θ5))
222
+ * Carriable's localRotation x:-π/2 makes carrier_world = TCP_world ∘ R_x(-π/2);
223
+ * for carrier_world to land at the carrier's pre-reparent yaw γ, we
224
+ * need TCP_world = R_y(γ) ∘ R_x(π/2), which gives:
225
+ * end_X = (cos γ, 0, -sin γ)
226
+ * Solving end_X equation vs. this target: j0 - θ5 = π + γ
227
+ * → θ5 = j0 - π - γ
228
+ * Wrapped to [-π, π] then clamped to chain[5].range.
229
+ *
230
+ * If omitted, joint 5 stays at 0 (no yaw alignment).
231
+ */
232
+ targetYaw) {
233
+ if (!isSixAxisZYYZYZ(chain))
234
+ return null;
235
+ const DEG2RAD = Math.PI / 180;
236
+ const L0 = chain[0].length;
237
+ const upper = chain[1].length;
238
+ const lower = chain[2].length + chain[3].length;
239
+ const wristTail = chain[4].length + chain[5].length;
240
+ const reach = upper + lower;
241
+ const j0Range = [chain[0].range[0] * DEG2RAD, chain[0].range[1] * DEG2RAD];
242
+ const j0 = resolveBaseYaw(target, j0Range, currentJointsRad[0] ?? 0);
243
+ if (j0 === null)
244
+ return null;
245
+ const T_H = Math.hypot(target.x, target.y);
246
+ const T_V = target.z;
247
+ const tcpRelH = T_H;
248
+ const tcpRelV = T_V - L0;
249
+ const p2 = tcpRelH * tcpRelH + tcpRelV * tcpRelV;
250
+ const p = Math.sqrt(p2);
251
+ // Try strict descent (α = π) first.
252
+ let alpha = Math.PI;
253
+ let wRelH = T_H;
254
+ let wRelV = (T_V + wristTail) - L0;
255
+ let d2 = wRelH * wRelH + wRelV * wRelV;
256
+ if (d2 > reach * reach + 1) {
257
+ // Relax: find α on reach boundary, closest to π.
258
+ const rhs = (p2 + wristTail * wristTail - reach * reach) / (2 * wristTail);
259
+ if (Math.abs(rhs) > p + 1e-3)
260
+ return null;
261
+ const beta = Math.atan2(tcpRelH, tcpRelV);
262
+ const offset = Math.acos(clamp(rhs / p, -1, 1));
263
+ const alphaA = beta + offset;
264
+ const alphaB = beta - offset;
265
+ const wrap = (a) => {
266
+ let x = a;
267
+ while (x > Math.PI)
268
+ x -= 2 * Math.PI;
269
+ while (x < -Math.PI)
270
+ x += 2 * Math.PI;
271
+ return x;
272
+ };
273
+ const distA = Math.abs(wrap(alphaA - Math.PI));
274
+ const distB = Math.abs(wrap(alphaB - Math.PI));
275
+ alpha = distA <= distB ? alphaA : alphaB;
276
+ wRelH = T_H - wristTail * Math.sin(alpha);
277
+ wRelV = T_V - wristTail * Math.cos(alpha) - L0;
278
+ d2 = wRelH * wRelH + wRelV * wRelV;
279
+ if (d2 > reach * reach + 1)
280
+ return null;
281
+ }
282
+ let cosPsi2 = (d2 - upper * upper - lower * lower) / (2 * upper * lower);
283
+ cosPsi2 = clamp(cosPsi2, -1, 1);
284
+ const psi2 = Math.acos(cosPsi2);
285
+ const psi1 = Math.atan2(wRelH, wRelV) -
286
+ Math.atan2(lower * Math.sin(psi2), upper + lower * Math.cos(psi2));
287
+ const psi4 = alpha - psi1 - psi2;
288
+ const radRanges = chain.map(c => [c.range[0] * DEG2RAD, c.range[1] * DEG2RAD]);
289
+ // Joint 5 (tool roll) — align gripper's "side" with the carrier's
290
+ // current world yaw, so reparenting at pick / release at place doesn't
291
+ // visibly snap the carrier's orientation.
292
+ let psi5 = 0;
293
+ if (typeof targetYaw === 'number' && Number.isFinite(targetYaw)) {
294
+ let v = j0 - Math.PI - targetYaw;
295
+ while (v > Math.PI)
296
+ v -= 2 * Math.PI;
297
+ while (v < -Math.PI)
298
+ v += 2 * Math.PI;
299
+ psi5 = v;
300
+ }
301
+ return [
302
+ clamp(j0, radRanges[0][0], radRanges[0][1]),
303
+ clamp(psi1, radRanges[1][0], radRanges[1][1]),
304
+ clamp(psi2, radRanges[2][0], radRanges[2][1]),
305
+ 0,
306
+ clamp(psi4, radRanges[4][0], radRanges[4][1]),
307
+ clamp(psi5, radRanges[5][0], radRanges[5][1])
308
+ ];
309
+ }
310
+ function clamp(v, lo, hi) {
311
+ return Math.max(lo, Math.min(hi, v));
312
+ }
313
+ //# sourceMappingURL=robot-arm-ik.js.map