@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 CHANGED
@@ -1,13 +1,33 @@
1
- ## build
1
+ # @operato/scene-manufacturing
2
2
 
3
- `$ yarn build`
3
+ > Things scene components for manufacturing industry
4
4
 
5
- | type | filename | for | tested |
6
- | ---- | ------------------------------------------ | -------------- | ------ |
7
- | UMD | things-scene-scene-manufacturing.js | modern browser | O |
8
- | UMD | things-scene-scene-manufacturing-ie.js | ie 11 | O |
9
- | ESM | things-scene-scene-manufacturing.mjs | modern browser | O |
5
+ <!-- AUTOGEN_BEGIN: do not edit between markers (run scripts/regenerate-readmes.mjs to update) -->
10
6
 
11
- ## publish
7
+ ## Components
12
8
 
13
- `$ yarn publish`
9
+ - `TactTimer`
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ yarn add @operato/scene-manufacturing
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```ts
20
+ import { TactTimer } from '@operato/scene-manufacturing'
21
+ ```
22
+
23
+ ## Build
24
+
25
+ ```bash
26
+ yarn build
27
+ ```
28
+
29
+ Output: ESM module at `dist/index.js` (single bundle, no UMD/IE legacy).
30
+
31
+ _Version: 10.0.0-beta.2_
32
+
33
+ <!-- AUTOGEN_END -->
package/dist/index.d.ts CHANGED
@@ -1 +1,7 @@
1
1
  export { default as TactTimer } from './tact-timer.js';
2
+ export { default as RobotArm } from './robot-arm.js';
3
+ export { RobotArm3D } from './robot-arm-3d.js';
4
+ export type { ChainElement, JointAxis, SolveOptions } from './robot-arm-ik.js';
5
+ export { forwardKinematics, solveCCDIK, maxReach } from './robot-arm-ik.js';
6
+ export type { LinkShape, JointHousing, StyleName, GripperType, ChainPresetName, GripperConfig, RobotArmStyle } from './robot-arm-styles.js';
7
+ export { STYLES, CHAIN_PRESETS, DEFAULT_GRIPPER } from './robot-arm-styles.js';
package/dist/index.js CHANGED
@@ -1,2 +1,6 @@
1
1
  export { default as TactTimer } from './tact-timer.js';
