@operato/scene-manufacturing 10.0.0-beta.2 → 10.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -9
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/robot-arm-3d.d.ts +169 -0
- package/dist/robot-arm-3d.js +971 -0
- package/dist/robot-arm-3d.js.map +1 -0
- package/dist/robot-arm-ik.d.ts +115 -0
- package/dist/robot-arm-ik.js +313 -0
- package/dist/robot-arm-ik.js.map +1 -0
- package/dist/robot-arm-styles.d.ts +48 -0
- package/dist/robot-arm-styles.js +106 -0
- package/dist/robot-arm-styles.js.map +1 -0
- package/dist/robot-arm.d.ts +181 -0
- package/dist/robot-arm.js +544 -0
- package/dist/robot-arm.js.map +1 -0
- package/dist/templates/index.d.ts +28 -2
- package/dist/templates/index.js +2 -1
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/robot-arm.d.ts +28 -0
- package/dist/templates/robot-arm.js +31 -0
- package/dist/templates/robot-arm.js.map +1 -0
- package/dist/templates/tact-timer.js +1 -1
- package/dist/templates/tact-timer.js.map +1 -1
- package/package.json +6 -3
- package/translations/en.json +8 -1
- package/translations/ja.json +8 -1
- package/translations/ko.json +8 -1
- package/translations/ms.json +8 -1
- package/translations/zh.json +8 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robot-arm-ik.js","sourceRoot":"","sources":["../src/robot-arm-ik.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * CCDIK (Cyclic Coordinate Descent Inverse Kinematics) for an arbitrary\n * articulated chain.\n *\n * Why CCDIK over analytical IK or Jacobian methods:\n * - Generalizes to arbitrary chain length / axis combinations without\n * re-deriving closed-form solutions per geometry.\n * - Trivial to implement in ~120 lines, no matrix inversion.\n * - Visually pleasing convergence (each iteration nudges the closest\n * joint to the end-effector toward the target — naturally produces\n * \"elbow leads, wrist follows\" motion that mimics real arms).\n * - Adequate for animation use; not a replacement for high-precision\n * analytical IK in a real motion-planning context.\n *\n * Algorithm (one iteration):\n * For each joint i from end → base:\n * 1. tip = world position of end-effector under current joint angles\n * 2. pivot = world position of joint i\n * 3. v1 = (tip - pivot) — current direction\n * v2 = (target - pivot) — desired direction\n * 4. project v1 and v2 onto the plane normal to joint i's axis\n * 5. θ = signed angle between projections (around the axis)\n * 6. jointValues[i] += θ, clamp to range\n * Repeat until tip-target distance < threshold or maxIterations reached.\n *\n * The chain is fixed (no link insertion/removal during a solve), and the\n * solver mutates a copy of jointValues — caller decides whether to commit.\n */\n\nimport * as THREE from 'three'\n\nexport type JointAxis = 'x' | 'y' | 'z'\n\nexport interface ChainElement {\n /** 'revolute' (rotates) or 'prismatic' (slides). PoC supports revolute. */\n type: 'revolute' | 'prismatic'\n /** axis of rotation/sliding in the joint's local frame */\n axis: JointAxis\n /** length of the link that follows this joint, along local +Z */\n length: number\n /** [min, max] joint value, in radians for revolute / units for prismatic */\n range: [number, number]\n}\n\nconst _AXES: 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\n/**\n * Forward kinematics: given joint values, compute every joint's world\n * position + orientation. Index 0 = base, index N = end-effector frame\n * (where the gripper is mounted).\n *\n * Convention: each joint's local frame starts coincident with its parent's\n * end frame; the joint applies its rotation/translation, then the link\n * extends along local +Z by `length`.\n */\nexport function forwardKinematics(\n chain: ChainElement[],\n jointValues: number[],\n baseMatrix: THREE.Matrix4 = new THREE.Matrix4()\n): { positions: THREE.Vector3[]; quaternions: THREE.Quaternion[] } {\n const positions: THREE.Vector3[] = []\n const quaternions: THREE.Quaternion[] = []\n\n const m = baseMatrix.clone()\n const tmpQ = new THREE.Quaternion()\n const tmpT = new THREE.Vector3()\n const linkOffset = new THREE.Vector3()\n\n // Joint 0 sits at the base.\n positions.push(new THREE.Vector3().setFromMatrixPosition(m))\n quaternions.push(new THREE.Quaternion().setFromRotationMatrix(m))\n\n for (let i = 0; i < chain.length; i++) {\n const link = chain[i]\n const value = jointValues[i] ?? 0\n if (link.type === 'revolute') {\n tmpQ.setFromAxisAngle(_AXES[link.axis], value)\n const rotM = new THREE.Matrix4().makeRotationFromQuaternion(tmpQ)\n m.multiply(rotM)\n } else {\n // prismatic: slide along axis by `value` (PoC support — most common\n // in real manipulators is revolute, but keeping the door open).\n linkOffset.copy(_AXES[link.axis]).multiplyScalar(value)\n m.multiply(new THREE.Matrix4().makeTranslation(linkOffset.x, linkOffset.y, linkOffset.z))\n }\n // Then translate along +Z by link.length to reach the next joint frame.\n m.multiply(new THREE.Matrix4().makeTranslation(0, 0, link.length))\n\n tmpT.setFromMatrixPosition(m)\n positions.push(tmpT.clone())\n quaternions.push(new THREE.Quaternion().setFromRotationMatrix(m))\n }\n\n return { positions, quaternions }\n}\n\nexport interface SolveOptions {\n maxIterations?: number\n threshold?: number\n /** how aggressively each iteration nudges (0..1). 0.5 = damped, less jitter. */\n damping?: number\n}\n\n/**\n * Solve IK for `targetWorld` and return new joint values. Does not mutate\n * the input array.\n *\n * Returns `{ values, reached }`. `reached` is true if the end-effector\n * came within `threshold` of the target — false if the target is outside\n * reachable workspace or the solver gave up.\n */\nexport function solveCCDIK(\n chain: ChainElement[],\n jointValues: number[],\n targetWorld: THREE.Vector3,\n baseMatrix: THREE.Matrix4 = new THREE.Matrix4(),\n options: SolveOptions = {}\n): { values: number[]; reached: boolean } {\n const maxIterations = options.maxIterations ?? 12\n const threshold = options.threshold ?? 0.5\n const damping = options.damping ?? 0.7\n\n const values = jointValues.slice()\n // Pre-allocate scratch vectors to avoid per-iteration GC churn.\n const v1 = new THREE.Vector3()\n const v2 = new THREE.Vector3()\n const axisWorld = new THREE.Vector3()\n const cross = new THREE.Vector3()\n\n for (let iter = 0; iter < maxIterations; iter++) {\n const fk = forwardKinematics(chain, values, baseMatrix)\n const tip = fk.positions[fk.positions.length - 1]\n\n // Early out: already close enough.\n if (tip.distanceTo(targetWorld) < threshold) {\n return { values, reached: true }\n }\n\n // Walk joints from the one nearest the tip toward the base.\n for (let i = chain.length - 1; i >= 0; i--) {\n if (chain[i].type !== 'revolute') continue\n\n // Joint i's pivot = positions[i] (frame BEFORE applying joint i).\n // After applying joint i and link i, we get positions[i+1].\n const pivot = fk.positions[i]\n const tipNow = forwardKinematics(chain, values, baseMatrix).positions[chain.length]\n\n v1.subVectors(tipNow, pivot)\n v2.subVectors(targetWorld, pivot)\n\n if (v1.lengthSq() < 1e-6 || v2.lengthSq() < 1e-6) continue\n\n // Joint axis in world space at this joint frame.\n axisWorld.copy(_AXES[chain[i].axis]).applyQuaternion(fk.quaternions[i])\n axisWorld.normalize()\n\n // Project v1, v2 onto the plane perpendicular to the axis.\n const v1p = v1.clone().projectOnPlane(axisWorld)\n const v2p = v2.clone().projectOnPlane(axisWorld)\n if (v1p.lengthSq() < 1e-6 || v2p.lengthSq() < 1e-6) continue\n v1p.normalize()\n v2p.normalize()\n\n // Signed angle around `axisWorld` from v1p to v2p.\n let angle = Math.acos(THREE.MathUtils.clamp(v1p.dot(v2p), -1, 1))\n cross.crossVectors(v1p, v2p)\n if (cross.dot(axisWorld) < 0) angle = -angle\n\n angle *= damping\n values[i] = clamp(values[i] + angle, chain[i].range[0], chain[i].range[1])\n }\n }\n\n // Final check after exhausting iterations.\n const finalTip = forwardKinematics(chain, values, baseMatrix).positions[chain.length]\n return { values, reached: finalTip.distanceTo(targetWorld) < threshold }\n}\n\n/**\n * Cheap reachability estimate — sum of all link lengths. Doesn't account\n * for joint-range restrictions, so a bit optimistic; good enough for\n * \"show me a workspace sphere\" visualization.\n */\nexport function maxReach(chain: ChainElement[]): number {\n return chain.reduce((sum, c) => sum + (c.length || 0), 0)\n}\n\n/**\n * True if `chain` has the canonical 6-axis Z-Y-Y-Z-Y-Z structure.\n * Industrial / cobot presets match. This unlocks closed-form analytical\n * IK; other chain shapes fall back to CCDIK.\n */\nexport function isSixAxisZYYZYZ(chain: ChainElement[]): boolean {\n if (chain.length !== 6) return false\n const expected: JointAxis[] = ['z', 'y', 'y', 'z', 'y', 'z']\n for (let i = 0; i < 6; i++) {\n if (chain[i].type !== 'revolute') return false\n if (chain[i].axis !== expected[i]) return false\n }\n return true\n}\n\n/**\n * Pick the base-yaw angle that points the chain toward the target's\n * XY direction. Returns null if the target is on the Z axis (no XY\n * direction defined). Unwraps to the multiple-of-2π closest to\n * `currentYaw` (then clamps to range), so a small physical motion in\n * world space doesn't produce a giant joint swing across ±π.\n *\n * `range` and `currentYaw` are in RADIANS.\n */\nexport function resolveBaseYaw(\n target: { x: number; y: number },\n range: [number, number],\n currentYaw: number\n): number | null {\n const xy = Math.hypot(target.x, target.y)\n if (xy < 1e-3) return null\n const a = Math.atan2(target.y, target.x)\n const TAU = Math.PI * 2\n let best = a\n let bestDist = Math.abs(a - currentYaw)\n for (const k of [-2, -1, 1, 2]) {\n const candidate = a + k * TAU\n const d = Math.abs(candidate - currentYaw)\n if (d < bestDist) {\n best = candidate\n bestDist = d\n }\n }\n return clamp(best, range[0], range[1])\n}\n\n/**\n * Closed-form analytical IK for the canonical 6-axis Z-Y-Y-Z-Y-Z chain.\n *\n * Inputs and outputs are in RADIANS. Chain ranges are in DEGREES (the\n * editor's user-facing convention) — converted internally. Returns null\n * if the target is unreachable; caller should fall back to CCDIK.\n *\n * Strategy:\n * 1. Joint 0 = base yaw to face target's XY direction.\n * 2. Try strict descent (gripper straight down, α = π).\n * 3. If wrist would be beyond reach, relax α to the value closest to\n * π that puts the wrist on the reach boundary.\n * 4. 2-link IK (cosine law) on upper + lower for shoulder/elbow.\n * 5. Wrist pitch ψ4 = α - ψ1 - ψ2 to realize the chosen α.\n * 6. Joints 3, 5 (Z-axis wrist roll / tool roll) = 0.\n *\n * Joint values are clamped to chain ranges; if a clamp activates the\n * gripper won't be perfectly oriented, but the rest of the pose is\n * still natural — and the visual TCP will then deviate from the\n * commanded target by the clamp residual.\n */\nexport function analyticalIk6Axis(\n chain: ChainElement[],\n target: { x: number; y: number; z: number },\n currentJointsRad: number[],\n /**\n * Optional carrier/place-holder yaw (radians, around world +Y) at the\n * target. When provided, joint 5 (tool roll) is set so the gripper's\n * \"side\" axes align with the carrier's — preventing a visible rotation\n * snap when the carrier reparents to the gripper at pick / off the\n * gripper at place.\n *\n * Derivation: with cumulative pitch ψ1+ψ2+ψ4 = π, the end-frame's\n * world axes are determined by joint 0 (j0) and joint 5 (θ5):\n * end_X = (-cos(j0 - θ5), 0, sin(j0 - θ5))\n * Carriable's localRotation x:-π/2 makes carrier_world = TCP_world ∘ R_x(-π/2);\n * for carrier_world to land at the carrier's pre-reparent yaw γ, we\n * need TCP_world = R_y(γ) ∘ R_x(π/2), which gives:\n * end_X = (cos γ, 0, -sin γ)\n * Solving end_X equation vs. this target: j0 - θ5 = π + γ\n * → θ5 = j0 - π - γ\n * Wrapped to [-π, π] then clamped to chain[5].range.\n *\n * If omitted, joint 5 stays at 0 (no yaw alignment).\n */\n targetYaw?: number\n): number[] | null {\n if (!isSixAxisZYYZYZ(chain)) return null\n\n const DEG2RAD = Math.PI / 180\n const L0 = chain[0].length\n const upper = chain[1].length\n const lower = chain[2].length + chain[3].length\n const wristTail = chain[4].length + chain[5].length\n const reach = upper + lower\n\n const j0Range: [number, number] = [chain[0].range[0] * DEG2RAD, chain[0].range[1] * DEG2RAD]\n const j0 = resolveBaseYaw(target, j0Range, currentJointsRad[0] ?? 0)\n if (j0 === null) return null\n\n const T_H = Math.hypot(target.x, target.y)\n const T_V = target.z\n\n const tcpRelH = T_H\n const tcpRelV = T_V - L0\n const p2 = tcpRelH * tcpRelH + tcpRelV * tcpRelV\n const p = Math.sqrt(p2)\n\n // Try strict descent (α = π) first.\n let alpha = Math.PI\n let wRelH = T_H\n let wRelV = (T_V + wristTail) - L0\n let d2 = wRelH * wRelH + wRelV * wRelV\n\n if (d2 > reach * reach + 1) {\n // Relax: find α on reach boundary, closest to π.\n const rhs = (p2 + wristTail * wristTail - reach * reach) / (2 * wristTail)\n if (Math.abs(rhs) > p + 1e-3) return null\n const beta = Math.atan2(tcpRelH, tcpRelV)\n const offset = Math.acos(clamp(rhs / p, -1, 1))\n const alphaA = beta + offset\n const alphaB = beta - offset\n const wrap = (a: number) => {\n let x = a\n while (x > Math.PI) x -= 2 * Math.PI\n while (x < -Math.PI) x += 2 * Math.PI\n return x\n }\n const distA = Math.abs(wrap(alphaA - Math.PI))\n const distB = Math.abs(wrap(alphaB - Math.PI))\n alpha = distA <= distB ? alphaA : alphaB\n\n wRelH = T_H - wristTail * Math.sin(alpha)\n wRelV = T_V - wristTail * Math.cos(alpha) - L0\n d2 = wRelH * wRelH + wRelV * wRelV\n if (d2 > reach * reach + 1) return null\n }\n\n let cosPsi2 = (d2 - upper * upper - lower * lower) / (2 * upper * lower)\n cosPsi2 = clamp(cosPsi2, -1, 1)\n const psi2 = Math.acos(cosPsi2)\n const psi1 =\n Math.atan2(wRelH, wRelV) -\n Math.atan2(lower * Math.sin(psi2), upper + lower * Math.cos(psi2))\n const psi4 = alpha - psi1 - psi2\n\n const radRanges = chain.map(c => [c.range[0] * DEG2RAD, c.range[1] * DEG2RAD] as [number, number])\n\n // Joint 5 (tool roll) — align gripper's \"side\" with the carrier's\n // current world yaw, so reparenting at pick / release at place doesn't\n // visibly snap the carrier's orientation.\n let psi5 = 0\n if (typeof targetYaw === 'number' && Number.isFinite(targetYaw)) {\n let v = j0 - Math.PI - targetYaw\n while (v > Math.PI) v -= 2 * Math.PI\n while (v < -Math.PI) v += 2 * Math.PI\n psi5 = v\n }\n\n return [\n clamp(j0, radRanges[0][0], radRanges[0][1]),\n clamp(psi1, radRanges[1][0], radRanges[1][1]),\n clamp(psi2, radRanges[2][0], radRanges[2][1]),\n 0,\n clamp(psi4, radRanges[4][0], radRanges[4][1]),\n clamp(psi5, radRanges[5][0], radRanges[5][1])\n ]\n}\n\nfunction clamp(v: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, v))\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ChainElement } from './robot-arm-ik.js';
|
|
2
|
+
export type LinkShape = 'cylinder' | 'tapered' | 'box' | 'tube' | 'gltf';
|
|
3
|
+
export type JointHousing = 'disk' | 'sphere' | 'knuckle' | 'none';
|
|
4
|
+
export type StyleName = 'industrial' | 'cobot' | 'scara' | 'minimal';
|
|
5
|
+
export type GripperType = 'parallel' | 'suction' | 'magnetic' | 'three-finger' | 'none';
|
|
6
|
+
/**
|
|
7
|
+
* Color slot in a style. Accepts hex int (`0xeaeaea`) or any THREE color
|
|
8
|
+
* string ('#fff' / 'rgb(...)' / 'red'). The 3D renderer feeds this directly
|
|
9
|
+
* to `MeshStandardMaterial.color` which accepts `THREE.ColorRepresentation`,
|
|
10
|
+
* so both forms work without conversion.
|
|
11
|
+
*/
|
|
12
|
+
export type StyleColor = number | string;
|
|
13
|
+
export interface RobotArmStyle {
|
|
14
|
+
linkShape: LinkShape;
|
|
15
|
+
jointHousing: JointHousing;
|
|
16
|
+
/** primary color (hex int or color string) */
|
|
17
|
+
color: StyleColor;
|
|
18
|
+
/** accent color for joint housings / details */
|
|
19
|
+
accentColor: StyleColor;
|
|
20
|
+
/** link cross-section radius / half-width (scene units) */
|
|
21
|
+
linkRadius: number;
|
|
22
|
+
}
|
|
23
|
+
export declare const STYLES: Record<StyleName, RobotArmStyle>;
|
|
24
|
+
export type ChainPresetName = '6-axis-industrial' | 'cobot-6-axis' | 'scara-4-axis' | 'pick-and-place-3-axis';
|
|
25
|
+
export declare const CHAIN_PRESETS: Record<ChainPresetName, ChainElement[]>;
|
|
26
|
+
export interface GripperConfig {
|
|
27
|
+
type: GripperType;
|
|
28
|
+
/** parallel / three-finger: open ↔ close 'state' (0..1). 0 = open, 1 = closed. */
|
|
29
|
+
state?: number;
|
|
30
|
+
/** parallel: distance fingers can travel. three-finger: same idea. */
|
|
31
|
+
stroke?: number;
|
|
32
|
+
/** parallel / three-finger: width of each finger. */
|
|
33
|
+
fingerWidth?: number;
|
|
34
|
+
/** suction / magnetic: cup or magnet diameter. */
|
|
35
|
+
diameter?: number;
|
|
36
|
+
/** color override; falls back to style.accentColor if absent. */
|
|
37
|
+
color?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Defaults intentionally omit `stroke` / `fingerWidth` / `diameter` so the
|
|
41
|
+
* 3D builder's linkRadius-proportional fallback kicks in. If we hard-coded
|
|
42
|
+
* those here, the spread-merge in the builder would overwrite the
|
|
43
|
+
* proportional defaults with these fixed numbers, and the gripper would
|
|
44
|
+
* always render the same size regardless of the arm's link thickness.
|
|
45
|
+
* Set `stroke` / `fingerWidth` / `diameter` via state.gripper only to
|
|
46
|
+
* override the proportional default.
|
|
47
|
+
*/
|
|
48
|
+
export declare const DEFAULT_GRIPPER: GripperConfig;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © HatioLab Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Style presets and chain templates for robot-arm.
|
|
5
|
+
*
|
|
6
|
+
* Two layers of presets:
|
|
7
|
+
* 1. `Style` — visual treatment (link shape, joint housing, colors).
|
|
8
|
+
* Same chain config can be rendered as a sleek cobot OR a heavy
|
|
9
|
+
* industrial arm just by picking a different style.
|
|
10
|
+
* 2. `ChainPreset` — common kinematic configurations (6-axis, SCARA, ...).
|
|
11
|
+
* Useful default chains; user can still override individual entries
|
|
12
|
+
* via `state.chain[i]`.
|
|
13
|
+
*/
|
|
14
|
+
export const STYLES = {
|
|
15
|
+
industrial: {
|
|
16
|
+
linkShape: 'tapered',
|
|
17
|
+
jointHousing: 'knuckle',
|
|
18
|
+
color: 0xe8c547,
|
|
19
|
+
accentColor: 0x2a2a2a,
|
|
20
|
+
linkRadius: 8
|
|
21
|
+
},
|
|
22
|
+
cobot: {
|
|
23
|
+
linkShape: 'cylinder',
|
|
24
|
+
jointHousing: 'disk',
|
|
25
|
+
color: 0xeaeaea,
|
|
26
|
+
accentColor: 0x4a8acc,
|
|
27
|
+
linkRadius: 6
|
|
28
|
+
},
|
|
29
|
+
scara: {
|
|
30
|
+
linkShape: 'box',
|
|
31
|
+
jointHousing: 'sphere',
|
|
32
|
+
color: 0x6c8aa6,
|
|
33
|
+
accentColor: 0x2a2a2a,
|
|
34
|
+
linkRadius: 7
|
|
35
|
+
},
|
|
36
|
+
minimal: {
|
|
37
|
+
linkShape: 'tube',
|
|
38
|
+
jointHousing: 'none',
|
|
39
|
+
color: 0x888888,
|
|
40
|
+
accentColor: 0x444444,
|
|
41
|
+
linkRadius: 3
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
// Revolute joint ranges expressed in DEGREES — what the user enters in
|
|
45
|
+
// the property panel. The 3D side converts to radians at the math
|
|
46
|
+
// boundary (forward kinematics, CCDIK, quaternion construction). This
|
|
47
|
+
// trade — store as user-facing units, convert internally — keeps the
|
|
48
|
+
// property panel intuitive without requiring a custom angle editor.
|
|
49
|
+
//
|
|
50
|
+
// Prismatic joint ranges are in scene length units (no conversion).
|
|
51
|
+
const FULL = [-180, 180];
|
|
52
|
+
const HALF = [-90, 90];
|
|
53
|
+
export const CHAIN_PRESETS = {
|
|
54
|
+
// Classic industrial 6-DOF: yaw → shoulder → elbow → wrist (3 axes).
|
|
55
|
+
'6-axis-industrial': [
|
|
56
|
+
{ type: 'revolute', axis: 'z', length: 30, range: FULL }, // base yaw
|
|
57
|
+
{ type: 'revolute', axis: 'y', length: 60, range: [-150, 150] }, // shoulder
|
|
58
|
+
{ type: 'revolute', axis: 'y', length: 50, range: [-150, 150] }, // elbow
|
|
59
|
+
{ type: 'revolute', axis: 'z', length: 20, range: FULL }, // wrist roll
|
|
60
|
+
// Wrist pitch needs wide range so the gripper can curl around to
|
|
61
|
+
// point straight DOWN at low targets — ψ1+ψ2+ψ4 cumulative reaches
|
|
62
|
+
// π for descent. With small ψ1+ψ2 (typical for upper-arm-led pose)
|
|
63
|
+
// ψ4 must be 150°+, well beyond the old HALF (±90°) limit. A clamp
|
|
64
|
+
// there silently shifts the actual TCP off-target — IK "converges"
|
|
65
|
+
// to a pose the arm physically can't realize as the requested point.
|
|
66
|
+
{ type: 'revolute', axis: 'y', length: 18, range: FULL }, // wrist pitch
|
|
67
|
+
{ type: 'revolute', axis: 'z', length: 10, range: FULL } // tool roll
|
|
68
|
+
],
|
|
69
|
+
// Cobot — same kinematic class but typically more reach + softer ranges.
|
|
70
|
+
'cobot-6-axis': [
|
|
71
|
+
{ type: 'revolute', axis: 'z', length: 25, range: FULL },
|
|
72
|
+
{ type: 'revolute', axis: 'y', length: 80, range: [-170, 170] },
|
|
73
|
+
{ type: 'revolute', axis: 'y', length: 70, range: [-170, 170] },
|
|
74
|
+
{ type: 'revolute', axis: 'z', length: 15, range: FULL },
|
|
75
|
+
{ type: 'revolute', axis: 'y', length: 15, range: FULL }, // wrist pitch
|
|
76
|
+
{ type: 'revolute', axis: 'z', length: 10, range: FULL }
|
|
77
|
+
],
|
|
78
|
+
// SCARA: 2 revolute (parallel axes) + 1 prismatic (Z) + 1 revolute (tool yaw).
|
|
79
|
+
'scara-4-axis': [
|
|
80
|
+
{ type: 'revolute', axis: 'z', length: 20, range: [-130, 130] },
|
|
81
|
+
{ type: 'revolute', axis: 'z', length: 60, range: [-150, 150] },
|
|
82
|
+
{ type: 'prismatic', axis: 'z', length: 50, range: [-30, 30] }, // length units
|
|
83
|
+
{ type: 'revolute', axis: 'z', length: 10, range: FULL }
|
|
84
|
+
],
|
|
85
|
+
// Compact 3-axis pick-and-place — base rotate + one elbow + tool drop.
|
|
86
|
+
'pick-and-place-3-axis': [
|
|
87
|
+
{ type: 'revolute', axis: 'z', length: 20, range: FULL },
|
|
88
|
+
{ type: 'revolute', axis: 'y', length: 50, range: HALF },
|
|
89
|
+
{ type: 'prismatic', axis: 'z', length: 30, range: [-25, 25] } // length units
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Defaults intentionally omit `stroke` / `fingerWidth` / `diameter` so the
|
|
94
|
+
* 3D builder's linkRadius-proportional fallback kicks in. If we hard-coded
|
|
95
|
+
* those here, the spread-merge in the builder would overwrite the
|
|
96
|
+
* proportional defaults with these fixed numbers, and the gripper would
|
|
97
|
+
* always render the same size regardless of the arm's link thickness.
|
|
98
|
+
* Set `stroke` / `fingerWidth` / `diameter` via state.gripper only to
|
|
99
|
+
* override the proportional default.
|
|
100
|
+
*/
|
|
101
|
+
export const DEFAULT_GRIPPER = {
|
|
102
|
+
type: 'parallel',
|
|
103
|
+
state: 0
|
|
104
|
+
// stroke / fingerWidth omitted — see JSDoc above.
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=robot-arm-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robot-arm-styles.js","sourceRoot":"","sources":["../src/robot-arm-styles.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Style presets and chain templates for robot-arm.\n *\n * Two layers of presets:\n * 1. `Style` — visual treatment (link shape, joint housing, colors).\n * Same chain config can be rendered as a sleek cobot OR a heavy\n * industrial arm just by picking a different style.\n * 2. `ChainPreset` — common kinematic configurations (6-axis, SCARA, ...).\n * Useful default chains; user can still override individual entries\n * via `state.chain[i]`.\n */\n\nimport type { ChainElement } from './robot-arm-ik.js'\n\nexport type LinkShape = 'cylinder' | 'tapered' | 'box' | 'tube' | 'gltf'\nexport type JointHousing = 'disk' | 'sphere' | 'knuckle' | 'none'\nexport type StyleName = 'industrial' | 'cobot' | 'scara' | 'minimal'\nexport type GripperType = 'parallel' | 'suction' | 'magnetic' | 'three-finger' | 'none'\n\n/**\n * Color slot in a style. Accepts hex int (`0xeaeaea`) or any THREE color\n * string ('#fff' / 'rgb(...)' / 'red'). The 3D renderer feeds this directly\n * to `MeshStandardMaterial.color` which accepts `THREE.ColorRepresentation`,\n * so both forms work without conversion.\n */\nexport type StyleColor = number | string\n\nexport interface RobotArmStyle {\n linkShape: LinkShape\n jointHousing: JointHousing\n /** primary color (hex int or color string) */\n color: StyleColor\n /** accent color for joint housings / details */\n accentColor: StyleColor\n /** link cross-section radius / half-width (scene units) */\n linkRadius: number\n}\n\nexport const STYLES: Record<StyleName, RobotArmStyle> = {\n industrial: {\n linkShape: 'tapered',\n jointHousing: 'knuckle',\n color: 0xe8c547,\n accentColor: 0x2a2a2a,\n linkRadius: 8\n },\n cobot: {\n linkShape: 'cylinder',\n jointHousing: 'disk',\n color: 0xeaeaea,\n accentColor: 0x4a8acc,\n linkRadius: 6\n },\n scara: {\n linkShape: 'box',\n jointHousing: 'sphere',\n color: 0x6c8aa6,\n accentColor: 0x2a2a2a,\n linkRadius: 7\n },\n minimal: {\n linkShape: 'tube',\n jointHousing: 'none',\n color: 0x888888,\n accentColor: 0x444444,\n linkRadius: 3\n }\n}\n\n// Revolute joint ranges expressed in DEGREES — what the user enters in\n// the property panel. The 3D side converts to radians at the math\n// boundary (forward kinematics, CCDIK, quaternion construction). This\n// trade — store as user-facing units, convert internally — keeps the\n// property panel intuitive without requiring a custom angle editor.\n//\n// Prismatic joint ranges are in scene length units (no conversion).\nconst FULL: [number, number] = [-180, 180]\nconst HALF: [number, number] = [-90, 90]\n\nexport type ChainPresetName = '6-axis-industrial' | 'cobot-6-axis' | 'scara-4-axis' | 'pick-and-place-3-axis'\n\nexport const CHAIN_PRESETS: Record<ChainPresetName, ChainElement[]> = {\n // Classic industrial 6-DOF: yaw → shoulder → elbow → wrist (3 axes).\n '6-axis-industrial': [\n { type: 'revolute', axis: 'z', length: 30, range: FULL }, // base yaw\n { type: 'revolute', axis: 'y', length: 60, range: [-150, 150] }, // shoulder\n { type: 'revolute', axis: 'y', length: 50, range: [-150, 150] }, // elbow\n { type: 'revolute', axis: 'z', length: 20, range: FULL }, // wrist roll\n // Wrist pitch needs wide range so the gripper can curl around to\n // point straight DOWN at low targets — ψ1+ψ2+ψ4 cumulative reaches\n // π for descent. With small ψ1+ψ2 (typical for upper-arm-led pose)\n // ψ4 must be 150°+, well beyond the old HALF (±90°) limit. A clamp\n // there silently shifts the actual TCP off-target — IK \"converges\"\n // to a pose the arm physically can't realize as the requested point.\n { type: 'revolute', axis: 'y', length: 18, range: FULL }, // wrist pitch\n { type: 'revolute', axis: 'z', length: 10, range: FULL } // tool roll\n ],\n // Cobot — same kinematic class but typically more reach + softer ranges.\n 'cobot-6-axis': [\n { type: 'revolute', axis: 'z', length: 25, range: FULL },\n { type: 'revolute', axis: 'y', length: 80, range: [-170, 170] },\n { type: 'revolute', axis: 'y', length: 70, range: [-170, 170] },\n { type: 'revolute', axis: 'z', length: 15, range: FULL },\n { type: 'revolute', axis: 'y', length: 15, range: FULL }, // wrist pitch\n { type: 'revolute', axis: 'z', length: 10, range: FULL }\n ],\n // SCARA: 2 revolute (parallel axes) + 1 prismatic (Z) + 1 revolute (tool yaw).\n 'scara-4-axis': [\n { type: 'revolute', axis: 'z', length: 20, range: [-130, 130] },\n { type: 'revolute', axis: 'z', length: 60, range: [-150, 150] },\n { type: 'prismatic', axis: 'z', length: 50, range: [-30, 30] }, // length units\n { type: 'revolute', axis: 'z', length: 10, range: FULL }\n ],\n // Compact 3-axis pick-and-place — base rotate + one elbow + tool drop.\n 'pick-and-place-3-axis': [\n { type: 'revolute', axis: 'z', length: 20, range: FULL },\n { type: 'revolute', axis: 'y', length: 50, range: HALF },\n { type: 'prismatic', axis: 'z', length: 30, range: [-25, 25] } // length units\n ]\n}\n\nexport interface GripperConfig {\n type: GripperType\n /** parallel / three-finger: open ↔ close 'state' (0..1). 0 = open, 1 = closed. */\n state?: number\n /** parallel: distance fingers can travel. three-finger: same idea. */\n stroke?: number\n /** parallel / three-finger: width of each finger. */\n fingerWidth?: number\n /** suction / magnetic: cup or magnet diameter. */\n diameter?: number\n /** color override; falls back to style.accentColor if absent. */\n color?: number\n}\n\n/**\n * Defaults intentionally omit `stroke` / `fingerWidth` / `diameter` so the\n * 3D builder's linkRadius-proportional fallback kicks in. If we hard-coded\n * those here, the spread-merge in the builder would overwrite the\n * proportional defaults with these fixed numbers, and the gripper would\n * always render the same size regardless of the arm's link thickness.\n * Set `stroke` / `fingerWidth` / `diameter` via state.gripper only to\n * override the proportional default.\n */\nexport const DEFAULT_GRIPPER: GripperConfig = {\n type: 'parallel',\n state: 0\n // stroke / fingerWidth omitted — see JSDoc above.\n}\n"]}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { Component, ComponentNature, RealObject } from '@hatiolab/things-scene';
|
|
3
|
+
import { type Alignment, type Heights, type LegendBinding, type MoveOptions, type PlacementArchetype } from '@operato/scene-base';
|
|
4
|
+
export type RobotArmStatus = 'idle' | 'moving' | 'gripping' | 'warn' | 'error';
|
|
5
|
+
declare const Base: typeof Component & {
|
|
6
|
+
new (...args: any[]): Component & {
|
|
7
|
+
isMover: boolean;
|
|
8
|
+
pick(carrier: Component, options?: MoveOptions): Promise<void>;
|
|
9
|
+
place(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>;
|
|
10
|
+
pickAndPlace(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export default class RobotArm extends Base {
|
|
14
|
+
static legends: Record<string, LegendBinding>;
|
|
15
|
+
/**
|
|
16
|
+
* Robot arms sit on the floor (or mount to a ceiling/wall — that's a
|
|
17
|
+
* v2 feature). Default depth = operation - floor like other floor-
|
|
18
|
+
* mounted equipment, so the chain reach scales with the configured
|
|
19
|
+
* facility height.
|
|
20
|
+
*/
|
|
21
|
+
static placement: PlacementArchetype;
|
|
22
|
+
static align: Alignment;
|
|
23
|
+
static defaultDepth: (h: Heights) => number;
|
|
24
|
+
/**
|
|
25
|
+
* Dynamic nature — appends one number property per joint in the active
|
|
26
|
+
* chain. Each property uses the joint's range as `min`/`max` so the
|
|
27
|
+
* property panel can render a constrained slider/spinner. The chain
|
|
28
|
+
* preset can change at runtime, and `get nature()` is re-evaluated
|
|
29
|
+
* whenever the property panel queries it, so the joint count stays in
|
|
30
|
+
* sync with the active preset.
|
|
31
|
+
*
|
|
32
|
+
* For revolute joints the value is in radians; for prismatic, scene units.
|
|
33
|
+
*/
|
|
34
|
+
get nature(): ComponentNature;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the active chain for property-panel introspection. Mirrors
|
|
37
|
+
* the resolution in robot-arm-3d.ts (state.chain wins, else preset,
|
|
38
|
+
* else default 6-axis-industrial). Kept simple — the 3D side does the
|
|
39
|
+
* same logic with depth-based scaling, but for property labeling we
|
|
40
|
+
* only need the structure (axis count + ranges), not absolute lengths.
|
|
41
|
+
*/
|
|
42
|
+
private get _activeChain();
|
|
43
|
+
get anchors(): never[];
|
|
44
|
+
/**
|
|
45
|
+
* 2D — base rectangle + a stylized arm silhouette pointing toward the
|
|
46
|
+
* top-right. Just enough to identify the component as a robot arm in
|
|
47
|
+
* plan view; the real visual lives in 3D.
|
|
48
|
+
*/
|
|
49
|
+
render(ctx: CanvasRenderingContext2D): void;
|
|
50
|
+
onchange(after: Record<string, unknown>, before: Record<string, unknown>): void;
|
|
51
|
+
buildRealObject(): RealObject | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* CarrierHolder hook — return the gripper TCP frame so any Carriable
|
|
54
|
+
* child (parcel/box/pallet/...) mounts onto the moving end-effector.
|
|
55
|
+
* IK rotation propagates to the carrier through Three.js scene-graph.
|
|
56
|
+
*
|
|
57
|
+
* Pose convention (real-world pick-and-place: gripper pointing toward
|
|
58
|
+
* the work, carrier hanging *beyond* the gripper tip):
|
|
59
|
+
*
|
|
60
|
+
* - Frame: TCP (gripper working point — between finger tips for
|
|
61
|
+
* jaws, contact face for suction/magnetic). Built by
|
|
62
|
+
* `RobotArm3D._buildGripper`. TCP's +Z = gripper-forward direction
|
|
63
|
+
* (away from the wrist).
|
|
64
|
+
*
|
|
65
|
+
* - Rotation: x:-π/2 — maps carrier's local +Y axis ("up" in the
|
|
66
|
+
* carrier's authored frame) to TCP's -Z direction. With the gripper
|
|
67
|
+
* pointing down (typical work pose), TCP +Z = world -Y (down), so
|
|
68
|
+
* TCP -Z = world +Y (up). Result: carrier's "up" stays world-up
|
|
69
|
+
* during transit, and the carrier's body extends from TCP origin
|
|
70
|
+
* in TCP +Z direction (down in world) — i.e. hanging BELOW the
|
|
71
|
+
* gripper, not buried inside it.
|
|
72
|
+
*
|
|
73
|
+
* - Position: z = +halfDepth — places the carrier's TOP face center
|
|
74
|
+
* at the TCP origin (where the fingers grip). Carrier's local +Y
|
|
75
|
+
* extent (top) = halfDepth, which after x:-π/2 rotation maps to
|
|
76
|
+
* TCP -halfDepth Z. Shifting carrier center to TCP +halfDepth Z
|
|
77
|
+
* puts that top point exactly at TCP origin. Carrier body then
|
|
78
|
+
* extends through TCP +Z, ending at TCP +depth (bottom face).
|
|
79
|
+
*
|
|
80
|
+
* Earlier (x:+π/2, z:-halfDepth) inverted the carrier's body direction
|
|
81
|
+
* — body extended back into the wrist, leaving the box visually inside
|
|
82
|
+
* the finger area. The current convention pushes the body OUT past the
|
|
83
|
+
* fingertips, where a real gripper would hold it.
|
|
84
|
+
*/
|
|
85
|
+
attachPointFor(carrier: Component): {
|
|
86
|
+
attach: THREE.Object3D<THREE.Object3DEventMap>;
|
|
87
|
+
localPosition: {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
z: number;
|
|
91
|
+
};
|
|
92
|
+
localRotation: {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
z: number;
|
|
96
|
+
};
|
|
97
|
+
} | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Pick: TCP descends vertically onto the carrier's top face, gripper
|
|
100
|
+
* closes, carrier becomes our child.
|
|
101
|
+
*
|
|
102
|
+
* 1. TCP → APPROACH above pick (carrier's xy, +clearance in world Y)
|
|
103
|
+
* 2. TCP → pick (descend straight down to carrier's top face)
|
|
104
|
+
* 3. close gripper + reparent(carrier → this)
|
|
105
|
+
*
|
|
106
|
+
* The approach waypoint exists so the FINAL leg is a clean vertical
|
|
107
|
+
* descent — the gripper enters the carrier from straight above, not a
|
|
108
|
+
* sideways sweep that could clip or grab at a wrong angle.
|
|
109
|
+
*
|
|
110
|
+
* Pose resolution: TCP lands on the CARRIER'S TOP FACE (carrier.world.y +
|
|
111
|
+
* carrier.depth/2). After grip, `attachPointFor`'s `localPosition.z =
|
|
112
|
+
* +halfDepth` keeps the carrier's top at TCP origin during transit —
|
|
113
|
+
* exact, no offset drift.
|
|
114
|
+
*
|
|
115
|
+
* Each waypoint includes the carrier's world yaw so IK can spin joint 5
|
|
116
|
+
* (tool roll) to align the gripper's "side" with the carrier's. Without
|
|
117
|
+
* it, reparent at pick instantly snaps the carrier to the gripper's
|
|
118
|
+
* axis, visibly twisting it 0° → up to 360° in one frame.
|
|
119
|
+
*
|
|
120
|
+
* @param options.approachClearance Vertical offset (world units)
|
|
121
|
+
* between approach and pick targets. Default 10.
|
|
122
|
+
* @param options.timeoutMs Per-segment IK timeout (default 15000ms).
|
|
123
|
+
* @param options.reparentDuration Animation duration for reparent (default 800ms).
|
|
124
|
+
*/
|
|
125
|
+
pick(carrier: Component, options?: MoveOptions): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Place: TCP descends vertically over the holder, gripper opens,
|
|
128
|
+
* carrier becomes the holder's child.
|
|
129
|
+
*
|
|
130
|
+
* 1. TCP → APPROACH above place (carrier's xy, +clearance)
|
|
131
|
+
* 2. TCP → place (descend straight down to drop point)
|
|
132
|
+
* 3. open gripper + reparent(carrier → holder)
|
|
133
|
+
*
|
|
134
|
+
* Pose resolution: TCP lands at where the carrier's top WILL BE after
|
|
135
|
+
* the drop, so the carrier lands with its bottom on the holder's attach
|
|
136
|
+
* surface. Computed as `holder.attachFrame.world.y + carrier.depth` (so
|
|
137
|
+
* yOffset = carrierDepth, not halfDepth like pick).
|
|
138
|
+
*
|
|
139
|
+
* @see pick — same option semantics.
|
|
140
|
+
*/
|
|
141
|
+
place(carrier: Component, holder: Component, options?: MoveOptions): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* `pickAndPlace` is inherited from the `Mover` mixin default — runs
|
|
144
|
+
* `pick(carrier)` then `place(carrier, holder)` sequentially. The
|
|
145
|
+
* decomposition is safe: the carrier's world position only matters
|
|
146
|
+
* during pick (carrier-relative waypoints), and after pick the carrier
|
|
147
|
+
* is the TCP's child (so re-querying it would chase its own tail —
|
|
148
|
+
* which we don't, since place uses holder-relative waypoints only).
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* await robotArm.pickAndPlace(box, spotB)
|
|
153
|
+
* await robotArm.pnp(parcel, palletA, { approachClearance: 30 })
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
/** Short alias for `pickAndPlace`. Same arguments, same behavior. */
|
|
157
|
+
pnp(carrier: Component, placeHolder: Component, options?: MoveOptions): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Resolve a TCP position in this arm's chain-local frame.
|
|
160
|
+
*
|
|
161
|
+
* For a CarrierHolder (has `attachPointFor`), uses the holder's own
|
|
162
|
+
* attach frame as the base — that's the canonical "where carriers
|
|
163
|
+
* sit on me" point (top of Spot's pad, gripper TCP for another arm,
|
|
164
|
+
* etc.). For a plain carrier, uses its world center.
|
|
165
|
+
*
|
|
166
|
+
* `worldYOffset` is added to the resolved world Y before projecting
|
|
167
|
+
* back to chain-local — used by pickAndPlace to lift the TCP above
|
|
168
|
+
* the target (approach waypoints) and to land it on the carrier's
|
|
169
|
+
* top face rather than its volumetric center.
|
|
170
|
+
*/
|
|
171
|
+
private _targetFor;
|
|
172
|
+
/**
|
|
173
|
+
* Extract a component's world yaw (rotation around world +Y) from its
|
|
174
|
+
* 3D object's world matrix. Returns 0 if the object isn't built yet.
|
|
175
|
+
* Used by `pickAndPlace` so the gripper can match the carrier's /
|
|
176
|
+
* placeHolder's current orientation — preventing a yaw snap at the
|
|
177
|
+
* moment of reparent.
|
|
178
|
+
*/
|
|
179
|
+
private _yawOf;
|
|
180
|
+
}
|
|
181
|
+
export {};
|