@operato/scene-manufacturing 10.0.0-beta.30 → 10.0.0-beta.31

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.
@@ -2,8 +2,7 @@ import * as THREE from 'three';
2
2
  import { RealObjectGroup } from '@hatiolab/things-scene';
3
3
  export declare class RobotArm3D extends RealObjectGroup {
4
4
  private _smoothing?;
5
- private _animFrame?;
6
- private _isAnimating;
5
+ private _unsubTick;
7
6
  private _chain;
8
7
  private _jointFrames;
9
8
  build(): void;
@@ -128,6 +127,8 @@ export declare class RobotArm3D extends RealObjectGroup {
128
127
  */
129
128
  private _buildGripper;
130
129
  private _tcpFrame?;
130
+ /** 마지막 joint(=wrist) frame — 그리퍼 빌드가 부착되는 부모 노드. */
131
+ private _endFrame?;
131
132
  /**
132
133
  * Each gripper sub-builder returns its TCP z-offset (in `_endFrame`'s
133
134
  * local coordinates) — the point in space where a held carrier's grip
@@ -162,6 +163,18 @@ export declare class RobotArm3D extends RealObjectGroup {
162
163
  * been built yet (build pre-condition).
163
164
  */
164
165
  private _retargetIk;
166
+ /**
167
+ * 사용자 설정 home pose (state.joints / state.jointN) 의 joint 값 배열 반환.
168
+ * `goHome()` 의 target 으로 사용. _smoothing 의 current 와 무관 — pick/place 도중
169
+ * 호출되어도 본래 휴식 포즈를 반환.
170
+ */
171
+ getHomeJoints(): number[];
172
+ /**
173
+ * IK 를 거치지 않고 forward joint 값 배열을 smoothing target 으로 직접 설정.
174
+ * `goHome()` 외에도 외부에서 joint pose 직접 제어 시 사용.
175
+ * 완료 시 'tcp-reached' 이벤트 발생 (smoothing 의 allReached 경로 공통).
176
+ */
177
+ moveJointsTo(jointValues: number[]): void;
165
178
  updateDimension(): void;
166
179
  onchange(after: Record<string, unknown>, before: Record<string, unknown>): void;
167
180
  dispose(): void;
@@ -23,7 +23,7 @@
23
23
  * runs in matrix math (separate from this scene-graph walk) when needed.
24
24
  */
25
25
  import * as THREE from 'three';
26
- import { RealObjectGroup, resolveMaterial3d, applyMaterial3dProps } from '@hatiolab/things-scene';
26
+ import { RealObjectGroup, resolveMaterial3d, applyMaterial3dProps, frameClock } from '@hatiolab/things-scene';
27
27
  import { STYLES, CHAIN_PRESETS, DEFAULT_GRIPPER } from './robot-arm-styles.js';
28
28
  import { solveCCDIK, maxReach, isSixAxisZYYZYZ, resolveBaseYaw, analyticalIk6Axis } from './robot-arm-ik.js';
29
29
  const _AXIS_VEC = {
@@ -46,8 +46,7 @@ const DESCENT_BIAS = 30;
46
46
  const NO_RAYCAST = () => { };
47
47
  export class RobotArm3D extends RealObjectGroup {
48
48
  _smoothing;
49
- _animFrame;
50
- _isAnimating = false;
49
+ _unsubTick = null;
51
50
  _chain = [];
52
51
  _jointFrames = [];
53
52
  build() {
@@ -478,7 +477,6 @@ export class RobotArm3D extends RealObjectGroup {
478
477
  // Also exposed via `getGripperFrame()` so CarrierHolder.attachPointFor
479
478
  // can return it — making any Carriable child mount onto the moving
480
479
  // gripper TCP and follow IK automatically.
481
- ;
482
480
  this._endFrame = currentParent;
483
481
  }
484
482
  /**
@@ -660,6 +658,8 @@ export class RobotArm3D extends RealObjectGroup {
660
658
  tcp.position.z = tcpZ;
661
659
  }
662
660
  _tcpFrame;
661
+ /** 마지막 joint(=wrist) frame — 그리퍼 빌드가 부착되는 부모 노드. */
662
+ _endFrame;
663
663
  /**
664
664
  * Each gripper sub-builder returns its TCP z-offset (in `_endFrame`'s
665
665
  * local coordinates) — the point in space where a held carrier's grip
@@ -787,16 +787,16 @@ export class RobotArm3D extends RealObjectGroup {
787
787
  }
788
788
  // ─── Animation: smooth joint values toward solved target ─────────────
789
789
  _startAnimation() {
790
- this._isAnimating = true;
791
- let lastTime = performance.now();
792
- const tick = () => {
793
- if (!this._isAnimating || !this._smoothing)
790
+ if (this._unsubTick)
791
+ return;
792
+ // RobotArm joint motion 은 시뮬레이션 사건 (pickAndPlace
793
+ // 일부). speed 따라 가속, paused 시 정지. dt 는 sim ms.
794
+ this._unsubTick = frameClock.subscribe((dt) => {
795
+ if (!this._smoothing)
794
796
  return;
795
- const now = performance.now();
796
- const dt = Math.min((now - lastTime) / 1000, 0.1); // clamp for stability
797
- lastTime = now;
797
+ const dtSec = Math.min(dt / 1000, 0.1); // clamp for stability
798
798
  const { current, target, speed } = this._smoothing;
799
- const maxStep = speed * dt;
799
+ const maxStep = speed * dtSec;
800
800
  let allReached = true;
801
801
  for (let i = 0; i < current.length; i++) {
802
802
  const diff = (target[i] ?? 0) - current[i];
@@ -813,18 +813,18 @@ export class RobotArm3D extends RealObjectGroup {
813
813
  this.component.invalidate?.();
814
814
  if (allReached) {
815
815
  this._stopAnimation();
816
- this.component.trigger?.('tcp-reached', { component: this.component });
817
- return;
816
+ // Notify external code (pickAndPlace, custom scripts) that the
817
+ // gripper has reached its target. Component.trigger fires the
818
+ // standard things-scene event bus so consumers can subscribe via
819
+ // `component.on('tcp-reached', handler)`.
820
+ this.component.trigger('tcp-reached', { component: this.component });
818
821
  }
819
- this._animFrame = requestAnimationFrame(tick);
820
- };
821
- this._animFrame = requestAnimationFrame(tick);
822
+ }, { description: 'joint smoothing', component: this.component });
822
823
  }
823
824
  _stopAnimation() {
824
- this._isAnimating = false;
825
- if (this._animFrame !== undefined) {
826
- cancelAnimationFrame(this._animFrame);
827
- this._animFrame = undefined;
825
+ if (this._unsubTick) {
826
+ this._unsubTick();
827
+ this._unsubTick = null;
828
828
  }
829
829
  }
830
830
  /**
@@ -880,6 +880,43 @@ export class RobotArm3D extends RealObjectGroup {
880
880
  this._stopAnimation();
881
881
  }
882
882
  }
883
+ /**
884
+ * 사용자 설정 home pose (state.joints / state.jointN) 의 joint 값 배열 반환.
885
+ * `goHome()` 의 target 으로 사용. _smoothing 의 current 와 무관 — pick/place 도중
886
+ * 호출되어도 본래 휴식 포즈를 반환.
887
+ */
888
+ getHomeJoints() {
889
+ if (!this._chain)
890
+ return [];
891
+ return this._resolveJoints(this._chain, this.component.state);
892
+ }
893
+ /**
894
+ * IK 를 거치지 않고 forward joint 값 배열을 smoothing target 으로 직접 설정.
895
+ * `goHome()` 외에도 외부에서 joint pose 직접 제어 시 사용.
896
+ * 완료 시 'tcp-reached' 이벤트 발생 (smoothing 의 allReached 경로 공통).
897
+ */
898
+ moveJointsTo(jointValues) {
899
+ if (!this._chain)
900
+ return;
901
+ const state = this.component.state;
902
+ const previous = this._smoothing?.current?.slice() ?? this._resolveJoints(this._chain, state);
903
+ // 길이 보정 — chain 보다 짧으면 0 으로 채움, 길면 자름. range clamp.
904
+ const target = [];
905
+ for (let i = 0; i < this._chain.length; i++) {
906
+ let v = Number(jointValues[i] ?? 0);
907
+ if (!Number.isFinite(v))
908
+ v = 0;
909
+ v = Math.max(this._chain[i].range[0], Math.min(this._chain[i].range[1], v));
910
+ target.push(v);
911
+ }
912
+ this._smoothing = {
913
+ current: previous,
914
+ target,
915
+ speed: this._jointSpeed(state)
916
+ };
917
+ this._stopAnimation();
918
+ this._startAnimation();
919
+ }
883
920
  updateDimension() { }
884
921
  onchange(after, before) {
885
922
  // Structural changes — full rebuild.
@@ -1 +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"]}
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 frameClock,\n type Component,\n type Material3D\n} from '@hatiolab/things-scene'\nimport type { Unsubscribe } 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 _unsubTick: Unsubscribe | null = null\n private _chain: ChainElement[] = []\n private _jointFrames: THREE.Object3D[] = []\n\n build() {\n super.build()\n\n const state = this.component.state\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\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\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._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._endFrame\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._endFrame\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 /** 마지막 joint(=wrist) frame — 그리퍼 빌드가 부착되는 부모 노드. */\n private _endFrame?: 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 if (this._unsubTick) return\n // RobotArm joint motion 은 시뮬레이션 사건 (pickAndPlace 의\n // 일부). speed 따라 가속, paused 시 정지. dt 는 sim ms.\n this._unsubTick = frameClock.subscribe(\n (dt) => {\n if (!this._smoothing) return\n const dtSec = Math.min(dt / 1000, 0.1) // clamp for stability\n const { current, target, speed } = this._smoothing\n const maxStep = speed * dtSec\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.trigger('tcp-reached', { component: this.component })\n }\n },\n { description: 'joint smoothing', component: this.component }\n )\n }\n\n private _stopAnimation() {\n if (this._unsubTick) {\n this._unsubTick()\n this._unsubTick = null\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\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 /**\n * 사용자 설정 home pose (state.joints / state.jointN) 의 joint 값 배열 반환.\n * `goHome()` 의 target 으로 사용. _smoothing 의 current 와 무관 — pick/place 도중\n * 호출되어도 본래 휴식 포즈를 반환.\n */\n getHomeJoints(): number[] {\n if (!this._chain) return []\n return this._resolveJoints(this._chain, this.component.state)\n }\n\n /**\n * IK 를 거치지 않고 forward joint 값 배열을 smoothing target 으로 직접 설정.\n * `goHome()` 외에도 외부에서 joint pose 직접 제어 시 사용.\n * 완료 시 'tcp-reached' 이벤트 발생 (smoothing 의 allReached 경로 공통).\n */\n moveJointsTo(jointValues: number[]): void {\n if (!this._chain) return\n const state = this.component.state\n const previous = this._smoothing?.current?.slice() ?? this._resolveJoints(this._chain, state)\n // 길이 보정 — chain 보다 짧으면 0 으로 채움, 길면 자름. range clamp.\n const target: number[] = []\n for (let i = 0; i < this._chain.length; i++) {\n let v = Number(jointValues[i] ?? 0)\n if (!Number.isFinite(v)) v = 0\n v = Math.max(this._chain[i].range[0], Math.min(this._chain[i].range[1], v))\n target.push(v)\n }\n this._smoothing = {\n current: previous,\n target,\n speed: this._jointSpeed(state)\n }\n this._stopAnimation()\n this._startAnimation()\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\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"]}
@@ -1,8 +1,44 @@
1
1
  import * as THREE from 'three';
2
2
  import { Component, ComponentNature, RealObject } from '@hatiolab/things-scene';
3
- import type { SlotDef } from '@hatiolab/things-scene';
3
+ import type { SlotDef, State, Material3D } from '@hatiolab/things-scene';
4
4
  import { type Alignment, type Heights, type LegendBinding, type MoveOptions, type PlacementArchetype } from '@operato/scene-base';
5
+ import { RobotArm3D } from './robot-arm-3d.js';
6
+ import { type ChainPresetName } from './robot-arm-styles.js';
7
+ import type { ChainElement } from './robot-arm-ik.js';
8
+ import type { GripperConfig, LinkShape, JointHousing, StyleName } from './robot-arm-styles.js';
9
+ declare module '@hatiolab/things-scene' {
10
+ interface ComponentEventMap {
11
+ /** TCP 가 목표 도달 시 발생 (pickAndPlace 시퀀싱용). */
12
+ 'tcp-reached': [info: {
13
+ component: Component;
14
+ }];
15
+ }
16
+ }
5
17
  export type RobotArmStatus = 'idle' | 'moving' | 'gripping' | 'warn' | 'error';
18
+ /** RobotArm 컴포넌트 state */
19
+ export interface RobotArmState extends State {
20
+ style?: StyleName;
21
+ chainPreset?: ChainPresetName;
22
+ chain?: ChainElement[];
23
+ joints?: number[] | Record<string, number>;
24
+ linkShape?: LinkShape;
25
+ jointHousing?: JointHousing;
26
+ linkRadius?: number;
27
+ color?: string | number;
28
+ accentColor?: string | number;
29
+ gripper?: GripperConfig;
30
+ gripperType?: GripperConfig['type'];
31
+ target?: {
32
+ x: number;
33
+ y: number;
34
+ z: number;
35
+ yaw?: number;
36
+ };
37
+ showReachSphere?: boolean;
38
+ jointSpeed?: number;
39
+ status?: RobotArmStatus;
40
+ material3d?: Material3D;
41
+ }
6
42
  declare const Base: typeof Component & {
7
43
  new (...args: any[]): Component & {
8
44
  isMover: boolean;
@@ -12,6 +48,8 @@ declare const Base: typeof Component & {
12
48
  };
13
49
  };
14
50
  export default class RobotArm extends Base {
51
+ get state(): RobotArmState;
52
+ _realObject: RobotArm3D | undefined;
15
53
  static legends: Record<string, LegendBinding>;
16
54
  /**
17
55
  * Robot arms sit on the floor (or mount to a ceiling/wall — that's a
@@ -158,6 +196,26 @@ export default class RobotArm extends Base {
158
196
  */
159
197
  /** Short alias for `pickAndPlace`. Same arguments, same behavior. */
160
198
  pnp(carrier: Component, placeHolder: Component, options?: MoveOptions): Promise<void>;
199
+ /**
200
+ * Return all joints to the configured home pose (state.joints / state.jointN).
201
+ *
202
+ * IK target 을 클리어하고 forward joint 제어로 부드럽게 휴식 포즈로 복귀.
203
+ * `pickAndPlace` 의 마지막 단계로 자동 호출되며, 사용자가 명시적으로 호출도 가능.
204
+ *
205
+ * **인터럽트 가능**: 집에 도달하기 전에 새 `pick`/`place` 가 호출되면 (`set('target', ...)`)
206
+ * `_retargetIk()` 가 발동되어 smoothing 이 home 으로 가던 걸 멈추고 새 IK target 쪽으로
207
+ * redirect. mid-flight joint 값을 새 IK 의 시작점으로 사용해 끊김 없이 전환. tcp-reached
208
+ * 가 redirect 후의 새 target 에서 발생하면 goHome 의 await 도 함께 resolve (정상).
209
+ * 즉 "집으로 가다가 다음 pick 으로 자연스럽게 이어진다".
210
+ *
211
+ * @param options.timeoutMs joint smoothing 의 'tcp-reached' 대기 timeout (default 15000ms).
212
+ */
213
+ goHome(options?: MoveOptions): Promise<void>;
214
+ /**
215
+ * pick → place → goHome 시퀀스. 마지막에 home pose 복귀가 robot-arm 의
216
+ * pickAndPlace 표준 동작. (Mover mixin 의 default 는 pick + place 만)
217
+ */
218
+ pickAndPlace(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>;
161
219
  /**
162
220
  * Resolve a TCP position in this arm's chain-local frame.
163
221
  *
package/dist/robot-arm.js CHANGED
@@ -145,6 +145,12 @@ const STATIC_PROPERTIES = [
145
145
  // CarrierHolder.attachPointFor() (overridden below) provides 3D TCP positioning.
146
146
  const Base = Mover(CarrierHolder(ContainerCapacity(Legendable(Placeable(ContainerAbstract)))));
147
147
  let RobotArm = class RobotArm extends Base {
148
+ // `Base` is cast through `typeof Component` so TS sees `state` as an
149
+ // accessor; `declare state: …` would conflict with TS2610. Override the
150
+ // getter instead — runtime behavior is identical (just delegates to super).
151
+ get state() {
152
+ return super.state;
153
+ }
148
154
  static legends = {
149
155
  bodyColor: { from: 'status', legend: BODY_LEGEND },
150
156
  borderColor: { from: 'status', legend: BORDER_LEGEND },
@@ -287,8 +293,7 @@ let RobotArm = class RobotArm extends Base {
287
293
  'status' in after ||
288
294
  'bodyColor' in after ||
289
295
  'borderColor' in after) {
290
- ;
291
- this.clearCache?.('fillStyle');
296
+ this.clearCache('fillStyle');
292
297
  this.invalidate();
293
298
  }
294
299
  super.onchange(after, before);
@@ -439,6 +444,40 @@ let RobotArm = class RobotArm extends Base {
439
444
  pnp(carrier, placeHolder, options) {
440
445
  return this.pickAndPlace(carrier, placeHolder, options);
441
446
  }
447
+ /**
448
+ * Return all joints to the configured home pose (state.joints / state.jointN).
449
+ *
450
+ * IK target 을 클리어하고 forward joint 제어로 부드럽게 휴식 포즈로 복귀.
451
+ * `pickAndPlace` 의 마지막 단계로 자동 호출되며, 사용자가 명시적으로 호출도 가능.
452
+ *
453
+ * **인터럽트 가능**: 집에 도달하기 전에 새 `pick`/`place` 가 호출되면 (`set('target', ...)`)
454
+ * `_retargetIk()` 가 발동되어 smoothing 이 home 으로 가던 걸 멈추고 새 IK target 쪽으로
455
+ * redirect. mid-flight joint 값을 새 IK 의 시작점으로 사용해 끊김 없이 전환. tcp-reached
456
+ * 가 redirect 후의 새 target 에서 발생하면 goHome 의 await 도 함께 resolve (정상).
457
+ * 즉 "집으로 가다가 다음 pick 으로 자연스럽게 이어진다".
458
+ *
459
+ * @param options.timeoutMs joint smoothing 의 'tcp-reached' 대기 timeout (default 15000ms).
460
+ */
461
+ async goHome(options = {}) {
462
+ const timeoutMs = options.timeoutMs ?? 15000;
463
+ const ro = this._realObject;
464
+ if (!ro?.moveJointsTo || !ro?.getHomeJoints)
465
+ return;
466
+ // IK target 제거 — 다음 rebuild 시 _smoothing.target 이 IK 로 다시 풀리지 않도록.
467
+ // 외부에서 set('target', ...) 호출하면 다시 IK 모드로 전환되며 redirect.
468
+ this.set('target', undefined);
469
+ ro.moveJointsTo(ro.getHomeJoints());
470
+ await waitForTcpReached(this, timeoutMs);
471
+ }
472
+ /**
473
+ * pick → place → goHome 시퀀스. 마지막에 home pose 복귀가 robot-arm 의
474
+ * pickAndPlace 표준 동작. (Mover mixin 의 default 는 pick + place 만)
475
+ */
476
+ async pickAndPlace(carrier, holder, options = {}) {
477
+ await this.pick(carrier, options);
478
+ await this.place(carrier, holder, options);
479
+ await this.goHome(options);
480
+ }
442
481
  /**
443
482
  * Resolve a TCP position in this arm's chain-local frame.
444
483
  *
@@ -511,15 +550,14 @@ function waitForTcpReached(component, timeoutMs) {
511
550
  let timer;
512
551
  const onReached = () => {
513
552
  clearTimeout(timer);
514
- component.off?.('tcp-reached', onReached);
553
+ component.off('tcp-reached', onReached);
515
554
  resolve();
516
555
  };
517
556
  timer = setTimeout(() => {
518
- ;
519
- component.off?.('tcp-reached', onReached);
557
+ component.off('tcp-reached', onReached);
520
558
  reject(new Error('TCP reach timeout'));
521
559
  }, timeoutMs);
522
- component.on?.('tcp-reached', onReached);
560
+ component.on('tcp-reached', onReached);
523
561
  });
524
562
  }
525
563
  function sleep(ms) {
@@ -1 +1 @@
1
- {"version":3,"file":"robot-arm.js","sourceRoot":"","sources":["../src/robot-arm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAA8B,iBAAiB,EAAE,iBAAiB,EAAc,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAErI,OAAO,EACL,aAAa,EACb,UAAU,EACV,KAAK,EACL,SAAS,EAMV,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAwB,MAAM,uBAAuB,CAAA;AAK3E,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,MAAM;CAChB,CAAA;AAED,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,MAAM;CAChB,CAAA;AAED,MAAM,oBAAoB,GAAG;IAC3B,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,SAAS;CACnB,CAAA;AAED,MAAM,iBAAiB,GAAG;IACxB;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;gBAC9C,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;gBACpC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;gBACpC,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;aACzC;SACF;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,EAAE;gBAC5D,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;gBAClD,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;gBAClD,EAAE,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,uBAAuB,EAAE;aACnE;SACF;KACF;IACD,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE;IAC5D;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;gBAC1C,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACxC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;gBAC1C,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;gBAClD,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;aACnC;SACF;KACF;IACD,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,iBAAiB,EAAE;IACzE;QACE,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;gBAClC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;gBACtC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;gBAC1C,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;gBAClC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;aACrC;SACF;KACF;CACF,CAAA;AAED,8EAA8E;AAC9E,mEAAmE;AACnE,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAC1E,qBAAqB;AACrB,EAAE;AACF,2FAA2F;AAC3F,mEAAmE;AACnE,yEAAyE;AACzE,8EAA8E;AAC9E,EAAE;AACF,0EAA0E;AAC1E,8EAA8E;AAC9E,qEAAqE;AACrE,gDAAgD;AAChD,EAAE;AACF,oEAAoE;AACpE,sEAAsE;AACtE,mEAAmE;AACnE,0CAA0C;AAC1C,iFAAiF;AACjF,4EAA4E;AAC5E,iFAAiF;AACjF,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAO5F,CAAA;AAGc,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,IAAI;IACxC,MAAM,CAAC,OAAO,GAAkC;QAC9C,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;QAClD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE;QACtD,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE;KAC/D,CAAA;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAAS,GAAuB,OAAO,CAAA;IAC9C,MAAM,CAAC,KAAK,GAAc,QAAQ,CAAA;IAClC,MAAM,CAAC,YAAY,GAAG,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,CAAA;IAE3D,6EAA6E;IAE7E,gEAAgE;IAChE,IAAI,KAAK;QACP,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACzC,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,MAAM;QACR,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAA;QAC/B,qEAAqE;QACrE,sEAAsE;QACtE,iEAAiE;QACjE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACtC,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE;YACvB,IAAI,EAAE,QAAQ,CAAC,EAAE;YACjB,QAAQ,EAAE;gBACR,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACf,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;gBACf,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACpC;SACF,CAAC,CAAC,CAAA;QACH,OAAO;YACL,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,CAAC,GAAG,iBAAiB,EAAE,GAAG,UAAU,CAAQ;YACxD,IAAI,EAAE,2BAA2B;SAClC,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACH,IAAY,YAAY;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAY,CAAA;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,KAAK,CAAA;QAC5E,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,mBAAmB,CAAoB,CAAA;QAChF,OAAO,aAAa,CAAC,UAAU,CAAC,IAAI,aAAa,CAAC,mBAAmB,CAAC,CAAA;IACxE,CAAC;IAED,IAAI,OAAO;QACT,OAAO,EAAE,CAAA;IACX,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAA6B;QAClC,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QACnE,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAG,IAAI,CAAC,KAAa,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;QACpG,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAG,IAAI,CAAC,KAAa,CAAC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;QAC7G,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;QAEhD,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAClC,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;QACxB,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,WAAW,GAAG,WAAW,CAAA;QAC7B,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QACzB,GAAG,CAAC,MAAM,EAAE,CAAA;QAEZ,oEAAoE;QACpE,MAAM,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC,CAAA;QAC3B,MAAM,EAAE,GAAG,GAAG,GAAG,MAAM,GAAG,CAAC,CAAA;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;QACxC,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,WAAW,GAAG,WAAW,CAAA;QAC7B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,CAAA;QAEpE,gBAAgB;QAChB,GAAG,CAAC,SAAS,GAAG,WAAW,CAAA;QAC3B,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAA;QACpD,YAAY;QACZ,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;QAC5B,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;QAC5B,GAAG,CAAC,MAAM,EAAE,CAAA;QACZ,UAAU;QACV,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;QAC5B,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;QACtC,GAAG,CAAC,MAAM,EAAE,CAAA;QACZ,aAAa;QACb,GAAG,CAAC,SAAS,GAAG,WAAqB,CAAA;QACrC,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QAC/D,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QAC5E,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,OAAO,EAAE,CAAA;IACf,CAAC;IAED,QAAQ,CAAC,KAA8B,EAAE,MAA+B;QACtE,qEAAqE;QACrE,kDAAkD;QAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QACnE,IACE,QAAQ;YACR,OAAO,IAAI,KAAK;YAChB,aAAa,IAAI,KAAK;YACtB,OAAO,IAAI,KAAK;YAChB,QAAQ,IAAI,KAAK;YACjB,WAAW,IAAI,KAAK;YACpB,cAAc,IAAI,KAAK;YACvB,YAAY,IAAI,KAAK;YACrB,OAAO,IAAI,KAAK;YAChB,aAAa,IAAI,KAAK;YACtB,WAAW,IAAI,KAAK;YACpB,aAAa,IAAI,KAAK;YACtB,WAAW,IAAI,KAAK;YACpB,OAAO,IAAI,KAAK;YAChB,YAAY,IAAI,KAAK;YACrB,SAAS,IAAI,KAAK;YAClB,aAAa,IAAI,KAAK;YACtB,QAAQ,IAAI,KAAK;YACjB,iBAAiB,IAAI,KAAK;YAC1B,QAAQ,IAAI,KAAK;YACjB,WAAW,IAAI,KAAK;YACpB,aAAa,IAAI,KAAK,EACtB,CAAC;YACD,CAAC;YAAC,IAAY,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAA;YACxC,IAAI,CAAC,UAAU,EAAE,CAAA;QACnB,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC/B,CAAC;IAED,eAAe;QACb,OAAO,IAAI,UAAU,CAAC,IAAW,CAAC,CAAA;IACpC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,cAAc,CAAC,OAAkB;QAC/B,MAAM,EAAE,GAAI,IAAY,CAAC,WAAqC,CAAA;QAC9D,MAAM,KAAK,GAAG,EAAE,EAAE,eAAe,EAAE,EAAE,CAAA;QACrC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAA;QAC5B,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3C,OAAO;YACL,MAAM,EAAE,KAAK;YACb,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE;YAC3C,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;SAC/C,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACM,KAAK,CAAC,IAAI,CAAC,OAAkB,EAAE,UAAuB,EAAE;QAC/D,MAAM,SAAS,GAAI,OAAO,CAAC,SAAgC,IAAI,KAAK,CAAA;QACpE,MAAM,gBAAgB,GAAI,OAAO,CAAC,gBAAuC,IAAI,GAAG,CAAA;QAChF,MAAM,SAAS,GAAI,OAAO,CAAC,iBAAwC,IAAI,EAAE,CAAA;QACzE,qEAAqE;QACrE,yDAAyD;QACzD,mEAAmE;QACnE,qEAAqE;QACrE,6CAA6C;QAC7C,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,YAAY,GAAG,CAAC,CAAA;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,CAAC,CAAA;QAErE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAC5B,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QAExC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC1B,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAEvC;QAAC,IAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAA;QAClF,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,CAAE,IAAI,CAAC,KAAa,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QACzE,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAC/B,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACM,KAAK,CAAC,KAAK,CAAC,OAAkB,EAAE,MAAiB,EAAE,UAAuB,EAAE;QACnF,MAAM,SAAS,GAAI,OAAO,CAAC,SAAgC,IAAI,KAAK,CAAA;QACpE,MAAM,gBAAgB,GAAI,OAAO,CAAC,gBAAuC,IAAI,GAAG,CAAA;QAChF,MAAM,SAAS,GAAI,OAAO,CAAC,iBAAwC,IAAI,EAAE,CAAA;QACzE,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,CAAA,CAAC,4BAA4B;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,GAAG,CAAC,CAAA;QAEvE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAC5B,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QAExC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC1B,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAEvC;QAAC,MAAc,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAA;QACpF,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,CAAE,IAAI,CAAC,KAAa,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QACzE,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAC/B,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,qEAAqE;IACrE,GAAG,CAAC,OAAkB,EAAE,WAAsB,EAAE,OAAqB;QACnE,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;IACzD,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,UAAU,CAChB,SAAoB,EACpB,YAAY,GAAG,CAAC,EAChB,GAAY;QAEZ,MAAM,IAAI,GAAI,IAAY,CAAC,WAAqC,CAAA;QAEhE,IAAI,MAAiC,CAAA;QACrC,+CAA+C;QAC/C,MAAM,cAAc,GAAI,SAAiB,CAAC,cAAc,CAAA;QACxD,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YAClD,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;gBAClB,KAAK,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC7C,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YAC/D,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,GAAI,SAAiB,CAAC,WAAW,EAAE,QAAQ,CAAA;YACpD,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAClC,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACpD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrB,4DAA4D;YAC5D,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAA;YAC1B,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAA;QACjD,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QACjF,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAA;IACpD,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,SAAoB;QACjC,MAAM,GAAG,GAAI,SAAiB,CAAC,WAAW,EAAE,QAAQ,CAAA;QACpD,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAA;QAClB,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAClC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,UAAU,EAAE,CAAA;QAChC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAA;QACzB,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACvD,OAAO,CAAC,CAAC,CAAC,CAAA;IACZ,CAAC;;AA1XkB,QAAQ;IAD5B,cAAc,CAAC,WAAW,CAAC;GACP,QAAQ,CA2X5B;eA3XoB,QAAQ;AA6X7B;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,SAAoB,EAAE,SAAiB;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,KAAU,CAAA;QACd,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,YAAY,CAAC,KAAK,CAAC,CAClB;YAAC,SAAiB,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;YACnD,OAAO,EAAE,CAAA;QACX,CAAC,CAAA;QACD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,CAAC;YAAC,SAAiB,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;YACnD,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAA;QACxC,CAAC,EAAE,SAAS,CAAC,CACZ;QAAC,SAAiB,CAAC,EAAE,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,KAAK,CAAC,CAAU,EAAE,IAAY;IACrC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAC/D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,CAAY;IAChC,MAAM,GAAG,GAAI,CAAS,EAAE,WAAW,EAAE,cAAc,CAAA;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAA;IAC/D,OAAO,KAAK,CAAE,CAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AAC3C,CAAC;AAED,SAAS,SAAS,CAAC,GAAG,UAAqB;IACzC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,KAAK,aAAa;YAAE,OAAO,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Robot Arm — generalized articulated manipulator component.\n *\n * Designed to cover the visualization needs of robot arms WITHOUT a\n * specific URDF model. Configurable kinematic chain, link shape, joint\n * housing, gripper type — same component renders as a sleek cobot, a\n * heavy industrial 6-axis, a SCARA, or a minimal educational arm.\n *\n * State schema (all top-level properties optional except width/height):\n *\n * {\n * // structure\n * style?: 'industrial' | 'cobot' | 'scara' | 'minimal',\n * chainPreset?: '6-axis-industrial' | 'cobot-6-axis' | 'scara-4-axis' | 'pick-and-place-3-axis',\n * chain?: ChainElement[], // overrides preset\n * joints?: number[] | { [i]: number }, // current joint values\n *\n * // styling overrides\n * linkShape?, jointHousing?, linkRadius?, color?, accentColor?,\n *\n * // gripper\n * gripper?: GripperConfig,\n *\n * // IK target (TCP world position relative to component center, in\n * // 3D-z-up convention used by IK module)\n * target?: { x: number, y: number, z: number },\n *\n * // visualization\n * showReachSphere?: boolean\n * }\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, ContainerCapacity, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { SlotDef } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Legendable,\n Mover,\n Placeable,\n type Alignment,\n type Heights,\n type LegendBinding,\n type MoveOptions,\n type PlacementArchetype\n} from '@operato/scene-base'\n\nimport { RobotArm3D } from './robot-arm-3d.js'\nimport { CHAIN_PRESETS, type ChainPresetName } from './robot-arm-styles.js'\nimport type { ChainElement } from './robot-arm-ik.js'\n\nexport type RobotArmStatus = 'idle' | 'moving' | 'gripping' | 'warn' | 'error'\n\nconst BODY_LEGEND = {\n idle: '#ccc',\n moving: '#afd0f1',\n gripping: '#cfe6c8',\n warn: '#ffba00',\n error: '#e9746b',\n default: '#ccc'\n}\n\nconst BORDER_LEGEND = {\n idle: '#888',\n moving: '#87b1db',\n gripping: '#7aa274',\n warn: '#d96f21',\n error: '#a73928',\n default: '#888'\n}\n\nconst LAMP_EMISSIVE_LEGEND = {\n idle: '#333333',\n moving: '#44aaff',\n gripping: '#33aa44',\n warn: '#ffaa00',\n error: '#ff3333',\n default: '#333333'\n}\n\nconst STATIC_PROPERTIES = [\n {\n type: 'select',\n label: 'style',\n name: 'style',\n property: {\n options: [\n { display: 'Industrial', value: 'industrial' },\n { display: 'Cobot', value: 'cobot' },\n { display: 'SCARA', value: 'scara' },\n { display: 'Minimal', value: 'minimal' }\n ]\n }\n },\n {\n type: 'select',\n label: 'chain-preset',\n name: 'chainPreset',\n property: {\n options: [\n { display: '6-Axis Industrial', value: '6-axis-industrial' },\n { display: 'Cobot 6-Axis', value: 'cobot-6-axis' },\n { display: 'SCARA 4-Axis', value: 'scara-4-axis' },\n { display: 'Pick & Place 3-Axis', value: 'pick-and-place-3-axis' }\n ]\n }\n },\n { type: 'number', label: 'link-radius', name: 'linkRadius' },\n {\n type: 'select',\n label: 'gripper-type',\n name: 'gripperType',\n property: {\n options: [\n { display: 'Parallel', value: 'parallel' },\n { display: 'Suction', value: 'suction' },\n { display: 'Magnetic', value: 'magnetic' },\n { display: 'Three-Finger', value: 'three-finger' },\n { display: 'None', value: 'none' }\n ]\n }\n },\n { type: 'checkbox', label: 'show-reach-sphere', name: 'showReachSphere' },\n {\n type: 'select',\n label: 'status',\n name: 'status',\n property: {\n options: [\n { display: 'Idle', value: 'idle' },\n { display: 'Moving', value: 'moving' },\n { display: 'Gripping', value: 'gripping' },\n { display: 'Warn', value: 'warn' },\n { display: 'Error', value: 'error' }\n ]\n }\n }\n]\n\n// CarrierHolder + ContainerAbstract: the arm needs the container's child-list\n// machinery (addComponent / reparent / events) AND CarrierHolder's\n// attachPointFor hook. CarrierHolder mixin alone only publishes the attach\n// policy; it doesn't add child management. RectPath(Shape) was wrong here —\n// Shape is a leaf so reparent silently failed. ContainerAbstract provides\n// the missing piece.\n//\n// `ContainerAbstract` (not `Container`) — Container = MixinHTMLElement(ContainerAbstract),\n// which forces `isHTMLElement(): true` and trips the 3D pipeline's\n// addObject DOM-skip gate. Robot arm exists purely in the 3D scene graph\n// (URDF/IK joints, no DOM overlay), so the bare logical container is correct.\n//\n// Mover wraps the chain to publish pick/place/pickAndPlace primitives. It\n// must sit OUTSIDE CarrierHolder because Mover's defaults call this.reparent,\n// which CarrierHolder provides (overrides the base ContainerAbstract\n// version with the attach-frame-aware variant).\n//\n// The instance type cast surfaces Mover's API on `this` so subclass\n// `override` keywords compile and `this.pickAndPlace(...)` resolves —\n// without it, the `as unknown as typeof Component` cast erases all\n// mixin contributions to the static side.\n// ContainerCapacity inserted between CarrierHolder and Legendable — same pattern\n// as Forklift/AGV: receive()/dispatch() for slot-tracking + event emission;\n// CarrierHolder.attachPointFor() (overridden below) provides 3D TCP positioning.\nconst Base = Mover(CarrierHolder(ContainerCapacity(Legendable(Placeable(ContainerAbstract))))) as unknown as typeof Component & {\n new (...args: any[]): Component & {\n isMover: boolean\n pick(carrier: Component, options?: MoveOptions): Promise<void>\n place(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>\n pickAndPlace(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>\n }\n}\n\n@sceneComponent('robot-arm')\nexport default class RobotArm extends Base {\n static legends: Record<string, LegendBinding> = {\n bodyColor: { from: 'status', legend: BODY_LEGEND },\n borderColor: { from: 'status', legend: BORDER_LEGEND },\n lampEmissive: { from: 'status', legend: LAMP_EMISSIVE_LEGEND }\n }\n\n /**\n * Robot arms sit on the floor (or mount to a ceiling/wall — that's a\n * v2 feature). Default depth = operation - floor like other floor-\n * mounted equipment, so the chain reach scales with the configured\n * facility height.\n */\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (h: Heights) => h.operation - h.floor\n\n // ── ContainerCapacity ─────────────────────────────────────────────────────\n\n /** Single gripper slot — robot arm grips one item at a time. */\n get slots(): SlotDef[] {\n return [{ id: 'gripper', maxCount: 1 }]\n }\n\n /**\n * Dynamic nature — appends one number property per joint in the active\n * chain. Each property uses the joint's range as `min`/`max` so the\n * property panel can render a constrained slider/spinner. The chain\n * preset can change at runtime, and `get nature()` is re-evaluated\n * whenever the property panel queries it, so the joint count stays in\n * sync with the active preset.\n *\n * For revolute joints the value is in radians; for prismatic, scene units.\n */\n get nature(): ComponentNature {\n const chain = this._activeChain\n // Joint values: revolute = degrees (range usually ±180), prismatic =\n // scene length units. CHAIN_PRESETS already encode revolute ranges in\n // degrees; the 3D side converts to radians at the math boundary.\n const jointProps = chain.map((c, i) => ({\n type: 'number',\n label: `joint-${i + 1}`,\n name: `joint${i}`,\n property: {\n min: c.range[0],\n max: c.range[1],\n step: c.type === 'revolute' ? 1 : 1\n }\n }))\n return {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...STATIC_PROPERTIES, ...jointProps] as any,\n help: 'scene/component/robot-arm'\n }\n }\n\n /**\n * Resolve the active chain for property-panel introspection. Mirrors\n * the resolution in robot-arm-3d.ts (state.chain wins, else preset,\n * else default 6-axis-industrial). Kept simple — the 3D side does the\n * same logic with depth-based scaling, but for property labeling we\n * only need the structure (axis count + ranges), not absolute lengths.\n */\n private get _activeChain(): ChainElement[] {\n const state = this.state as any\n if (Array.isArray(state.chain) && state.chain.length > 0) return state.chain\n const presetName = (state.chainPreset ?? '6-axis-industrial') as ChainPresetName\n return CHAIN_PRESETS[presetName] ?? CHAIN_PRESETS['6-axis-industrial']\n }\n\n get anchors() {\n return []\n }\n\n /**\n * 2D — base rectangle + a stylized arm silhouette pointing toward the\n * top-right. Just enough to identify the component as a robot arm in\n * plan view; the real visual lives in 3D.\n */\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0, width = 100, height = 100 } = this.state\n const bodyFill = pickColor(this.state.fillStyle, (this.state as any).bodyColor, BODY_LEGEND.default)\n const borderColor = pickColor(this.state.strokeStyle, (this.state as any).borderColor, BORDER_LEGEND.default)\n const lineWidth = numOr(this.state.lineWidth, 1)\n\n ctx.beginPath()\n ctx.rect(left, top, width, height)\n ctx.fillStyle = bodyFill\n ctx.fill()\n ctx.strokeStyle = borderColor\n ctx.lineWidth = lineWidth\n ctx.stroke()\n\n // Stylized arm silhouette: base square at center → up → bent right.\n const cx = left + width / 2\n const cy = top + height / 2\n const r = Math.min(width, height) * 0.32\n ctx.save()\n ctx.strokeStyle = borderColor\n ctx.lineWidth = Math.max(lineWidth, Math.min(width, height) * 0.025)\n\n // Base pedestal\n ctx.fillStyle = borderColor\n ctx.fillRect(cx - r * 0.5, cy + r * 0.6, r, r * 0.3)\n // Upper arm\n ctx.beginPath()\n ctx.moveTo(cx, cy + r * 0.6)\n ctx.lineTo(cx, cy - r * 0.2)\n ctx.stroke()\n // Forearm\n ctx.beginPath()\n ctx.moveTo(cx, cy - r * 0.2)\n ctx.lineTo(cx + r * 0.7, cy - r * 0.7)\n ctx.stroke()\n // Joint dots\n ctx.fillStyle = borderColor as string\n ctx.beginPath()\n ctx.arc(cx, cy - r * 0.2, Math.max(2, r * 0.1), 0, Math.PI * 2)\n ctx.fill()\n ctx.beginPath()\n ctx.arc(cx + r * 0.7, cy - r * 0.7, Math.max(1.5, r * 0.08), 0, Math.PI * 2)\n ctx.fill()\n ctx.restore()\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n // Per-joint number properties (joint0 … jointN-1) are dynamic; treat\n // any key matching the pattern as a joint update.\n const hasJoint = Object.keys(after).some(k => /^joint\\d+$/.test(k))\n if (\n hasJoint ||\n 'style' in after ||\n 'chainPreset' in after ||\n 'chain' in after ||\n 'joints' 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 'lineWidth' in after ||\n 'alpha' in after ||\n 'material3d' in after ||\n 'gripper' in after ||\n 'gripperType' in after ||\n 'target' in after ||\n 'showReachSphere' in after ||\n 'status' in after ||\n 'bodyColor' in after ||\n 'borderColor' in after\n ) {\n ;(this as any).clearCache?.('fillStyle')\n this.invalidate()\n }\n super.onchange(after, before)\n }\n\n buildRealObject(): RealObject | undefined {\n return new RobotArm3D(this as any)\n }\n\n /**\n * CarrierHolder hook — return the gripper TCP frame so any Carriable\n * child (parcel/box/pallet/...) mounts onto the moving end-effector.\n * IK rotation propagates to the carrier through Three.js scene-graph.\n *\n * Pose convention (real-world pick-and-place: gripper pointing toward\n * the work, carrier hanging *beyond* the gripper tip):\n *\n * - Frame: TCP (gripper working point — between finger tips for\n * jaws, contact face for suction/magnetic). Built by\n * `RobotArm3D._buildGripper`. TCP's +Z = gripper-forward direction\n * (away from the wrist).\n *\n * - Rotation: x:-π/2 — maps carrier's local +Y axis (\"up\" in the\n * carrier's authored frame) to TCP's -Z direction. With the gripper\n * pointing down (typical work pose), TCP +Z = world -Y (down), so\n * TCP -Z = world +Y (up). Result: carrier's \"up\" stays world-up\n * during transit, and the carrier's body extends from TCP origin\n * in TCP +Z direction (down in world) — i.e. hanging BELOW the\n * gripper, not buried inside it.\n *\n * - Position: z = +halfDepth — places the carrier's TOP face center\n * at the TCP origin (where the fingers grip). Carrier's local +Y\n * extent (top) = halfDepth, which after x:-π/2 rotation maps to\n * TCP -halfDepth Z. Shifting carrier center to TCP +halfDepth Z\n * puts that top point exactly at TCP origin. Carrier body then\n * extends through TCP +Z, ending at TCP +depth (bottom face).\n *\n * Earlier (x:+π/2, z:-halfDepth) inverted the carrier's body direction\n * — body extended back into the wrist, leaving the box visually inside\n * the finger area. The current convention pushes the body OUT past the\n * fingertips, where a real gripper would hold it.\n */\n attachPointFor(carrier: Component) {\n const ro = (this as any)._realObject as RobotArm3D | undefined\n const frame = ro?.getGripperFrame?.()\n if (!frame) return undefined\n const halfDepth = resolveDepth(carrier) / 2\n return {\n attach: frame,\n localPosition: { x: 0, y: 0, z: halfDepth },\n localRotation: { x: -Math.PI / 2, y: 0, z: 0 }\n }\n }\n\n /**\n * Pick: TCP descends vertically onto the carrier's top face, gripper\n * closes, carrier becomes our child.\n *\n * 1. TCP → APPROACH above pick (carrier's xy, +clearance in world Y)\n * 2. TCP → pick (descend straight down to carrier's top face)\n * 3. close gripper + reparent(carrier → this)\n *\n * The approach waypoint exists so the FINAL leg is a clean vertical\n * descent — the gripper enters the carrier from straight above, not a\n * sideways sweep that could clip or grab at a wrong angle.\n *\n * Pose resolution: TCP lands on the CARRIER'S TOP FACE (carrier.world.y +\n * carrier.depth/2). After grip, `attachPointFor`'s `localPosition.z =\n * +halfDepth` keeps the carrier's top at TCP origin during transit —\n * exact, no offset drift.\n *\n * Each waypoint includes the carrier's world yaw so IK can spin joint 5\n * (tool roll) to align the gripper's \"side\" with the carrier's. Without\n * it, reparent at pick instantly snaps the carrier to the gripper's\n * axis, visibly twisting it 0° → up to 360° in one frame.\n *\n * @param options.approachClearance Vertical offset (world units)\n * between approach and pick targets. Default 10.\n * @param options.timeoutMs Per-segment IK timeout (default 15000ms).\n * @param options.reparentDuration Animation duration for reparent (default 800ms).\n */\n override async pick(carrier: Component, options: MoveOptions = {}): Promise<void> {\n const timeoutMs = (options.timeoutMs as number | undefined) ?? 15000\n const reparentDuration = (options.reparentDuration as number | undefined) ?? 800\n const clearance = (options.approachClearance as number | undefined) ?? 10\n // Read carrier height via _realObject.effectiveDepth — `state.depth`\n // is often not explicitly set (carriers like Box rely on\n // `static defaultDepth`), and reading state alone returns 0, which\n // collapses every Y offset and drives the gripper into the carrier's\n // volumetric center instead of its top face.\n const carrierDepth = resolveDepth(carrier)\n const halfDepth = carrierDepth / 2\n const yaw = this._yawOf(carrier)\n const target = this._targetFor(carrier, halfDepth, yaw)\n const approach = this._targetFor(carrier, halfDepth + clearance, yaw)\n\n this.set('target', approach)\n await waitForTcpReached(this, timeoutMs)\n\n this.set('target', target)\n await waitForTcpReached(this, timeoutMs)\n\n ;(this as any).reparent?.(carrier, { animated: true, duration: reparentDuration })\n this.set('gripper', { ...((this.state as any).gripper ?? {}), state: 1 })\n await sleep(reparentDuration)\n }\n\n /**\n * Place: TCP descends vertically over the holder, gripper opens,\n * carrier becomes the holder's child.\n *\n * 1. TCP → APPROACH above place (carrier's xy, +clearance)\n * 2. TCP → place (descend straight down to drop point)\n * 3. open gripper + reparent(carrier → holder)\n *\n * Pose resolution: TCP lands at where the carrier's top WILL BE after\n * the drop, so the carrier lands with its bottom on the holder's attach\n * surface. Computed as `holder.attachFrame.world.y + carrier.depth` (so\n * yOffset = carrierDepth, not halfDepth like pick).\n *\n * @see pick — same option semantics.\n */\n override async place(carrier: Component, holder: Component, options: MoveOptions = {}): Promise<void> {\n const timeoutMs = (options.timeoutMs as number | undefined) ?? 15000\n const reparentDuration = (options.reparentDuration as number | undefined) ?? 800\n const clearance = (options.approachClearance as number | undefined) ?? 10\n const carrierDepth = resolveDepth(carrier)\n const yaw = this._yawOf(holder)\n const target = this._targetFor(holder, carrierDepth, yaw) // top-of-carrier after drop\n const approach = this._targetFor(holder, carrierDepth + clearance, yaw)\n\n this.set('target', approach)\n await waitForTcpReached(this, timeoutMs)\n\n this.set('target', target)\n await waitForTcpReached(this, timeoutMs)\n\n ;(holder as any).reparent?.(carrier, { animated: true, duration: reparentDuration })\n this.set('gripper', { ...((this.state as any).gripper ?? {}), state: 0 })\n await sleep(reparentDuration)\n }\n\n /**\n * `pickAndPlace` is inherited from the `Mover` mixin default — runs\n * `pick(carrier)` then `place(carrier, holder)` sequentially. The\n * decomposition is safe: the carrier's world position only matters\n * during pick (carrier-relative waypoints), and after pick the carrier\n * is the TCP's child (so re-querying it would chase its own tail —\n * which we don't, since place uses holder-relative waypoints only).\n *\n * @example\n * ```ts\n * await robotArm.pickAndPlace(box, spotB)\n * await robotArm.pnp(parcel, palletA, { approachClearance: 30 })\n * ```\n */\n /** Short alias for `pickAndPlace`. Same arguments, same behavior. */\n pnp(carrier: Component, placeHolder: Component, options?: MoveOptions): Promise<void> {\n return this.pickAndPlace(carrier, placeHolder, options)\n }\n\n /**\n * Resolve a TCP position in this arm's chain-local frame.\n *\n * For a CarrierHolder (has `attachPointFor`), uses the holder's own\n * attach frame as the base — that's the canonical \"where carriers\n * sit on me\" point (top of Spot's pad, gripper TCP for another arm,\n * etc.). For a plain carrier, uses its world center.\n *\n * `worldYOffset` is added to the resolved world Y before projecting\n * back to chain-local — used by pickAndPlace to lift the TCP above\n * the target (approach waypoints) and to land it on the carrier's\n * top face rather than its volumetric center.\n */\n private _targetFor(\n component: Component,\n worldYOffset = 0,\n yaw?: number\n ): { x: number; y: number; z: number; yaw?: number } {\n const ro3d = (this as any)._realObject as RobotArm3D | undefined\n\n let baseWp: THREE.Vector3 | undefined\n // Prefer holder's attach frame when available.\n const attachPointFor = (component as any).attachPointFor\n if (typeof attachPointFor === 'function') {\n const point = attachPointFor.call(component, this)\n if (point?.attach) {\n point.attach.updateWorldMatrix?.(true, false)\n baseWp = point.attach.getWorldPosition?.(new THREE.Vector3())\n }\n }\n if (!baseWp) {\n const obj = (component as any)._realObject?.object3d\n if (obj) {\n obj.updateWorldMatrix(true, false)\n baseWp = obj.getWorldPosition(new THREE.Vector3())\n }\n }\n if (!ro3d || !baseWp) {\n // Final fallback: 2D bounds center — only before 3D builds.\n const c = component.center\n return { x: c.x, y: worldYOffset, z: c.y, yaw }\n }\n const local = ro3d.worldToChainLocal(baseWp.x, baseWp.y + worldYOffset, baseWp.z)\n return { x: local.x, y: local.y, z: local.z, yaw }\n }\n\n /**\n * Extract a component's world yaw (rotation around world +Y) from its\n * 3D object's world matrix. Returns 0 if the object isn't built yet.\n * Used by `pickAndPlace` so the gripper can match the carrier's /\n * placeHolder's current orientation — preventing a yaw snap at the\n * moment of reparent.\n */\n private _yawOf(component: Component): number {\n const obj = (component as any)._realObject?.object3d\n if (!obj) return 0\n obj.updateWorldMatrix(true, false)\n const q = new THREE.Quaternion()\n obj.getWorldQuaternion(q)\n const e = new THREE.Euler().setFromQuaternion(q, 'YXZ')\n return e.y\n }\n}\n\n/**\n * Resolve when the robot arm fires `tcp-reached`, reject on timeout.\n * The 3D side fires this event on smoothing completion (last joint\n * value within threshold of its target).\n */\nfunction waitForTcpReached(component: Component, timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n let timer: any\n const onReached = () => {\n clearTimeout(timer)\n ;(component as any).off?.('tcp-reached', onReached)\n resolve()\n }\n timer = setTimeout(() => {\n ;(component as any).off?.('tcp-reached', onReached)\n reject(new Error('TCP reach timeout'))\n }, timeoutMs)\n ;(component as any).on?.('tcp-reached', onReached)\n })\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction numOr(v: unknown, dflt: number): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : dflt\n}\n\n/**\n * Resolve a component's 3D height. things-scene v10 carriers (Box, Pallet,\n * etc.) typically declare `static defaultDepth` rather than setting\n * `state.depth`, so reading state alone returns 0 — wrong for a\n * default-sized box. The framework resolves the actual value into\n * `_realObject.effectiveDepth`. Falls back to `state.depth` for\n * components built before their RealObject exists.\n */\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)?._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n return numOr((c as any)?.state?.depth, 0)\n}\n\nfunction pickColor(...candidates: unknown[]): string {\n for (const c of candidates) {\n if (typeof c === 'string' && c && c !== 'transparent') return c\n }\n return '#888'\n}\n"]}
1
+ {"version":3,"file":"robot-arm.js","sourceRoot":"","sources":["../src/robot-arm.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Robot Arm — generalized articulated manipulator component.\n *\n * Designed to cover the visualization needs of robot arms WITHOUT a\n * specific URDF model. Configurable kinematic chain, link shape, joint\n * housing, gripper type — same component renders as a sleek cobot, a\n * heavy industrial 6-axis, a SCARA, or a minimal educational arm.\n *\n * State schema (all top-level properties optional except width/height):\n *\n * {\n * // structure\n * style?: 'industrial' | 'cobot' | 'scara' | 'minimal',\n * chainPreset?: '6-axis-industrial' | 'cobot-6-axis' | 'scara-4-axis' | 'pick-and-place-3-axis',\n * chain?: ChainElement[], // overrides preset\n * joints?: number[] | { [i]: number }, // current joint values\n *\n * // styling overrides\n * linkShape?, jointHousing?, linkRadius?, color?, accentColor?,\n *\n * // gripper\n * gripper?: GripperConfig,\n *\n * // IK target (TCP world position relative to component center, in\n * // 3D-z-up convention used by IK module)\n * target?: { x: number, y: number, z: number },\n *\n * // visualization\n * showReachSphere?: boolean\n * }\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, ContainerCapacity, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { SlotDef, State, Material3D } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Legendable,\n Mover,\n Placeable,\n type Alignment,\n type Heights,\n type LegendBinding,\n type MoveOptions,\n type PlacementArchetype\n} from '@operato/scene-base'\n\nimport { RobotArm3D } from './robot-arm-3d.js'\nimport { CHAIN_PRESETS, type ChainPresetName } from './robot-arm-styles.js'\nimport type { ChainElement } from './robot-arm-ik.js'\nimport type { GripperConfig, LinkShape, JointHousing, StyleName } from './robot-arm-styles.js'\n\n// ── ComponentEventMap 도메인 augmentation ─────────────────────────────────\n// RobotArm 이 발생시키는 도메인 이벤트들. things-scene 의 ComponentEventMap 에\n// 추가 등록하여 component.on/trigger 에서 자동완성 + 페이로드 타입 검증.\ndeclare module '@hatiolab/things-scene' {\n interface ComponentEventMap {\n /** TCP 가 목표 도달 시 발생 (pickAndPlace 시퀀싱용). */\n 'tcp-reached': [info: { component: Component }]\n }\n}\n\nexport type RobotArmStatus = 'idle' | 'moving' | 'gripping' | 'warn' | 'error'\n\n/** RobotArm 컴포넌트 state */\nexport interface RobotArmState extends State {\n // ── 구조 ──\n style?: StyleName\n chainPreset?: ChainPresetName\n chain?: ChainElement[]\n joints?: number[] | Record<string, number>\n linkShape?: LinkShape\n jointHousing?: JointHousing\n linkRadius?: number\n color?: string | number\n accentColor?: string | number\n\n // ── 그리퍼 ──\n gripper?: GripperConfig\n gripperType?: GripperConfig['type']\n\n // ── IK 타겟 ──\n target?: { x: number; y: number; z: number; yaw?: number }\n\n // ── 시각화 ──\n showReachSphere?: boolean\n\n // ── 모션 ──\n jointSpeed?: number\n\n // ── 운영 상태 ──\n status?: RobotArmStatus\n\n // ── 3D 재질 ──\n material3d?: Material3D\n}\n\nconst BODY_LEGEND = {\n idle: '#ccc',\n moving: '#afd0f1',\n gripping: '#cfe6c8',\n warn: '#ffba00',\n error: '#e9746b',\n default: '#ccc'\n}\n\nconst BORDER_LEGEND = {\n idle: '#888',\n moving: '#87b1db',\n gripping: '#7aa274',\n warn: '#d96f21',\n error: '#a73928',\n default: '#888'\n}\n\nconst LAMP_EMISSIVE_LEGEND = {\n idle: '#333333',\n moving: '#44aaff',\n gripping: '#33aa44',\n warn: '#ffaa00',\n error: '#ff3333',\n default: '#333333'\n}\n\nconst STATIC_PROPERTIES = [\n {\n type: 'select',\n label: 'style',\n name: 'style',\n property: {\n options: [\n { display: 'Industrial', value: 'industrial' },\n { display: 'Cobot', value: 'cobot' },\n { display: 'SCARA', value: 'scara' },\n { display: 'Minimal', value: 'minimal' }\n ]\n }\n },\n {\n type: 'select',\n label: 'chain-preset',\n name: 'chainPreset',\n property: {\n options: [\n { display: '6-Axis Industrial', value: '6-axis-industrial' },\n { display: 'Cobot 6-Axis', value: 'cobot-6-axis' },\n { display: 'SCARA 4-Axis', value: 'scara-4-axis' },\n { display: 'Pick & Place 3-Axis', value: 'pick-and-place-3-axis' }\n ]\n }\n },\n { type: 'number', label: 'link-radius', name: 'linkRadius' },\n {\n type: 'select',\n label: 'gripper-type',\n name: 'gripperType',\n property: {\n options: [\n { display: 'Parallel', value: 'parallel' },\n { display: 'Suction', value: 'suction' },\n { display: 'Magnetic', value: 'magnetic' },\n { display: 'Three-Finger', value: 'three-finger' },\n { display: 'None', value: 'none' }\n ]\n }\n },\n { type: 'checkbox', label: 'show-reach-sphere', name: 'showReachSphere' },\n {\n type: 'select',\n label: 'status',\n name: 'status',\n property: {\n options: [\n { display: 'Idle', value: 'idle' },\n { display: 'Moving', value: 'moving' },\n { display: 'Gripping', value: 'gripping' },\n { display: 'Warn', value: 'warn' },\n { display: 'Error', value: 'error' }\n ]\n }\n }\n]\n\n// CarrierHolder + ContainerAbstract: the arm needs the container's child-list\n// machinery (addComponent / reparent / events) AND CarrierHolder's\n// attachPointFor hook. CarrierHolder mixin alone only publishes the attach\n// policy; it doesn't add child management. RectPath(Shape) was wrong here —\n// Shape is a leaf so reparent silently failed. ContainerAbstract provides\n// the missing piece.\n//\n// `ContainerAbstract` (not `Container`) — Container = MixinHTMLElement(ContainerAbstract),\n// which forces `isHTMLElement(): true` and trips the 3D pipeline's\n// addObject DOM-skip gate. Robot arm exists purely in the 3D scene graph\n// (URDF/IK joints, no DOM overlay), so the bare logical container is correct.\n//\n// Mover wraps the chain to publish pick/place/pickAndPlace primitives. It\n// must sit OUTSIDE CarrierHolder because Mover's defaults call this.reparent,\n// which CarrierHolder provides (overrides the base ContainerAbstract\n// version with the attach-frame-aware variant).\n//\n// The instance type cast surfaces Mover's API on `this` so subclass\n// `override` keywords compile and `this.pickAndPlace(...)` resolves —\n// without it, the `as unknown as typeof Component` cast erases all\n// mixin contributions to the static side.\n// ContainerCapacity inserted between CarrierHolder and Legendable — same pattern\n// as Forklift/AGV: receive()/dispatch() for slot-tracking + event emission;\n// CarrierHolder.attachPointFor() (overridden below) provides 3D TCP positioning.\nconst Base = Mover(CarrierHolder(ContainerCapacity(Legendable(Placeable(ContainerAbstract))))) as unknown as typeof Component & {\n new (...args: any[]): Component & {\n isMover: boolean\n pick(carrier: Component, options?: MoveOptions): Promise<void>\n place(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>\n pickAndPlace(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>\n }\n}\n\n@sceneComponent('robot-arm')\nexport default class RobotArm extends Base {\n // `Base` is cast through `typeof Component` so TS sees `state` as an\n // accessor; `declare state: …` would conflict with TS2610. Override the\n // getter instead — runtime behavior is identical (just delegates to super).\n override get state(): RobotArmState {\n return super.state as RobotArmState\n }\n\n declare _realObject: RobotArm3D | undefined\n\n static legends: Record<string, LegendBinding> = {\n bodyColor: { from: 'status', legend: BODY_LEGEND },\n borderColor: { from: 'status', legend: BORDER_LEGEND },\n lampEmissive: { from: 'status', legend: LAMP_EMISSIVE_LEGEND }\n }\n\n /**\n * Robot arms sit on the floor (or mount to a ceiling/wall — that's a\n * v2 feature). Default depth = operation - floor like other floor-\n * mounted equipment, so the chain reach scales with the configured\n * facility height.\n */\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (h: Heights) => h.operation - h.floor\n\n // ── ContainerCapacity ─────────────────────────────────────────────────────\n\n /** Single gripper slot — robot arm grips one item at a time. */\n get slots(): SlotDef[] {\n return [{ id: 'gripper', maxCount: 1 }]\n }\n\n /**\n * Dynamic nature — appends one number property per joint in the active\n * chain. Each property uses the joint's range as `min`/`max` so the\n * property panel can render a constrained slider/spinner. The chain\n * preset can change at runtime, and `get nature()` is re-evaluated\n * whenever the property panel queries it, so the joint count stays in\n * sync with the active preset.\n *\n * For revolute joints the value is in radians; for prismatic, scene units.\n */\n get nature(): ComponentNature {\n const chain = this._activeChain\n // Joint values: revolute = degrees (range usually ±180), prismatic =\n // scene length units. CHAIN_PRESETS already encode revolute ranges in\n // degrees; the 3D side converts to radians at the math boundary.\n const jointProps = chain.map((c, i) => ({\n type: 'number',\n label: `joint-${i + 1}`,\n name: `joint${i}`,\n property: {\n min: c.range[0],\n max: c.range[1],\n step: c.type === 'revolute' ? 1 : 1\n }\n }))\n return {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...STATIC_PROPERTIES, ...jointProps] as any,\n help: 'scene/component/robot-arm'\n }\n }\n\n /**\n * Resolve the active chain for property-panel introspection. Mirrors\n * the resolution in robot-arm-3d.ts (state.chain wins, else preset,\n * else default 6-axis-industrial). Kept simple — the 3D side does the\n * same logic with depth-based scaling, but for property labeling we\n * only need the structure (axis count + ranges), not absolute lengths.\n */\n private get _activeChain(): ChainElement[] {\n const state = this.state\n if (Array.isArray(state.chain) && state.chain.length > 0) return state.chain\n const presetName = (state.chainPreset ?? '6-axis-industrial') as ChainPresetName\n return CHAIN_PRESETS[presetName] ?? CHAIN_PRESETS['6-axis-industrial']\n }\n\n get anchors() {\n return []\n }\n\n /**\n * 2D — base rectangle + a stylized arm silhouette pointing toward the\n * top-right. Just enough to identify the component as a robot arm in\n * plan view; the real visual lives in 3D.\n */\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0, width = 100, height = 100 } = this.state\n const bodyFill = pickColor(this.state.fillStyle, this.state.bodyColor, BODY_LEGEND.default)\n const borderColor = pickColor(this.state.strokeStyle, this.state.borderColor, BORDER_LEGEND.default)\n const lineWidth = numOr(this.state.lineWidth, 1)\n\n ctx.beginPath()\n ctx.rect(left, top, width, height)\n ctx.fillStyle = bodyFill\n ctx.fill()\n ctx.strokeStyle = borderColor\n ctx.lineWidth = lineWidth\n ctx.stroke()\n\n // Stylized arm silhouette: base square at center → up → bent right.\n const cx = left + width / 2\n const cy = top + height / 2\n const r = Math.min(width, height) * 0.32\n ctx.save()\n ctx.strokeStyle = borderColor\n ctx.lineWidth = Math.max(lineWidth, Math.min(width, height) * 0.025)\n\n // Base pedestal\n ctx.fillStyle = borderColor\n ctx.fillRect(cx - r * 0.5, cy + r * 0.6, r, r * 0.3)\n // Upper arm\n ctx.beginPath()\n ctx.moveTo(cx, cy + r * 0.6)\n ctx.lineTo(cx, cy - r * 0.2)\n ctx.stroke()\n // Forearm\n ctx.beginPath()\n ctx.moveTo(cx, cy - r * 0.2)\n ctx.lineTo(cx + r * 0.7, cy - r * 0.7)\n ctx.stroke()\n // Joint dots\n ctx.fillStyle = borderColor as string\n ctx.beginPath()\n ctx.arc(cx, cy - r * 0.2, Math.max(2, r * 0.1), 0, Math.PI * 2)\n ctx.fill()\n ctx.beginPath()\n ctx.arc(cx + r * 0.7, cy - r * 0.7, Math.max(1.5, r * 0.08), 0, Math.PI * 2)\n ctx.fill()\n ctx.restore()\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n // Per-joint number properties (joint0 … jointN-1) are dynamic; treat\n // any key matching the pattern as a joint update.\n const hasJoint = Object.keys(after).some(k => /^joint\\d+$/.test(k))\n if (\n hasJoint ||\n 'style' in after ||\n 'chainPreset' in after ||\n 'chain' in after ||\n 'joints' 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 'lineWidth' in after ||\n 'alpha' in after ||\n 'material3d' in after ||\n 'gripper' in after ||\n 'gripperType' in after ||\n 'target' in after ||\n 'showReachSphere' in after ||\n 'status' in after ||\n 'bodyColor' in after ||\n 'borderColor' in after\n ) {\n this.clearCache('fillStyle')\n this.invalidate()\n }\n super.onchange(after, before)\n }\n\n buildRealObject(): RealObject | undefined {\n return new RobotArm3D(this)\n }\n\n /**\n * CarrierHolder hook — return the gripper TCP frame so any Carriable\n * child (parcel/box/pallet/...) mounts onto the moving end-effector.\n * IK rotation propagates to the carrier through Three.js scene-graph.\n *\n * Pose convention (real-world pick-and-place: gripper pointing toward\n * the work, carrier hanging *beyond* the gripper tip):\n *\n * - Frame: TCP (gripper working point — between finger tips for\n * jaws, contact face for suction/magnetic). Built by\n * `RobotArm3D._buildGripper`. TCP's +Z = gripper-forward direction\n * (away from the wrist).\n *\n * - Rotation: x:-π/2 — maps carrier's local +Y axis (\"up\" in the\n * carrier's authored frame) to TCP's -Z direction. With the gripper\n * pointing down (typical work pose), TCP +Z = world -Y (down), so\n * TCP -Z = world +Y (up). Result: carrier's \"up\" stays world-up\n * during transit, and the carrier's body extends from TCP origin\n * in TCP +Z direction (down in world) — i.e. hanging BELOW the\n * gripper, not buried inside it.\n *\n * - Position: z = +halfDepth — places the carrier's TOP face center\n * at the TCP origin (where the fingers grip). Carrier's local +Y\n * extent (top) = halfDepth, which after x:-π/2 rotation maps to\n * TCP -halfDepth Z. Shifting carrier center to TCP +halfDepth Z\n * puts that top point exactly at TCP origin. Carrier body then\n * extends through TCP +Z, ending at TCP +depth (bottom face).\n *\n * Earlier (x:+π/2, z:-halfDepth) inverted the carrier's body direction\n * — body extended back into the wrist, leaving the box visually inside\n * the finger area. The current convention pushes the body OUT past the\n * fingertips, where a real gripper would hold it.\n */\n attachPointFor(carrier: Component) {\n const ro = this._realObject\n const frame = ro?.getGripperFrame?.()\n if (!frame) return undefined\n const halfDepth = resolveDepth(carrier) / 2\n return {\n attach: frame,\n localPosition: { x: 0, y: 0, z: halfDepth },\n localRotation: { x: -Math.PI / 2, y: 0, z: 0 }\n }\n }\n\n /**\n * Pick: TCP descends vertically onto the carrier's top face, gripper\n * closes, carrier becomes our child.\n *\n * 1. TCP → APPROACH above pick (carrier's xy, +clearance in world Y)\n * 2. TCP → pick (descend straight down to carrier's top face)\n * 3. close gripper + reparent(carrier → this)\n *\n * The approach waypoint exists so the FINAL leg is a clean vertical\n * descent — the gripper enters the carrier from straight above, not a\n * sideways sweep that could clip or grab at a wrong angle.\n *\n * Pose resolution: TCP lands on the CARRIER'S TOP FACE (carrier.world.y +\n * carrier.depth/2). After grip, `attachPointFor`'s `localPosition.z =\n * +halfDepth` keeps the carrier's top at TCP origin during transit —\n * exact, no offset drift.\n *\n * Each waypoint includes the carrier's world yaw so IK can spin joint 5\n * (tool roll) to align the gripper's \"side\" with the carrier's. Without\n * it, reparent at pick instantly snaps the carrier to the gripper's\n * axis, visibly twisting it 0° → up to 360° in one frame.\n *\n * @param options.approachClearance Vertical offset (world units)\n * between approach and pick targets. Default 10.\n * @param options.timeoutMs Per-segment IK timeout (default 15000ms).\n * @param options.reparentDuration Animation duration for reparent (default 800ms).\n */\n override async pick(carrier: Component, options: MoveOptions = {}): Promise<void> {\n const timeoutMs = (options.timeoutMs as number | undefined) ?? 15000\n const reparentDuration = (options.reparentDuration as number | undefined) ?? 800\n const clearance = (options.approachClearance as number | undefined) ?? 10\n // Read carrier height via _realObject.effectiveDepth — `state.depth`\n // is often not explicitly set (carriers like Box rely on\n // `static defaultDepth`), and reading state alone returns 0, which\n // collapses every Y offset and drives the gripper into the carrier's\n // volumetric center instead of its top face.\n const carrierDepth = resolveDepth(carrier)\n const halfDepth = carrierDepth / 2\n const yaw = this._yawOf(carrier)\n const target = this._targetFor(carrier, halfDepth, yaw)\n const approach = this._targetFor(carrier, halfDepth + clearance, yaw)\n\n this.set('target', approach)\n await waitForTcpReached(this, timeoutMs)\n\n this.set('target', target)\n await waitForTcpReached(this, timeoutMs)\n\n ;(this as any).reparent?.(carrier, { animated: true, duration: reparentDuration })\n this.set('gripper', { ...(this.state.gripper ?? {}), state: 1 })\n await sleep(reparentDuration)\n }\n\n /**\n * Place: TCP descends vertically over the holder, gripper opens,\n * carrier becomes the holder's child.\n *\n * 1. TCP → APPROACH above place (carrier's xy, +clearance)\n * 2. TCP → place (descend straight down to drop point)\n * 3. open gripper + reparent(carrier → holder)\n *\n * Pose resolution: TCP lands at where the carrier's top WILL BE after\n * the drop, so the carrier lands with its bottom on the holder's attach\n * surface. Computed as `holder.attachFrame.world.y + carrier.depth` (so\n * yOffset = carrierDepth, not halfDepth like pick).\n *\n * @see pick — same option semantics.\n */\n override async place(carrier: Component, holder: Component, options: MoveOptions = {}): Promise<void> {\n const timeoutMs = (options.timeoutMs as number | undefined) ?? 15000\n const reparentDuration = (options.reparentDuration as number | undefined) ?? 800\n const clearance = (options.approachClearance as number | undefined) ?? 10\n const carrierDepth = resolveDepth(carrier)\n const yaw = this._yawOf(holder)\n const target = this._targetFor(holder, carrierDepth, yaw) // top-of-carrier after drop\n const approach = this._targetFor(holder, carrierDepth + clearance, yaw)\n\n this.set('target', approach)\n await waitForTcpReached(this, timeoutMs)\n\n this.set('target', target)\n await waitForTcpReached(this, timeoutMs)\n\n ;(holder as any).reparent?.(carrier, { animated: true, duration: reparentDuration })\n this.set('gripper', { ...(this.state.gripper ?? {}), state: 0 })\n await sleep(reparentDuration)\n }\n\n /**\n * `pickAndPlace` is inherited from the `Mover` mixin default — runs\n * `pick(carrier)` then `place(carrier, holder)` sequentially. The\n * decomposition is safe: the carrier's world position only matters\n * during pick (carrier-relative waypoints), and after pick the carrier\n * is the TCP's child (so re-querying it would chase its own tail —\n * which we don't, since place uses holder-relative waypoints only).\n *\n * @example\n * ```ts\n * await robotArm.pickAndPlace(box, spotB)\n * await robotArm.pnp(parcel, palletA, { approachClearance: 30 })\n * ```\n */\n /** Short alias for `pickAndPlace`. Same arguments, same behavior. */\n pnp(carrier: Component, placeHolder: Component, options?: MoveOptions): Promise<void> {\n return this.pickAndPlace(carrier, placeHolder, options)\n }\n\n /**\n * Return all joints to the configured home pose (state.joints / state.jointN).\n *\n * IK target 을 클리어하고 forward joint 제어로 부드럽게 휴식 포즈로 복귀.\n * `pickAndPlace` 의 마지막 단계로 자동 호출되며, 사용자가 명시적으로 호출도 가능.\n *\n * **인터럽트 가능**: 집에 도달하기 전에 새 `pick`/`place` 가 호출되면 (`set('target', ...)`)\n * `_retargetIk()` 가 발동되어 smoothing 이 home 으로 가던 걸 멈추고 새 IK target 쪽으로\n * redirect. mid-flight joint 값을 새 IK 의 시작점으로 사용해 끊김 없이 전환. tcp-reached\n * 가 redirect 후의 새 target 에서 발생하면 goHome 의 await 도 함께 resolve (정상).\n * 즉 \"집으로 가다가 다음 pick 으로 자연스럽게 이어진다\".\n *\n * @param options.timeoutMs joint smoothing 의 'tcp-reached' 대기 timeout (default 15000ms).\n */\n async goHome(options: MoveOptions = {}): Promise<void> {\n const timeoutMs = (options.timeoutMs as number | undefined) ?? 15000\n const ro = this._realObject as any\n if (!ro?.moveJointsTo || !ro?.getHomeJoints) return\n // IK target 제거 — 다음 rebuild 시 _smoothing.target 이 IK 로 다시 풀리지 않도록.\n // 외부에서 set('target', ...) 호출하면 다시 IK 모드로 전환되며 redirect.\n this.set('target', undefined)\n ro.moveJointsTo(ro.getHomeJoints())\n await waitForTcpReached(this, timeoutMs)\n }\n\n /**\n * pick → place → goHome 시퀀스. 마지막에 home pose 복귀가 robot-arm 의\n * pickAndPlace 표준 동작. (Mover mixin 의 default 는 pick + place 만)\n */\n override async pickAndPlace(\n carrier: Component,\n holder: Component,\n options: MoveOptions = {}\n ): Promise<void> {\n await this.pick(carrier, options)\n await this.place(carrier, holder, options)\n await this.goHome(options)\n }\n\n /**\n * Resolve a TCP position in this arm's chain-local frame.\n *\n * For a CarrierHolder (has `attachPointFor`), uses the holder's own\n * attach frame as the base — that's the canonical \"where carriers\n * sit on me\" point (top of Spot's pad, gripper TCP for another arm,\n * etc.). For a plain carrier, uses its world center.\n *\n * `worldYOffset` is added to the resolved world Y before projecting\n * back to chain-local — used by pickAndPlace to lift the TCP above\n * the target (approach waypoints) and to land it on the carrier's\n * top face rather than its volumetric center.\n */\n private _targetFor(\n component: Component,\n worldYOffset = 0,\n yaw?: number\n ): { x: number; y: number; z: number; yaw?: number } {\n const ro3d = this._realObject\n\n let baseWp: THREE.Vector3 | undefined\n // Prefer holder's attach frame when available.\n const attachPointFor = (component as any).attachPointFor\n if (typeof attachPointFor === 'function') {\n const point = attachPointFor.call(component, this)\n if (point?.attach) {\n point.attach.updateWorldMatrix?.(true, false)\n baseWp = point.attach.getWorldPosition?.(new THREE.Vector3())\n }\n }\n if (!baseWp) {\n const obj = (component as any)._realObject?.object3d\n if (obj) {\n obj.updateWorldMatrix(true, false)\n baseWp = obj.getWorldPosition(new THREE.Vector3())\n }\n }\n if (!ro3d || !baseWp) {\n // Final fallback: 2D bounds center — only before 3D builds.\n const c = component.center\n return { x: c.x, y: worldYOffset, z: c.y, yaw }\n }\n const local = ro3d.worldToChainLocal(baseWp.x, baseWp.y + worldYOffset, baseWp.z)\n return { x: local.x, y: local.y, z: local.z, yaw }\n }\n\n /**\n * Extract a component's world yaw (rotation around world +Y) from its\n * 3D object's world matrix. Returns 0 if the object isn't built yet.\n * Used by `pickAndPlace` so the gripper can match the carrier's /\n * placeHolder's current orientation — preventing a yaw snap at the\n * moment of reparent.\n */\n private _yawOf(component: Component): number {\n const obj = (component as any)._realObject?.object3d\n if (!obj) return 0\n obj.updateWorldMatrix(true, false)\n const q = new THREE.Quaternion()\n obj.getWorldQuaternion(q)\n const e = new THREE.Euler().setFromQuaternion(q, 'YXZ')\n return e.y\n }\n}\n\n/**\n * Resolve when the robot arm fires `tcp-reached`, reject on timeout.\n * The 3D side fires this event on smoothing completion (last joint\n * value within threshold of its target).\n */\nfunction waitForTcpReached(component: Component, timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n let timer: any\n const onReached = () => {\n clearTimeout(timer)\n component.off('tcp-reached', onReached)\n resolve()\n }\n timer = setTimeout(() => {\n component.off('tcp-reached', onReached)\n reject(new Error('TCP reach timeout'))\n }, timeoutMs)\n component.on('tcp-reached', onReached)\n })\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction numOr(v: unknown, dflt: number): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : dflt\n}\n\n/**\n * Resolve a component's 3D height. things-scene v10 carriers (Box, Pallet,\n * etc.) typically declare `static defaultDepth` rather than setting\n * `state.depth`, so reading state alone returns 0 — wrong for a\n * default-sized box. The framework resolves the actual value into\n * `_realObject.effectiveDepth`. Falls back to `state.depth` for\n * components built before their RealObject exists.\n */\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)?._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n return numOr((c as any)?.state?.depth, 0)\n}\n\nfunction pickColor(...candidates: unknown[]): string {\n for (const c of candidates) {\n if (typeof c === 'string' && c && c !== 'transparent') return c\n }\n return '#888'\n}\n"]}
@@ -1,4 +1,25 @@
1
1
  import { ComponentNature, Properties, Shape } from '@hatiolab/things-scene';
2
+ import type { State } from '@hatiolab/things-scene';
3
+ /** TactTimer 컴포넌트 state */
4
+ export interface TactTimerState extends State {
5
+ startTime?: string;
6
+ endTime?: string;
7
+ format?: string;
8
+ progressDirection?: 'increase' | 'decrease' | '';
9
+ maskColor?: string;
10
+ beforeDueProgressColor?: string;
11
+ overDueProgressColor?: string;
12
+ beforeDueFontColor?: string;
13
+ overDueFontColor?: string;
14
+ underThresholdColor?: string;
15
+ progressThreshold?: number;
16
+ round?: number;
17
+ autoStart?: boolean;
18
+ showProgress?: boolean;
19
+ showTimer?: boolean;
20
+ started?: boolean;
21
+ data?: number;
22
+ }
2
23
  declare const TactTimer_base: (new (...args: any[]) => {
3
24
  contains(x: number, y: number): boolean;
4
25
  get path(): {
@@ -158,7 +179,7 @@ declare const TactTimer_base: (new (...args: any[]) => {
158
179
  findAll(s: string | ((c: import("@hatiolab/things-scene").Component) => boolean), ...others: any[]): any[] | undefined;
159
180
  capture(x: number, y: number, except?: (c: import("@hatiolab/things-scene").Component) => boolean): any;
160
181
  findAnchor(name: string): any;
161
- isDescendible(container: import("@hatiolab/things-scene").Component): boolean;
182
+ isDescendible(container: import("@hatiolab/things-scene").Component | any): boolean;
162
183
  getContext(component?: unknown): any;
163
184
  get root(): import("@hatiolab/things-scene").Component;
164
185
  get rootModel(): import("@hatiolab/things-scene").Component;
@@ -202,9 +223,13 @@ declare const TactTimer_base: (new (...args: any[]) => {
202
223
  toLocal(x: number, y: number, top?: import("@hatiolab/things-scene").Component): import("@hatiolab/things-scene").POINT;
203
224
  toGlobal(x: number, y: number, top?: import("@hatiolab/things-scene").Component): import("@hatiolab/things-scene").POINT;
204
225
  toOther(x: number, y: number, target: import("@hatiolab/things-scene").Component): import("@hatiolab/things-scene").POINT;
226
+ on<K extends keyof import("@hatiolab/things-scene").ComponentEventMap>(name: K, callback: (...args: import("@hatiolab/things-scene").ComponentEventMap[K]) => void, context?: any): any;
205
227
  on(name: string | object, callback: Function, context?: any): any;
228
+ off<K extends keyof import("@hatiolab/things-scene").ComponentEventMap>(name: K, callback?: ((...args: import("@hatiolab/things-scene").ComponentEventMap[K]) => void) | undefined, context?: any): any;
206
229
  off(name?: string | object, callback?: Function, context?: any): any;
230
+ once<K extends keyof import("@hatiolab/things-scene").ComponentEventMap>(name: K, callback: (...args: import("@hatiolab/things-scene").ComponentEventMap[K]) => void, context?: any): any;
207
231
  once(name: string | object, callback: Function, context?: any): any;
232
+ trigger<K extends keyof import("@hatiolab/things-scene").ComponentEventMap>(name: K, ...args: import("@hatiolab/things-scene").ComponentEventMap[K]): any;
208
233
  trigger(name: string, ...args: any[]): any;
209
234
  delegate_on(delegator: any): any;
210
235
  delegate_off(delegator: any): any;
@@ -237,6 +262,7 @@ declare const TactTimer_base: (new (...args: any[]) => {
237
262
  set element(_v: HTMLElement | null): any;
238
263
  }) & typeof Shape;
239
264
  export default class TactTimer extends TactTimer_base {
265
+ get state(): TactTimerState;
240
266
  private _start;
241
267
  private _due;
242
268
  private imageElement?;
@@ -249,10 +275,10 @@ export default class TactTimer extends TactTimer_base {
249
275
  counting(): void;
250
276
  render(context: CanvasRenderingContext2D): void;
251
277
  postrender(context: CanvasRenderingContext2D): void;
252
- parseTime(timeString: string): Date | undefined;
278
+ parseTime(timeString: string | undefined): Date | undefined;
253
279
  get countdown(): number;
254
- get value(): any[];
255
- set value(v: any[]);
280
+ get value(): (string | undefined)[];
281
+ set value(v: (string | undefined)[]);
256
282
  get started(): any;
257
283
  set started(started: any);
258
284
  }
@@ -93,6 +93,9 @@ const NATURE = {
93
93
  help: 'scene/component/manufacturing/tact-timer'
94
94
  };
95
95
  let TactTimer = class TactTimer extends RectPath(Shape) {
96
+ get state() {
97
+ return super.state;
98
+ }
96
99
  _start = 0;
97
100
  _due = 0;
98
101
  imageElement;
@@ -1 +1 @@
1
- {"version":3,"file":"tact-timer.js","sourceRoot":"","sources":["../src/tact-timer.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentNature, Properties, RectPath, Shape, sceneComponent } from '@hatiolab/things-scene'\nimport format from './libs/format.js'\nimport { MASK } from './tact-timer-mask.js'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n {\n type: 'string',\n label: 'start-time',\n name: 'startTime',\n placeholder: 'YYYYMMDDhhmmss'\n },\n {\n type: 'string',\n label: 'end-time',\n name: 'endTime',\n placeholder: 'YYYYMMDDhhmmss'\n },\n {\n type: 'string',\n label: 'format',\n name: 'format',\n placeholder: 'hh:mm:ss'\n },\n {\n type: 'select',\n label: 'progress-direction',\n name: 'progressDirection',\n property: {\n options: ['', 'increase', 'decrease']\n }\n },\n {\n type: 'color',\n label: 'tact-timer-mask-color',\n name: 'maskColor'\n },\n {\n type: 'color',\n label: 'before-due-progress-color',\n name: 'beforeDueProgressColor'\n },\n {\n type: 'color',\n label: 'over-due-progress-color',\n name: 'overDueProgressColor'\n },\n {\n type: 'color',\n label: 'before-due-font-color',\n name: 'beforeDueFontColor'\n },\n {\n type: 'color',\n label: 'over-due-font-color',\n name: 'overDueFontColor'\n },\n {\n type: 'color',\n label: 'under-threshold-color',\n name: 'underThresholdColor'\n },\n {\n type: 'number',\n label: 'progress-threshold',\n name: 'progressThreshold',\n placeholder: '%'\n },\n {\n type: 'number',\n label: 'round',\n name: 'round'\n },\n {\n type: 'boolean',\n label: 'auto-start',\n name: 'autoStart'\n },\n {\n type: 'boolean',\n label: 'show-progress',\n name: 'showProgress'\n },\n {\n type: 'boolean',\n label: 'show-timer',\n name: 'showTimer'\n }\n ],\n help: 'scene/component/manufacturing/tact-timer'\n}\n\n@sceneComponent('tact-timer')\nexport default class TactTimer extends RectPath(Shape) {\n private _start: number = 0\n private _due: number = 0\n private imageElement?: HTMLImageElement\n\n get nature() {\n return NATURE\n }\n\n async ready() {\n await super.ready()\n if (!this.app.isViewMode) {\n return\n }\n\n const { autoStart, started } = this.state\n\n if (autoStart || started) {\n this.setState('started', true)\n\n this.start()\n }\n }\n\n start() {\n const { startTime, endTime, hidden } = this.state\n const start = this.parseTime(startTime)\n const end = this.parseTime(endTime)\n\n if (start && end && !hidden) {\n this._due = end.getTime()\n this._start = start.getTime()\n this.counting()\n }\n }\n\n stop() {\n this.started = false\n }\n\n onchange(after: Properties) {\n if ('startTime' in after || 'endTime' in after || 'hidden' in after) {\n this.start()\n }\n\n if ('maskColor' in after) {\n delete this.imageElement\n }\n }\n\n getImageElement(): HTMLImageElement | undefined {\n if (!this.imageElement) {\n const { maskColor = 'black' } = this.state\n\n this.imageElement = new Image()\n this.imageElement.src =\n 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(MASK.replace(/{{fillColor}}/g, maskColor))\n }\n\n return this.imageElement\n }\n\n counting() {\n const { hidden, started } = this.state\n if (this.disposed || hidden || !started) {\n return\n }\n\n requestAnimationFrame(() => {\n const { showTimer, beforeDueFontColor, overDueFontColor, fontColor } = this.state\n const countdown = this.countdown\n\n this.setState('fontColor', (this.countdown > 0 ? beforeDueFontColor : overDueFontColor) || fontColor)\n\n if (showTimer) {\n const text = format(Math.abs(countdown), this.getState('format'))\n this.text = text\n } else {\n this.text = ''\n }\n\n this.setState('data', this.countdown)\n\n setTimeout(() => {\n this.counting()\n }, 1000)\n })\n }\n\n render(context: CanvasRenderingContext2D) {\n var {\n top,\n left,\n height,\n width,\n round = 0,\n fontColor,\n maskColor,\n beforeDueFontColor,\n overDueFontColor,\n beforeDueProgressColor = 'transparent',\n overDueProgressColor = 'transparent',\n underThresholdColor = 'transparent',\n progressDirection = 'increase',\n progressThreshold = 0,\n showProgress\n } = this.state\n\n const increase = this.countdown > 0\n const totalDuration = (this._due - this._start) / 1000\n const underThreshold = this.countdown / totalDuration < progressThreshold / 100\n\n // progress의 색상\n context.beginPath()\n context.roundRect(left, top, width, height, round)\n context.clip()\n this.drawFill(context)\n\n // value의 색상\n context.beginPath()\n\n if (!showProgress) {\n return\n }\n\n var progress = Math.abs((this.countdown / totalDuration) * 100)\n\n if (!isNaN(progress)) {\n progress = width - (width * progress) / 100\n progress = Math.max(Math.min(progress, width), 0)\n\n if (progressDirection == 'increase') {\n context.rect(left, top, progress, height)\n } else {\n context.rect(left + progress, top, width - progress, height)\n }\n\n context.fillStyle = increase\n ? underThreshold\n ? underThresholdColor\n : beforeDueProgressColor\n : overDueProgressColor\n context.fill()\n\n context.beginPath()\n }\n\n const image = this.getImageElement()\n this.drawImage(context, image!, left - 2, top - 2, width + 4, height + 4)\n\n context.roundRect(left, top, width, height, round)\n\n this.setState('fontColor', (increase ? beforeDueFontColor : overDueFontColor) || fontColor)\n }\n\n postrender(context: CanvasRenderingContext2D) {\n this.drawStroke(context)\n this.drawText(context)\n }\n\n parseTime(timeString: string): Date | undefined {\n if (!timeString || timeString.length !== 14) {\n return undefined\n }\n const year = parseInt(timeString.slice(0, 4), 10)\n const month = parseInt(timeString.slice(4, 6), 10) - 1\n const day = parseInt(timeString.slice(6, 8), 10)\n const hour = parseInt(timeString.slice(8, 10), 10)\n const minute = parseInt(timeString.slice(10, 12), 10)\n const second = parseInt(timeString.slice(12, 14), 10)\n\n return new Date(year, month, day, hour, minute, second)\n }\n\n get countdown(): number {\n const due = this._due || 0\n const now = Date.now()\n\n return Math.round((due - now) / 1000)\n }\n\n get value() {\n const { startTime, endTime } = this.state\n return [startTime, endTime]\n }\n\n set value(v) {\n if (v instanceof Array) {\n const [startTime, endTime] = v\n this.setState({\n startTime,\n endTime\n })\n } else if (typeof v == 'object') {\n const { startTime, endTime } = v\n this.setState({\n startTime,\n endTime\n })\n } else if (typeof v == 'string') {\n const [startTime, endTime] = (v as string).split(/[-+/%$#_,]+/)\n this.setState({\n startTime,\n endTime\n })\n } else {\n this.setState({\n startTime: undefined,\n endTime: undefined\n })\n }\n }\n\n get started() {\n return this.getState('started')\n }\n\n set started(started) {\n if (this.started !== started) {\n this.setState('started', started)\n if (started) {\n this.start()\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"tact-timer.js","sourceRoot":"","sources":["../src/tact-timer.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentNature, Properties, RectPath, Shape, sceneComponent } from '@hatiolab/things-scene'\nimport type { State } from '@hatiolab/things-scene'\nimport format from './libs/format.js'\nimport { MASK } from './tact-timer-mask.js'\n\n/** TactTimer 컴포넌트 state */\nexport interface TactTimerState extends State {\n startTime?: string\n endTime?: string\n format?: string\n progressDirection?: 'increase' | 'decrease' | ''\n maskColor?: string\n beforeDueProgressColor?: string\n overDueProgressColor?: string\n beforeDueFontColor?: string\n overDueFontColor?: string\n underThresholdColor?: string\n progressThreshold?: number\n round?: number\n autoStart?: boolean\n showProgress?: boolean\n showTimer?: boolean\n started?: boolean\n data?: number\n}\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n {\n type: 'string',\n label: 'start-time',\n name: 'startTime',\n placeholder: 'YYYYMMDDhhmmss'\n },\n {\n type: 'string',\n label: 'end-time',\n name: 'endTime',\n placeholder: 'YYYYMMDDhhmmss'\n },\n {\n type: 'string',\n label: 'format',\n name: 'format',\n placeholder: 'hh:mm:ss'\n },\n {\n type: 'select',\n label: 'progress-direction',\n name: 'progressDirection',\n property: {\n options: ['', 'increase', 'decrease']\n }\n },\n {\n type: 'color',\n label: 'tact-timer-mask-color',\n name: 'maskColor'\n },\n {\n type: 'color',\n label: 'before-due-progress-color',\n name: 'beforeDueProgressColor'\n },\n {\n type: 'color',\n label: 'over-due-progress-color',\n name: 'overDueProgressColor'\n },\n {\n type: 'color',\n label: 'before-due-font-color',\n name: 'beforeDueFontColor'\n },\n {\n type: 'color',\n label: 'over-due-font-color',\n name: 'overDueFontColor'\n },\n {\n type: 'color',\n label: 'under-threshold-color',\n name: 'underThresholdColor'\n },\n {\n type: 'number',\n label: 'progress-threshold',\n name: 'progressThreshold',\n placeholder: '%'\n },\n {\n type: 'number',\n label: 'round',\n name: 'round'\n },\n {\n type: 'boolean',\n label: 'auto-start',\n name: 'autoStart'\n },\n {\n type: 'boolean',\n label: 'show-progress',\n name: 'showProgress'\n },\n {\n type: 'boolean',\n label: 'show-timer',\n name: 'showTimer'\n }\n ],\n help: 'scene/component/manufacturing/tact-timer'\n}\n\n@sceneComponent('tact-timer')\nexport default class TactTimer extends RectPath(Shape) {\n override get state(): TactTimerState {\n return super.state as TactTimerState\n }\n\n private _start: number = 0\n private _due: number = 0\n private imageElement?: HTMLImageElement\n\n get nature() {\n return NATURE\n }\n\n async ready() {\n await super.ready()\n if (!this.app.isViewMode) {\n return\n }\n\n const { autoStart, started } = this.state\n\n if (autoStart || started) {\n this.setState('started', true)\n\n this.start()\n }\n }\n\n start() {\n const { startTime, endTime, hidden } = this.state\n const start = this.parseTime(startTime)\n const end = this.parseTime(endTime)\n\n if (start && end && !hidden) {\n this._due = end.getTime()\n this._start = start.getTime()\n this.counting()\n }\n }\n\n stop() {\n this.started = false\n }\n\n onchange(after: Properties) {\n if ('startTime' in after || 'endTime' in after || 'hidden' in after) {\n this.start()\n }\n\n if ('maskColor' in after) {\n delete this.imageElement\n }\n }\n\n getImageElement(): HTMLImageElement | undefined {\n if (!this.imageElement) {\n const { maskColor = 'black' } = this.state\n\n this.imageElement = new Image()\n this.imageElement.src =\n 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(MASK.replace(/{{fillColor}}/g, maskColor))\n }\n\n return this.imageElement\n }\n\n counting() {\n const { hidden, started } = this.state\n if (this.disposed || hidden || !started) {\n return\n }\n\n requestAnimationFrame(() => {\n const { showTimer, beforeDueFontColor, overDueFontColor, fontColor } = this.state\n const countdown = this.countdown\n\n this.setState('fontColor', (this.countdown > 0 ? beforeDueFontColor : overDueFontColor) || fontColor)\n\n if (showTimer) {\n const text = format(Math.abs(countdown), this.getState('format'))\n this.text = text\n } else {\n this.text = ''\n }\n\n this.setState('data', this.countdown)\n\n setTimeout(() => {\n this.counting()\n }, 1000)\n })\n }\n\n render(context: CanvasRenderingContext2D) {\n var {\n top,\n left,\n height,\n width,\n round = 0,\n fontColor,\n maskColor,\n beforeDueFontColor,\n overDueFontColor,\n beforeDueProgressColor = 'transparent',\n overDueProgressColor = 'transparent',\n underThresholdColor = 'transparent',\n progressDirection = 'increase',\n progressThreshold = 0,\n showProgress\n } = this.state\n\n const increase = this.countdown > 0\n const totalDuration = (this._due - this._start) / 1000\n const underThreshold = this.countdown / totalDuration < progressThreshold / 100\n\n // progress의 색상\n context.beginPath()\n context.roundRect(left, top, width, height, round)\n context.clip()\n this.drawFill(context)\n\n // value의 색상\n context.beginPath()\n\n if (!showProgress) {\n return\n }\n\n var progress = Math.abs((this.countdown / totalDuration) * 100)\n\n if (!isNaN(progress)) {\n progress = width - (width * progress) / 100\n progress = Math.max(Math.min(progress, width), 0)\n\n if (progressDirection == 'increase') {\n context.rect(left, top, progress, height)\n } else {\n context.rect(left + progress, top, width - progress, height)\n }\n\n context.fillStyle = increase\n ? underThreshold\n ? underThresholdColor\n : beforeDueProgressColor\n : overDueProgressColor\n context.fill()\n\n context.beginPath()\n }\n\n const image = this.getImageElement()\n this.drawImage(context, image!, left - 2, top - 2, width + 4, height + 4)\n\n context.roundRect(left, top, width, height, round)\n\n this.setState('fontColor', (increase ? beforeDueFontColor : overDueFontColor) || fontColor)\n }\n\n postrender(context: CanvasRenderingContext2D) {\n this.drawStroke(context)\n this.drawText(context)\n }\n\n parseTime(timeString: string | undefined): Date | undefined {\n if (!timeString || timeString.length !== 14) {\n return undefined\n }\n const year = parseInt(timeString.slice(0, 4), 10)\n const month = parseInt(timeString.slice(4, 6), 10) - 1\n const day = parseInt(timeString.slice(6, 8), 10)\n const hour = parseInt(timeString.slice(8, 10), 10)\n const minute = parseInt(timeString.slice(10, 12), 10)\n const second = parseInt(timeString.slice(12, 14), 10)\n\n return new Date(year, month, day, hour, minute, second)\n }\n\n get countdown(): number {\n const due = this._due || 0\n const now = Date.now()\n\n return Math.round((due - now) / 1000)\n }\n\n get value() {\n const { startTime, endTime } = this.state\n return [startTime, endTime]\n }\n\n set value(v) {\n if (v instanceof Array) {\n const [startTime, endTime] = v\n this.setState({\n startTime,\n endTime\n })\n } else if (typeof v == 'object') {\n const { startTime, endTime } = v\n this.setState({\n startTime,\n endTime\n })\n } else if (typeof v == 'string') {\n const [startTime, endTime] = (v as string).split(/[-+/%$#_,]+/)\n this.setState({\n startTime,\n endTime\n })\n } else {\n this.setState({\n startTime: undefined,\n endTime: undefined\n })\n }\n }\n\n get started() {\n return this.getState('started')\n }\n\n set started(started) {\n if (this.started !== started) {\n this.setState('started', started)\n if (started) {\n this.start()\n }\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@operato/scene-manufacturing",
3
3
  "description": "Things scene components for manufacturing industry",
4
- "version": "10.0.0-beta.30",
4
+ "version": "10.0.0-beta.31",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "things-scene": true,
@@ -25,17 +25,19 @@
25
25
  "prepublishOnly": "tsc",
26
26
  "lint": "eslint src/ && prettier \"src/**/*.ts\" --check",
27
27
  "format": "eslint src/ --fix && prettier \"src/**/*.ts\" --write",
28
- "migration": "things-factory-migration"
28
+ "migration": "things-factory-migration",
29
+ "test": "mocha --require should --node-option import=tsx \"test/**/test-*.ts\""
29
30
  },
30
31
  "dependencies": {
31
32
  "@hatiolab/things-scene": "^10.0.0-beta.1",
32
- "@operato/scene-base": "^10.0.0-beta.30",
33
+ "@operato/scene-base": "^10.0.0-beta.31",
33
34
  "three": "^0.183.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@hatiolab/prettier-config": "^1.0.0",
37
38
  "@things-factory/builder": "^10.0.0-beta.1",
38
39
  "@things-factory/operato-board": "^10.0.0-beta.1",
40
+ "@types/mocha": "^10.0.0",
39
41
  "@types/three": "^0.183.0",
40
42
  "@typescript-eslint/eslint-plugin": "^8.0.0",
41
43
  "@typescript-eslint/parser": "^8.0.0",
@@ -45,8 +47,11 @@
45
47
  "eslint-config-prettier": "^10.0.1",
46
48
  "husky": "^8.0.3",
47
49
  "lint-staged": "^15.2.2",
50
+ "mocha": "^10.0.0",
48
51
  "prettier": "^3.2.5",
52
+ "should": "^13.0.0",
49
53
  "tslib": "^2.3.1",
54
+ "tsx": "^4.0.0",
50
55
  "typescript": "^5.0.4"
51
56
  },
52
57
  "prettier": "@hatiolab/prettier-config",
@@ -61,5 +66,5 @@
61
66
  "prettier --write"
62
67
  ]
63
68
  },
64
- "gitHead": "06b35b1726ec4f27ee76657ce341c6c6f3ba1b3a"
69
+ "gitHead": "fdafbd04fd083a43690be937230c7d96a3ee5da3"
65
70
  }