2
+ export { default as RobotArm } from './robot-arm.js';
3
+ export { RobotArm3D } from './robot-arm-3d.js';
4
+ export { forwardKinematics, solveCCDIK, maxReach } from './robot-arm-ik.js';
5
+ export { STYLES, CHAIN_PRESETS, DEFAULT_GRIPPER } from './robot-arm-styles.js';
2
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAA","sourcesContent":["export { default as TactTimer } from './tact-timer.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAU3E,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA","sourcesContent":["export { default as TactTimer } from './tact-timer.js'\nexport { default as RobotArm } from './robot-arm.js'\nexport { RobotArm3D } from './robot-arm-3d.js'\nexport type { ChainElement, JointAxis, SolveOptions } from './robot-arm-ik.js'\nexport { forwardKinematics, solveCCDIK, maxReach } from './robot-arm-ik.js'\nexport type {\n LinkShape,\n JointHousing,\n StyleName,\n GripperType,\n ChainPresetName,\n GripperConfig,\n RobotArmStyle\n} from './robot-arm-styles.js'\nexport { STYLES, CHAIN_PRESETS, DEFAULT_GRIPPER } from './robot-arm-styles.js'\n"]}
@@ -0,0 +1,169 @@
1
+ import * as THREE from 'three';
2
+ import { RealObjectGroup } from '@hatiolab/things-scene';
3
+ export declare class RobotArm3D extends RealObjectGroup {
4
+ private _smoothing?;
5
+ private _animFrame?;
6
+ private _isAnimating;
7
+ private _chain;
8
+ private _jointFrames;
9
+ build(): void;
10
+ private _remountCarriers;
11
+ /**
12
+ * IK with a "point gripper downward" bias.
13
+ *
14
+ * CCDIK is position-only — it solves for joint values that put the
15
+ * end-effector at the target, without constraining the gripper's
16
+ * orientation. With no orientation constraint, valid solutions
17
+ * include twisted poses (gripper sideways / upside-down) — typical
18
+ * pick-and-place tasks then look broken: the box gets gripped at a
19
+ * wrong angle, or after release the carrier "launches" off because
20
+ * the gripper was facing some weird direction at the moment of
21
+ * release. The arm can also visibly "lock" near joint limits trying
22
+ * to satisfy a position-only target through a contorted path.
23
+ *
24
+ * Trick — augment the chain with a virtual rigid extension along the
25
+ * last frame's +Z, length L. When CCDIK puts this extended end at
26
+ * `target + L * (-Ẑ_chainLocal)` (i.e. the original target shifted
27
+ * downward by L in chain-local), the only way the chain can satisfy
28
+ * both placements simultaneously is by orienting the last frame's +Z
29
+ * to point in the chain-local -Z direction = world -Y direction =
30
+ * gripper pointing straight DOWN. Best-effort even when CCDIK can't
31
+ * fully converge — the solver pushes the chain in the right
32
+ * orientation, which matches what a real pick-and-place arm does.
33
+ */
34
+ private _gripperTcpZ;
35
+ private _solveIkDescent;
36
+ private _resolveChain;
37
+ /**
38
+ * Base pedestal height — small reservation at the bottom of `depth` so
39
+ * the chain doesn't start at z=0 (which would clip into the floor).
40
+ * About 12% of depth, clamped to a sane range.
41
+ */
42
+ private _baseHeight;
43
+ /**
44
+ * Color resolution priority (high → low):
45
+ * 1. `state.fillStyle` → main link color (overrides style preset)
46
+ * 2. `state.color` → legacy / explicit hex int
47
+ * 3. style preset color
48
+ * Same for accent: state.strokeStyle → state.accentColor → preset accent.
49
+ * This way the user can keep a SCARA's box-link shape but recolor it via
50
+ * the standard fillStyle property without dropping into custom presets.
51
+ */
52
+ private _resolveStyle;
53
+ /**
54
+ * Resolution priority for each joint i:
55
+ * 1. state.jointN (e.g. state.joint0, state.joint1, ...) — written
56
+ * by the property panel's per-joint number inputs (one row per
57
+ * joint, range-clamped slider).
58
+ * 2. state.joints[i] — array form, useful for programmatic batch set.
59
+ * 3. state.joints[i] — object form ({0: v, 1: v, ...}).
60
+ * 4. 0 — fallback.
61
+ * Final value is range-clamped against the joint's own limits.
62
+ */
63
+ private _resolveJoints;
64
+ private _jointSpeed;
65
+ /** Convert revolute joint values from degrees → radians. Prismatic
66
+ * values pass through untouched. */
67
+ private _toRadians;
68
+ /** Inverse of `_toRadians` — radians → degrees for revolute. */
69
+ private _fromRadians;
70
+ /**
71
+ * Build the chain as a tree of nested Object3Ds. Each link extends
72
+ * along its parent's +Z by `length` — applying the joint rotation BEFORE
73
+ * the translation. This way `rotateAround joint axis = rotate the
74
+ * downstream subtree`, which matches real arm kinematics.
75
+ */
76
+ private _buildArm;
77
+ /**
78
+ * Frame at the gripper TCP (Tool Center Point) — the working point of
79
+ * the gripper, NOT the wrist. For jaw grippers this is the mid-point
80
+ * between finger tips; for suction/magnetic it's the contact face.
81
+ * Carriers held by the arm parent here so they sit at the gripping
82
+ * interface, not buried inside the gripper meshes.
83
+ *
84
+ * Falls back to `_endFrame` (wrist) until `_buildGripper` has run.
85
+ */
86
+ getGripperFrame(): THREE.Object3D | undefined;
87
+ /**
88
+ * Convert a world-space point to the IK module's chain-local frame.
89
+ *
90
+ * Why this matters: CCDIK + forwardKinematics operate in `armRoot`'s
91
+ * local space (base joint at origin, +Z up — the IK math convention).
92
+ * `state.target` is interpreted in *that* frame. If a caller hands in
93
+ * a world position from another component (a parcel sitting somewhere
94
+ * in the scene), it must be projected through `armRoot`'s inverse
95
+ * world matrix first, otherwise the arm reaches toward "as if the
96
+ * world coords were base-relative" — a totally wrong direction once
97
+ * the robot itself isn't at the world origin.
98
+ *
99
+ * Returns the same `{x, y, z}` shape `state.target` accepts, which is
100
+ * already in chain-local space (no further conversion needed by
101
+ * pickAndPlace).
102
+ */
103
+ worldToChainLocal(worldX: number, worldY: number, worldZ: number): {
104
+ x: number;
105
+ y: number;
106
+ z: number;
107
+ };
108
+ private _armRoot?;
109
+ /**
110
+ * Apply a joint value to its scene-graph frame. `value` is in *user
111
+ * units* (degrees for revolute, scene units for prismatic) — convert
112
+ * to radians at the math boundary.
113
+ */
114
+ private _applyJointValue;
115
+ /** Cheap path: just refresh joint orientations without rebuilding the
116
+ * geometry tree. Used when only joint values changed. */
117
+ private _refreshJointPoses;
118
+ private _buildJointHousing;
119
+ private _buildLinkMesh;
120
+ /**
121
+ * Build the gripper meshes onto `_endFrame` and place a TCP frame at
122
+ * the gripper's working point (between the finger tips for jaw types,
123
+ * at the cup/disk distal face for surface types). Carriers held by the
124
+ * arm mount onto this TCP frame, NOT onto `_endFrame` — `_endFrame` is
125
+ * the wrist (chain end-of-link) and the gripper extends from it in +Z,
126
+ * so a carrier at `_endFrame` origin would visually overlap the gripper
127
+ * meshes (the fingers/cup would pierce through the box).
128
+ */
129
+ private _buildGripper;
130
+ private _tcpFrame?;
131
+ /**
132
+ * Each gripper sub-builder returns its TCP z-offset (in `_endFrame`'s
133
+ * local coordinates) — the point in space where a held carrier's grip
134
+ * face should land. The caller positions `_tcpFrame` at that z so
135
+ * carriers attach there directly.
136
+ */
137
+ private _buildParallelGripper;
138
+ private _buildThreeFingerGripper;
139
+ private _buildSuctionGripper;
140
+ private _buildMagneticGripper;
141
+ private _buildReachSphere;
142
+ /**
143
+ * Pedestal — sized from `state.width × state.height` (the 2D footprint).
144
+ * Cylindrical base whose radius fills ~90% of the smaller footprint
145
+ * dimension; a flared bottom (1.2× radius) gives the visual weight of
146
+ * a real industrial robot anchor.
147
+ */
148
+ private _buildBase;
149
+ private _startAnimation;
150
+ private _stopAnimation;
151
+ /**
152
+ * Re-run IK toward a new target without rebuilding the scene graph.
153
+ *
154
+ * Mirrors the IK block of `build()` but operates on the *existing*
155
+ * joint frames and meshes. Critically does NOT call `update()` /
156
+ * `clear()` — those tear down `this.object3d`'s children, which would
157
+ * also detach the gripper frame and any Carriable currently mounted
158
+ * onto it. A pickAndPlace operation would lose its held carrier the
159
+ * instant the place target is committed.
160
+ *
161
+ * Falls back to a full `update()` only when the cached chain hasn't
162
+ * been built yet (build pre-condition).
163
+ */
164
+ private _retargetIk;
165
+ updateDimension(): void;
166
+ onchange(after: Record<string, unknown>, before: Record<string, unknown>): void;
167
+ dispose(): void;
168
+ updateAlpha(): void;
169
+ }