@wandelbots/nova-js 3.1.0 → 3.2.0-pr.ci-simplify-build.137.87eeb8d

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.
Files changed (79) hide show
  1. package/dist/AutoReconnectingWebsocket-BI1ckzP8.d.ts +71 -0
  2. package/dist/AutoReconnectingWebsocket-BI1ckzP8.d.ts.map +1 -0
  3. package/dist/AutoReconnectingWebsocket-Cr7f9016.d.cts +71 -0
  4. package/dist/AutoReconnectingWebsocket-Cr7f9016.d.cts.map +1 -0
  5. package/dist/LoginWithAuth0-0g0wWRUC.js +217 -0
  6. package/dist/LoginWithAuth0-0g0wWRUC.js.map +1 -0
  7. package/dist/LoginWithAuth0-C82OCyDy.cjs +264 -0
  8. package/dist/LoginWithAuth0-C82OCyDy.cjs.map +1 -0
  9. package/dist/converters-DP2EIVv6.cjs +108 -0
  10. package/dist/converters-DP2EIVv6.cjs.map +1 -0
  11. package/dist/converters-DY6Lf7mb.js +66 -0
  12. package/dist/converters-DY6Lf7mb.js.map +1 -0
  13. package/dist/index.cjs +41 -386
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +70 -0
  16. package/dist/index.d.cts.map +1 -0
  17. package/dist/index.d.ts +69 -5
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +28 -52
  20. package/dist/index.js.map +1 -1
  21. package/dist/lib/v1/index.cjs +2146 -2917
  22. package/dist/lib/v1/index.cjs.map +1 -1
  23. package/dist/lib/v1/index.d.cts +397 -0
  24. package/dist/lib/v1/index.d.cts.map +1 -0
  25. package/dist/lib/v1/index.d.ts +395 -7
  26. package/dist/lib/v1/index.d.ts.map +1 -1
  27. package/dist/lib/v1/index.js +2127 -2623
  28. package/dist/lib/v1/index.js.map +1 -1
  29. package/dist/lib/v2/index.cjs +1356 -1472
  30. package/dist/lib/v2/index.cjs.map +1 -1
  31. package/dist/lib/v2/index.d.cts +115 -0
  32. package/dist/lib/v2/index.d.cts.map +1 -0
  33. package/dist/lib/v2/index.d.ts +113 -2
  34. package/dist/lib/v2/index.d.ts.map +1 -1
  35. package/dist/lib/v2/index.js +1346 -1189
  36. package/dist/lib/v2/index.js.map +1 -1
  37. package/package.json +14 -16
  38. package/src/LoginWithAuth0.ts +9 -9
  39. package/src/lib/v1/NovaCellAPIClient.ts +4 -2
  40. package/src/lib/v2/NovaCellAPIClient.ts +4 -2
  41. package/src/lib/v2/mock/MockNovaInstance.ts +9 -13
  42. package/dist/LoginWithAuth0.d.ts +0 -7
  43. package/dist/LoginWithAuth0.d.ts.map +0 -1
  44. package/dist/chunk-B2C22PTK.js +0 -53
  45. package/dist/chunk-B2C22PTK.js.map +0 -1
  46. package/dist/chunk-I3PUV6ZD.js +0 -286
  47. package/dist/chunk-I3PUV6ZD.js.map +0 -1
  48. package/dist/lib/AutoReconnectingWebsocket.d.ts +0 -43
  49. package/dist/lib/AutoReconnectingWebsocket.d.ts.map +0 -1
  50. package/dist/lib/availableStorage.d.ts +0 -15
  51. package/dist/lib/availableStorage.d.ts.map +0 -1
  52. package/dist/lib/converters.d.ts +0 -26
  53. package/dist/lib/converters.d.ts.map +0 -1
  54. package/dist/lib/errorHandling.d.ts +0 -15
  55. package/dist/lib/errorHandling.d.ts.map +0 -1
  56. package/dist/lib/v1/ConnectedMotionGroup.d.ts +0 -77
  57. package/dist/lib/v1/ConnectedMotionGroup.d.ts.map +0 -1
  58. package/dist/lib/v1/JoggerConnection.d.ts +0 -94
  59. package/dist/lib/v1/JoggerConnection.d.ts.map +0 -1
  60. package/dist/lib/v1/MotionStreamConnection.d.ts +0 -26
  61. package/dist/lib/v1/MotionStreamConnection.d.ts.map +0 -1
  62. package/dist/lib/v1/NovaCellAPIClient.d.ts +0 -68
  63. package/dist/lib/v1/NovaCellAPIClient.d.ts.map +0 -1
  64. package/dist/lib/v1/NovaClient.d.ts +0 -67
  65. package/dist/lib/v1/NovaClient.d.ts.map +0 -1
  66. package/dist/lib/v1/ProgramStateConnection.d.ts +0 -57
  67. package/dist/lib/v1/ProgramStateConnection.d.ts.map +0 -1
  68. package/dist/lib/v1/getLatestTrajectories.d.ts +0 -4
  69. package/dist/lib/v1/getLatestTrajectories.d.ts.map +0 -1
  70. package/dist/lib/v1/mock/MockNovaInstance.d.ts +0 -13
  71. package/dist/lib/v1/mock/MockNovaInstance.d.ts.map +0 -1
  72. package/dist/lib/v1/motionStateUpdate.d.ts +0 -4
  73. package/dist/lib/v1/motionStateUpdate.d.ts.map +0 -1
  74. package/dist/lib/v2/NovaCellAPIClient.d.ts +0 -62
  75. package/dist/lib/v2/NovaCellAPIClient.d.ts.map +0 -1
  76. package/dist/lib/v2/NovaClient.d.ts +0 -60
  77. package/dist/lib/v2/NovaClient.d.ts.map +0 -1
  78. package/dist/lib/v2/mock/MockNovaInstance.d.ts +0 -13
  79. package/dist/lib/v2/mock/MockNovaInstance.d.ts.map +0 -1
@@ -1,2653 +1,2157 @@
1
- import {
2
- isSameCoordinateSystem,
3
- tryParseJson
4
- } from "../../chunk-B2C22PTK.js";
5
- import {
6
- AutoReconnectingWebsocket,
7
- __async,
8
- __spreadProps,
9
- __spreadValues,
10
- availableStorage,
11
- loginWithAuth0
12
- } from "../../chunk-I3PUV6ZD.js";
13
-
14
- // src/lib/v1/index.ts
15
- export * from "@wandelbots/nova-api/v1";
16
-
17
- // src/lib/v1/ConnectedMotionGroup.ts
1
+ import { AutoReconnectingWebsocket, availableStorage, loginWithAuth0 } from "../../LoginWithAuth0-0g0wWRUC.js";
2
+ import { isSameCoordinateSystem, tryParseJson } from "../../converters-DY6Lf7mb.js";
3
+ import axios, { AxiosError, isAxiosError } from "axios";
4
+ import { ApplicationApi, CellApi, ControllerApi, ControllerIOsApi, CoordinateSystemsApi, DeviceConfigurationApi, LibraryProgramApi, LibraryProgramMetadataApi, LibraryRecipeApi, LibraryRecipeMetadataApi, MotionApi, MotionGroupApi, MotionGroupInfosApi, MotionGroupJoggingApi, MotionGroupKinematicApi, ProgramApi, ProgramValuesApi, StoreCollisionComponentsApi, StoreCollisionScenesApi, StoreObjectApi, SystemApi, VirtualRobotApi, VirtualRobotBehaviorApi, VirtualRobotModeApi, VirtualRobotSetupApi } from "@wandelbots/nova-api/v1";
18
5
  import { makeAutoObservable, runInAction } from "mobx";
19
6
  import * as THREE from "three";
7
+ import { Vector3 } from "three";
8
+ import { Vector3 as Vector3$1 } from "three/src/math/Vector3.js";
9
+ import urlJoin from "url-join";
10
+ import * as pathToRegexp from "path-to-regexp";
11
+
12
+ export * from "@wandelbots/nova-api/v1"
20
13
 
21
- // src/lib/v1/motionStateUpdate.ts
14
+ //#region src/lib/v1/motionStateUpdate.ts
22
15
  function jointValuesEqual(oldJointValues, newJointValues, changeDeltaThreshold) {
23
- if (newJointValues.length !== oldJointValues.length) {
24
- return true;
25
- }
26
- for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) {
27
- if (
28
- // biome-ignore lint/style/noNonNullAssertion: legacy code
29
- Math.abs(newJointValues[jointIndex] - oldJointValues[jointIndex]) > changeDeltaThreshold
30
- ) {
31
- return false;
32
- }
33
- }
34
- return true;
16
+ if (newJointValues.length !== oldJointValues.length) return true;
17
+ for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) if (Math.abs(newJointValues[jointIndex] - oldJointValues[jointIndex]) > changeDeltaThreshold) return false;
18
+ return true;
35
19
  }
36
20
  function tcpPoseEqual(oldTcp, newTcp, changeDeltaThreshold) {
37
- if (oldTcp === void 0 && newTcp || oldTcp && newTcp === void 0) {
38
- return false;
39
- }
40
- if (oldTcp === void 0 || newTcp === void 0) {
41
- return true;
42
- }
43
- let changedDelta = 0;
44
- changedDelta += Math.abs(oldTcp.orientation.x - newTcp.orientation.x);
45
- changedDelta += Math.abs(oldTcp.orientation.y - newTcp.orientation.y);
46
- changedDelta += Math.abs(oldTcp.orientation.z - newTcp.orientation.z);
47
- changedDelta += Math.abs(oldTcp.position.x - newTcp.position.x);
48
- changedDelta += Math.abs(oldTcp.position.y - newTcp.position.y);
49
- changedDelta += Math.abs(oldTcp.position.z - newTcp.position.z);
50
- if (changedDelta > changeDeltaThreshold) {
51
- return false;
52
- }
53
- return oldTcp.coordinate_system === newTcp.coordinate_system && oldTcp.tcp === newTcp.tcp;
21
+ if (oldTcp === void 0 && newTcp || oldTcp && newTcp === void 0) return false;
22
+ if (oldTcp === void 0 || newTcp === void 0) return true;
23
+ let changedDelta = 0;
24
+ changedDelta += Math.abs(oldTcp.orientation.x - newTcp.orientation.x);
25
+ changedDelta += Math.abs(oldTcp.orientation.y - newTcp.orientation.y);
26
+ changedDelta += Math.abs(oldTcp.orientation.z - newTcp.orientation.z);
27
+ changedDelta += Math.abs(oldTcp.position.x - newTcp.position.x);
28
+ changedDelta += Math.abs(oldTcp.position.y - newTcp.position.y);
29
+ changedDelta += Math.abs(oldTcp.position.z - newTcp.position.z);
30
+ if (changedDelta > changeDeltaThreshold) return false;
31
+ return oldTcp.coordinate_system === newTcp.coordinate_system && oldTcp.tcp === newTcp.tcp;
54
32
  }
55
33
 
56
- // src/lib/v1/ConnectedMotionGroup.ts
57
- var MOTION_DELTA_THRESHOLD = 1e-4;
58
- var ConnectedMotionGroup = class _ConnectedMotionGroup {
59
- constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup, mounting, initialControllerState, controllerStateSocket) {
60
- this.nova = nova;
61
- this.controller = controller;
62
- this.motionGroup = motionGroup;
63
- this.initialMotionState = initialMotionState;
64
- this.motionStateSocket = motionStateSocket;
65
- this.isVirtual = isVirtual;
66
- this.tcps = tcps;
67
- this.motionGroupSpecification = motionGroupSpecification;
68
- this.safetySetup = safetySetup;
69
- this.mounting = mounting;
70
- this.initialControllerState = initialControllerState;
71
- this.controllerStateSocket = controllerStateSocket;
72
- this.connectedJoggingCartesianSocket = null;
73
- this.connectedJoggingJointsSocket = null;
74
- // tmp
75
- this.joggingVelocity = 10;
76
- /**
77
- * Reflects activation state of the motion group / robot servos. The
78
- * movement controls in the UI should only be enabled in the "active" state
79
- */
80
- this.activationState = "inactive";
81
- this.rapidlyChangingMotionState = initialMotionState;
82
- this.controllerState = initialControllerState;
83
- controllerStateSocket.addEventListener("message", (event) => {
84
- var _a;
85
- const data = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result;
86
- if (!data) {
87
- return;
88
- }
89
- runInAction(() => {
90
- this.controllerState = data;
91
- });
92
- });
93
- motionStateSocket.addEventListener("message", (event) => {
94
- var _a;
95
- const motionStateResponse = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result;
96
- if (!motionStateResponse) {
97
- throw new Error(
98
- `Failed to get motion state for ${this.motionGroupId}: ${event.data}`
99
- );
100
- }
101
- if (!jointValuesEqual(
102
- this.rapidlyChangingMotionState.state.joint_position.joints,
103
- motionStateResponse.state.joint_position.joints,
104
- MOTION_DELTA_THRESHOLD
105
- )) {
106
- runInAction(() => {
107
- this.rapidlyChangingMotionState.state = motionStateResponse.state;
108
- });
109
- }
110
- if (!tcpPoseEqual(
111
- this.rapidlyChangingMotionState.tcp_pose,
112
- motionStateResponse.tcp_pose,
113
- MOTION_DELTA_THRESHOLD
114
- )) {
115
- runInAction(() => {
116
- this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
117
- });
118
- }
119
- });
120
- makeAutoObservable(this);
121
- }
122
- static connect(nova, motionGroupId, controllers) {
123
- return __async(this, null, function* () {
124
- var _a, _b;
125
- const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
126
- const controller = controllers.find((c) => c.controller === controllerId);
127
- const motionGroup = controller == null ? void 0 : controller.physical_motion_groups.find(
128
- (mg) => mg.motion_group === motionGroupId
129
- );
130
- if (!controller || !motionGroup) {
131
- throw new Error(
132
- `Controller ${controllerId} or motion group ${motionGroupId} not found`
133
- );
134
- }
135
- const motionStateSocket = nova.openReconnectingWebsocket(
136
- `/motion-groups/${motionGroupId}/state-stream`
137
- );
138
- const firstMessage = yield motionStateSocket.firstMessage();
139
- const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result;
140
- if (!initialMotionState) {
141
- throw new Error(
142
- `Unable to parse initial motion state message ${firstMessage.data}`
143
- );
144
- }
145
- console.log(
146
- `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:
147
- `,
148
- initialMotionState
149
- );
150
- const config = yield nova.api.controller.getRobotController(
151
- controller.controller
152
- );
153
- const isVirtual = config.configuration.kind === "VirtualController";
154
- const mounting = yield (() => __async(null, null, function* () {
155
- try {
156
- const mounting2 = yield nova.api.motionGroupInfos.getMounting(
157
- motionGroup.motion_group
158
- );
159
- return mounting2;
160
- } catch (err) {
161
- console.error(
162
- `Error fetching mounting for ${motionGroup.motion_group}`,
163
- err
164
- );
165
- return null;
166
- }
167
- }))();
168
- const controllerStateSocket = nova.openReconnectingWebsocket(
169
- `/controllers/${controller.controller}/state-stream?response_rate=1000`
170
- );
171
- const firstControllerMessage = yield controllerStateSocket.firstMessage();
172
- const initialControllerState = (_b = tryParseJson(firstControllerMessage.data)) == null ? void 0 : _b.result;
173
- if (!initialControllerState) {
174
- throw new Error(
175
- `Unable to parse initial controller state message ${firstControllerMessage.data}`
176
- );
177
- }
178
- console.log(
179
- `Connected controller state websocket to controller ${controller.controller}. Initial state:
180
- `,
181
- initialControllerState
182
- );
183
- const { tcps } = yield nova.api.motionGroupInfos.listTcps(motionGroupId);
184
- const motionGroupSpecification = yield nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId);
185
- const safetySetup = yield nova.api.motionGroupInfos.getSafetySetup(motionGroupId);
186
- return new _ConnectedMotionGroup(
187
- nova,
188
- controller,
189
- motionGroup,
190
- initialMotionState,
191
- motionStateSocket,
192
- isVirtual,
193
- // biome-ignore lint/style/noNonNullAssertion: legacy code
194
- tcps,
195
- motionGroupSpecification,
196
- safetySetup,
197
- mounting,
198
- initialControllerState,
199
- controllerStateSocket
200
- );
201
- });
202
- }
203
- get motionGroupId() {
204
- return this.motionGroup.motion_group;
205
- }
206
- get controllerId() {
207
- return this.controller.controller;
208
- }
209
- get modelFromController() {
210
- return this.motionGroup.model_from_controller;
211
- }
212
- get wandelscriptIdentifier() {
213
- const num = this.motionGroupId.split("@")[0];
214
- return `${this.controllerId.replaceAll("-", "_")}_${num}`;
215
- }
216
- /** Jogging velocity in radians for rotation and joint movement */
217
- get joggingVelocityRads() {
218
- return this.joggingVelocity * Math.PI / 180;
219
- }
220
- get joints() {
221
- return this.initialMotionState.state.joint_position.joints.map((_, i) => {
222
- return {
223
- index: i
224
- };
225
- });
226
- }
227
- get dhParameters() {
228
- return this.motionGroupSpecification.dh_parameters;
229
- }
230
- get safetyZones() {
231
- return this.safetySetup.safety_zones;
232
- }
233
- /** Gets the robot mounting position offset in 3D viz coordinates */
234
- get mountingPosition() {
235
- if (!this.mounting) {
236
- return [0, 0, 0];
237
- }
238
- return [
239
- this.mounting.pose.position.x / 1e3,
240
- this.mounting.pose.position.y / 1e3,
241
- this.mounting.pose.position.z / 1e3
242
- ];
243
- }
244
- /** Gets the robot mounting position rotation in 3D viz coordinates */
245
- get mountingQuaternion() {
246
- var _a, _b, _c, _d, _e, _f;
247
- const rotationVector = new THREE.Vector3(
248
- ((_b = (_a = this.mounting) == null ? void 0 : _a.pose.orientation) == null ? void 0 : _b.x) || 0,
249
- ((_d = (_c = this.mounting) == null ? void 0 : _c.pose.orientation) == null ? void 0 : _d.y) || 0,
250
- ((_f = (_e = this.mounting) == null ? void 0 : _e.pose.orientation) == null ? void 0 : _f.z) || 0
251
- );
252
- const magnitude = rotationVector.length();
253
- const axis = rotationVector.normalize();
254
- return new THREE.Quaternion().setFromAxisAngle(axis, magnitude);
255
- }
256
- /**
257
- * Whether the controller is currently in a safety state
258
- * corresponding to an emergency stop
259
- */
260
- get isEstopActive() {
261
- const estopStates = [
262
- "SAFETY_STATE_ROBOT_EMERGENCY_STOP",
263
- "SAFETY_STATE_DEVICE_EMERGENCY_STOP"
264
- ];
265
- return estopStates.includes(this.controllerState.safety_state);
266
- }
267
- /**
268
- * Whether the controller is in a safety state
269
- * that may be non-functional for robot pad purposes
270
- */
271
- get isMoveableSafetyState() {
272
- const goodSafetyStates = [
273
- "SAFETY_STATE_NORMAL",
274
- "SAFETY_STATE_REDUCED"
275
- ];
276
- return goodSafetyStates.includes(this.controllerState.safety_state);
277
- }
278
- /**
279
- * Whether the controller is in an operation mode that allows movement
280
- */
281
- get isMoveableOperationMode() {
282
- const goodOperationModes = [
283
- "OPERATION_MODE_AUTO",
284
- "OPERATION_MODE_MANUAL",
285
- "OPERATION_MODE_MANUAL_T1",
286
- "OPERATION_MODE_MANUAL_T2"
287
- ];
288
- return goodOperationModes.includes(this.controllerState.operation_mode);
289
- }
290
- /**
291
- * Whether the robot is currently active and can be moved, based on the
292
- * safety state, operation mode and servo toggle activation state.
293
- */
294
- get canBeMoved() {
295
- return this.isMoveableSafetyState && this.isMoveableOperationMode && this.activationState === "active";
296
- }
297
- deactivate() {
298
- return __async(this, null, function* () {
299
- if (this.activationState !== "active") {
300
- console.error("Tried to deactivate while already deactivating");
301
- return;
302
- }
303
- runInAction(() => {
304
- this.activationState = "deactivating";
305
- });
306
- try {
307
- yield this.nova.api.controller.setDefaultMode(
308
- this.controllerId,
309
- "MODE_MONITOR"
310
- );
311
- runInAction(() => {
312
- this.activationState = "inactive";
313
- });
314
- } catch (err) {
315
- runInAction(() => {
316
- this.activationState = "active";
317
- });
318
- throw err;
319
- }
320
- });
321
- }
322
- activate() {
323
- return __async(this, null, function* () {
324
- if (this.activationState !== "inactive") {
325
- console.error("Tried to activate while already activating");
326
- return;
327
- }
328
- runInAction(() => {
329
- this.activationState = "activating";
330
- });
331
- try {
332
- yield this.nova.api.controller.setDefaultMode(
333
- this.controllerId,
334
- "MODE_CONTROL"
335
- );
336
- runInAction(() => {
337
- this.activationState = "active";
338
- });
339
- } catch (err) {
340
- runInAction(() => {
341
- this.activationState = "inactive";
342
- });
343
- throw err;
344
- }
345
- });
346
- }
347
- toggleActivation() {
348
- if (this.activationState === "inactive") {
349
- this.activate();
350
- } else if (this.activationState === "active") {
351
- this.deactivate();
352
- }
353
- }
354
- dispose() {
355
- this.motionStateSocket.close();
356
- if (this.connectedJoggingCartesianSocket)
357
- this.connectedJoggingCartesianSocket.close();
358
- if (this.connectedJoggingJointsSocket)
359
- this.connectedJoggingJointsSocket.close();
360
- }
361
- setJoggingVelocity(velocity) {
362
- this.joggingVelocity = velocity;
363
- }
34
+ //#endregion
35
+ //#region src/lib/v1/ConnectedMotionGroup.ts
36
+ const MOTION_DELTA_THRESHOLD$1 = 1e-4;
37
+ /**
38
+ * Store representing the current state of a connected motion group.
39
+ */
40
+ var ConnectedMotionGroup = class ConnectedMotionGroup {
41
+ static async connect(nova, motionGroupId, controllers) {
42
+ const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
43
+ const controller = controllers.find((c) => c.controller === controllerId);
44
+ const motionGroup = controller?.physical_motion_groups.find((mg) => mg.motion_group === motionGroupId);
45
+ if (!controller || !motionGroup) throw new Error(`Controller ${controllerId} or motion group ${motionGroupId} not found`);
46
+ const motionStateSocket = nova.openReconnectingWebsocket(`/motion-groups/${motionGroupId}/state-stream`);
47
+ const firstMessage = await motionStateSocket.firstMessage();
48
+ const initialMotionState = tryParseJson(firstMessage.data)?.result;
49
+ if (!initialMotionState) throw new Error(`Unable to parse initial motion state message ${firstMessage.data}`);
50
+ console.log(`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\n `, initialMotionState);
51
+ const isVirtual = (await nova.api.controller.getRobotController(controller.controller)).configuration.kind === "VirtualController";
52
+ const mounting = await (async () => {
53
+ try {
54
+ return await nova.api.motionGroupInfos.getMounting(motionGroup.motion_group);
55
+ } catch (err) {
56
+ console.error(`Error fetching mounting for ${motionGroup.motion_group}`, err);
57
+ return null;
58
+ }
59
+ })();
60
+ const controllerStateSocket = nova.openReconnectingWebsocket(`/controllers/${controller.controller}/state-stream?response_rate=1000`);
61
+ const firstControllerMessage = await controllerStateSocket.firstMessage();
62
+ const initialControllerState = tryParseJson(firstControllerMessage.data)?.result;
63
+ if (!initialControllerState) throw new Error(`Unable to parse initial controller state message ${firstControllerMessage.data}`);
64
+ console.log(`Connected controller state websocket to controller ${controller.controller}. Initial state:\n `, initialControllerState);
65
+ const { tcps } = await nova.api.motionGroupInfos.listTcps(motionGroupId);
66
+ const motionGroupSpecification = await nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId);
67
+ const safetySetup = await nova.api.motionGroupInfos.getSafetySetup(motionGroupId);
68
+ return new ConnectedMotionGroup(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup, mounting, initialControllerState, controllerStateSocket);
69
+ }
70
+ constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup, mounting, initialControllerState, controllerStateSocket) {
71
+ this.nova = nova;
72
+ this.controller = controller;
73
+ this.motionGroup = motionGroup;
74
+ this.initialMotionState = initialMotionState;
75
+ this.motionStateSocket = motionStateSocket;
76
+ this.isVirtual = isVirtual;
77
+ this.tcps = tcps;
78
+ this.motionGroupSpecification = motionGroupSpecification;
79
+ this.safetySetup = safetySetup;
80
+ this.mounting = mounting;
81
+ this.initialControllerState = initialControllerState;
82
+ this.controllerStateSocket = controllerStateSocket;
83
+ this.connectedJoggingCartesianSocket = null;
84
+ this.connectedJoggingJointsSocket = null;
85
+ this.joggingVelocity = 10;
86
+ this.activationState = "inactive";
87
+ this.rapidlyChangingMotionState = initialMotionState;
88
+ this.controllerState = initialControllerState;
89
+ controllerStateSocket.addEventListener("message", (event) => {
90
+ const data = tryParseJson(event.data)?.result;
91
+ if (!data) return;
92
+ runInAction(() => {
93
+ this.controllerState = data;
94
+ });
95
+ });
96
+ motionStateSocket.addEventListener("message", (event) => {
97
+ const motionStateResponse = tryParseJson(event.data)?.result;
98
+ if (!motionStateResponse) throw new Error(`Failed to get motion state for ${this.motionGroupId}: ${event.data}`);
99
+ if (!jointValuesEqual(this.rapidlyChangingMotionState.state.joint_position.joints, motionStateResponse.state.joint_position.joints, MOTION_DELTA_THRESHOLD$1)) runInAction(() => {
100
+ this.rapidlyChangingMotionState.state = motionStateResponse.state;
101
+ });
102
+ if (!tcpPoseEqual(this.rapidlyChangingMotionState.tcp_pose, motionStateResponse.tcp_pose, MOTION_DELTA_THRESHOLD$1)) runInAction(() => {
103
+ this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
104
+ });
105
+ });
106
+ makeAutoObservable(this);
107
+ }
108
+ get motionGroupId() {
109
+ return this.motionGroup.motion_group;
110
+ }
111
+ get controllerId() {
112
+ return this.controller.controller;
113
+ }
114
+ get modelFromController() {
115
+ return this.motionGroup.model_from_controller;
116
+ }
117
+ get wandelscriptIdentifier() {
118
+ const num = this.motionGroupId.split("@")[0];
119
+ return `${this.controllerId.replaceAll("-", "_")}_${num}`;
120
+ }
121
+ /** Jogging velocity in radians for rotation and joint movement */
122
+ get joggingVelocityRads() {
123
+ return this.joggingVelocity * Math.PI / 180;
124
+ }
125
+ get joints() {
126
+ return this.initialMotionState.state.joint_position.joints.map((_, i) => {
127
+ return { index: i };
128
+ });
129
+ }
130
+ get dhParameters() {
131
+ return this.motionGroupSpecification.dh_parameters;
132
+ }
133
+ get safetyZones() {
134
+ return this.safetySetup.safety_zones;
135
+ }
136
+ /** Gets the robot mounting position offset in 3D viz coordinates */
137
+ get mountingPosition() {
138
+ if (!this.mounting) return [
139
+ 0,
140
+ 0,
141
+ 0
142
+ ];
143
+ return [
144
+ this.mounting.pose.position.x / 1e3,
145
+ this.mounting.pose.position.y / 1e3,
146
+ this.mounting.pose.position.z / 1e3
147
+ ];
148
+ }
149
+ /** Gets the robot mounting position rotation in 3D viz coordinates */
150
+ get mountingQuaternion() {
151
+ const rotationVector = new THREE.Vector3(this.mounting?.pose.orientation?.x || 0, this.mounting?.pose.orientation?.y || 0, this.mounting?.pose.orientation?.z || 0);
152
+ const magnitude = rotationVector.length();
153
+ const axis = rotationVector.normalize();
154
+ return new THREE.Quaternion().setFromAxisAngle(axis, magnitude);
155
+ }
156
+ /**
157
+ * Whether the controller is currently in a safety state
158
+ * corresponding to an emergency stop
159
+ */
160
+ get isEstopActive() {
161
+ return ["SAFETY_STATE_ROBOT_EMERGENCY_STOP", "SAFETY_STATE_DEVICE_EMERGENCY_STOP"].includes(this.controllerState.safety_state);
162
+ }
163
+ /**
164
+ * Whether the controller is in a safety state
165
+ * that may be non-functional for robot pad purposes
166
+ */
167
+ get isMoveableSafetyState() {
168
+ return ["SAFETY_STATE_NORMAL", "SAFETY_STATE_REDUCED"].includes(this.controllerState.safety_state);
169
+ }
170
+ /**
171
+ * Whether the controller is in an operation mode that allows movement
172
+ */
173
+ get isMoveableOperationMode() {
174
+ return [
175
+ "OPERATION_MODE_AUTO",
176
+ "OPERATION_MODE_MANUAL",
177
+ "OPERATION_MODE_MANUAL_T1",
178
+ "OPERATION_MODE_MANUAL_T2"
179
+ ].includes(this.controllerState.operation_mode);
180
+ }
181
+ /**
182
+ * Whether the robot is currently active and can be moved, based on the
183
+ * safety state, operation mode and servo toggle activation state.
184
+ */
185
+ get canBeMoved() {
186
+ return this.isMoveableSafetyState && this.isMoveableOperationMode && this.activationState === "active";
187
+ }
188
+ async deactivate() {
189
+ if (this.activationState !== "active") {
190
+ console.error("Tried to deactivate while already deactivating");
191
+ return;
192
+ }
193
+ runInAction(() => {
194
+ this.activationState = "deactivating";
195
+ });
196
+ try {
197
+ await this.nova.api.controller.setDefaultMode(this.controllerId, "MODE_MONITOR");
198
+ runInAction(() => {
199
+ this.activationState = "inactive";
200
+ });
201
+ } catch (err) {
202
+ runInAction(() => {
203
+ this.activationState = "active";
204
+ });
205
+ throw err;
206
+ }
207
+ }
208
+ async activate() {
209
+ if (this.activationState !== "inactive") {
210
+ console.error("Tried to activate while already activating");
211
+ return;
212
+ }
213
+ runInAction(() => {
214
+ this.activationState = "activating";
215
+ });
216
+ try {
217
+ await this.nova.api.controller.setDefaultMode(this.controllerId, "MODE_CONTROL");
218
+ runInAction(() => {
219
+ this.activationState = "active";
220
+ });
221
+ } catch (err) {
222
+ runInAction(() => {
223
+ this.activationState = "inactive";
224
+ });
225
+ throw err;
226
+ }
227
+ }
228
+ toggleActivation() {
229
+ if (this.activationState === "inactive") this.activate();
230
+ else if (this.activationState === "active") this.deactivate();
231
+ }
232
+ dispose() {
233
+ this.motionStateSocket.close();
234
+ if (this.connectedJoggingCartesianSocket) this.connectedJoggingCartesianSocket.close();
235
+ if (this.connectedJoggingJointsSocket) this.connectedJoggingJointsSocket.close();
236
+ }
237
+ setJoggingVelocity(velocity) {
238
+ this.joggingVelocity = velocity;
239
+ }
364
240
  };
365
241
 
366
- // src/lib/v1/getLatestTrajectories.ts
367
- var lastMotionIds = /* @__PURE__ */ new Set();
368
- function getLatestTrajectories(apiClient, sampleTime = 50, responsesCoordinateSystem) {
369
- return __async(this, null, function* () {
370
- const newTrajectories = [];
371
- try {
372
- const motions = yield apiClient.motion.listMotions();
373
- const currentMotionIds = new Set(motions.motions);
374
- const newMotionIds = Array.from(currentMotionIds).filter(
375
- (id) => !lastMotionIds.has(id)
376
- );
377
- for (const motionId of newMotionIds) {
378
- const trajectory = yield apiClient.motion.getMotionTrajectory(
379
- motionId,
380
- sampleTime,
381
- responsesCoordinateSystem
382
- );
383
- newTrajectories.push(trajectory);
384
- }
385
- lastMotionIds = currentMotionIds;
386
- } catch (error) {
387
- console.error("Failed to get latest trajectories:", error);
388
- }
389
- return newTrajectories;
390
- });
242
+ //#endregion
243
+ //#region src/lib/v1/getLatestTrajectories.ts
244
+ let lastMotionIds = /* @__PURE__ */ new Set();
245
+ async function getLatestTrajectories(apiClient, sampleTime = 50, responsesCoordinateSystem) {
246
+ const newTrajectories = [];
247
+ try {
248
+ const motions = await apiClient.motion.listMotions();
249
+ const currentMotionIds = new Set(motions.motions);
250
+ const newMotionIds = Array.from(currentMotionIds).filter((id) => !lastMotionIds.has(id));
251
+ for (const motionId of newMotionIds) {
252
+ const trajectory = await apiClient.motion.getMotionTrajectory(motionId, sampleTime, responsesCoordinateSystem);
253
+ newTrajectories.push(trajectory);
254
+ }
255
+ lastMotionIds = currentMotionIds;
256
+ } catch (error) {
257
+ console.error("Failed to get latest trajectories:", error);
258
+ }
259
+ return newTrajectories;
391
260
  }
392
261
 
393
- // src/lib/v1/JoggerConnection.ts
394
- import { Vector3 as Vector32 } from "three/src/math/Vector3.js";
395
- var JoggerConnection = class _JoggerConnection {
396
- constructor(motionStream, opts = {}) {
397
- this.motionStream = motionStream;
398
- this.opts = opts;
399
- // Currently a separate websocket is needed for each mode, pester API people
400
- // to merge these for simplicity
401
- this.cartesianWebsocket = null;
402
- this.jointWebsocket = null;
403
- this.cartesianJoggingOpts = {};
404
- }
405
- static open(_0, _1) {
406
- return __async(this, arguments, function* (nova, motionGroupId, opts = {}) {
407
- const motionStream = yield nova.connectMotionStream(motionGroupId);
408
- return new _JoggerConnection(motionStream, opts);
409
- });
410
- }
411
- get motionGroupId() {
412
- return this.motionStream.motionGroupId;
413
- }
414
- get nova() {
415
- return this.motionStream.nova;
416
- }
417
- get numJoints() {
418
- return this.motionStream.joints.length;
419
- }
420
- get activeJoggingMode() {
421
- if (this.cartesianWebsocket) return "cartesian";
422
- if (this.jointWebsocket) return "joint";
423
- return "increment";
424
- }
425
- get activeWebsocket() {
426
- return this.cartesianWebsocket || this.jointWebsocket;
427
- }
428
- stop() {
429
- return __async(this, null, function* () {
430
- if (this.cartesianWebsocket) {
431
- this.cartesianWebsocket.sendJson({
432
- motion_group: this.motionGroupId,
433
- position_direction: { x: 0, y: 0, z: 0 },
434
- rotation_direction: { x: 0, y: 0, z: 0 },
435
- position_velocity: 0,
436
- rotation_velocity: 0,
437
- tcp: this.cartesianJoggingOpts.tcpId,
438
- coordinate_system: this.cartesianJoggingOpts.coordSystemId
439
- });
440
- }
441
- if (this.jointWebsocket) {
442
- this.jointWebsocket.sendJson({
443
- motion_group: this.motionGroupId,
444
- joint_velocities: new Array(this.numJoints).fill(0)
445
- });
446
- }
447
- });
448
- }
449
- dispose() {
450
- if (this.cartesianWebsocket) {
451
- this.cartesianWebsocket.dispose();
452
- }
453
- if (this.jointWebsocket) {
454
- this.jointWebsocket.dispose();
455
- }
456
- }
457
- setJoggingMode(mode, cartesianJoggingOpts) {
458
- console.log("Setting jogging mode to", mode);
459
- if (cartesianJoggingOpts) {
460
- if (JSON.stringify(this.cartesianJoggingOpts) !== JSON.stringify(cartesianJoggingOpts)) {
461
- if (this.cartesianWebsocket) {
462
- this.cartesianWebsocket.dispose();
463
- this.cartesianWebsocket = null;
464
- }
465
- }
466
- this.cartesianJoggingOpts = cartesianJoggingOpts;
467
- }
468
- if (mode !== "cartesian" && this.cartesianWebsocket) {
469
- this.cartesianWebsocket.dispose();
470
- this.cartesianWebsocket = null;
471
- }
472
- if (mode !== "joint" && this.jointWebsocket) {
473
- this.jointWebsocket.dispose();
474
- this.jointWebsocket = null;
475
- }
476
- if (mode === "cartesian" && !this.cartesianWebsocket) {
477
- this.cartesianWebsocket = this.nova.openReconnectingWebsocket(
478
- `/motion-groups/move-tcp`
479
- );
480
- this.cartesianWebsocket.addEventListener(
481
- "message",
482
- (ev) => {
483
- const data = tryParseJson(ev.data);
484
- if (data && "error" in data) {
485
- if (this.opts.onError) {
486
- this.opts.onError(ev.data);
487
- } else {
488
- throw new Error(ev.data);
489
- }
490
- }
491
- }
492
- );
493
- }
494
- if (mode === "joint" && !this.jointWebsocket) {
495
- this.jointWebsocket = this.nova.openReconnectingWebsocket(
496
- `/motion-groups/move-joint`
497
- );
498
- this.jointWebsocket.addEventListener("message", (ev) => {
499
- const data = tryParseJson(ev.data);
500
- if (data && "error" in data) {
501
- if (this.opts.onError) {
502
- this.opts.onError(ev.data);
503
- } else {
504
- throw new Error(ev.data);
505
- }
506
- }
507
- });
508
- }
509
- }
510
- /**
511
- * Start rotation of a single robot joint at the specified velocity
512
- */
513
- startJointRotation(_0) {
514
- return __async(this, arguments, function* ({
515
- joint,
516
- direction,
517
- velocityRadsPerSec
518
- }) {
519
- if (!this.jointWebsocket) {
520
- throw new Error(
521
- "Joint jogging websocket not connected; call setJoggingMode first"
522
- );
523
- }
524
- const jointVelocities = new Array(this.numJoints).fill(0);
525
- jointVelocities[joint] = direction === "-" ? -velocityRadsPerSec : velocityRadsPerSec;
526
- this.jointWebsocket.sendJson({
527
- motion_group: this.motionGroupId,
528
- joint_velocities: jointVelocities
529
- });
530
- });
531
- }
532
- /**
533
- * Start the TCP moving along a specified axis at a given velocity
534
- */
535
- startTCPTranslation(_0) {
536
- return __async(this, arguments, function* ({
537
- axis,
538
- direction,
539
- velocityMmPerSec
540
- }) {
541
- if (!this.cartesianWebsocket) {
542
- throw new Error(
543
- "Cartesian jogging websocket not connected; call setJoggingMode first"
544
- );
545
- }
546
- const zeroVector = { x: 0, y: 0, z: 0 };
547
- const joggingVector = Object.assign({}, zeroVector);
548
- joggingVector[axis] = direction === "-" ? -1 : 1;
549
- this.cartesianWebsocket.sendJson({
550
- motion_group: this.motionGroupId,
551
- position_direction: joggingVector,
552
- rotation_direction: zeroVector,
553
- position_velocity: velocityMmPerSec,
554
- rotation_velocity: 0,
555
- tcp: this.cartesianJoggingOpts.tcpId,
556
- coordinate_system: this.cartesianJoggingOpts.coordSystemId
557
- });
558
- });
559
- }
560
- /**
561
- * Start the TCP rotating around a specified axis at a given velocity
562
- */
563
- startTCPRotation(_0) {
564
- return __async(this, arguments, function* ({
565
- axis,
566
- direction,
567
- velocityRadsPerSec
568
- }) {
569
- if (!this.cartesianWebsocket) {
570
- throw new Error(
571
- "Cartesian jogging websocket not connected; call setJoggingMode first"
572
- );
573
- }
574
- const zeroVector = { x: 0, y: 0, z: 0 };
575
- const joggingVector = Object.assign({}, zeroVector);
576
- joggingVector[axis] = direction === "-" ? -1 : 1;
577
- this.cartesianWebsocket.sendJson({
578
- motion_group: this.motionGroupId,
579
- position_direction: zeroVector,
580
- rotation_direction: joggingVector,
581
- position_velocity: 0,
582
- rotation_velocity: velocityRadsPerSec,
583
- tcp: this.cartesianJoggingOpts.tcpId,
584
- coordinate_system: this.cartesianJoggingOpts.coordSystemId
585
- });
586
- });
587
- }
588
- /**
589
- * Move the robot by a fixed distance in a single cartesian
590
- * axis, either rotating or translating relative to the TCP.
591
- * Promise resolves only after the motion has completed.
592
- */
593
- runIncrementalCartesianMotion(_0) {
594
- return __async(this, arguments, function* ({
595
- currentTcpPose,
596
- currentJoints,
597
- coordSystemId,
598
- velocityInRelevantUnits,
599
- axis,
600
- direction,
601
- motion
602
- }) {
603
- var _a;
604
- const commands = [];
605
- if (!isSameCoordinateSystem(currentTcpPose.coordinate_system, coordSystemId)) {
606
- throw new Error(
607
- `Current TCP pose coordinate system ${currentTcpPose.coordinate_system} does not match target coordinate system ${coordSystemId}`
608
- );
609
- }
610
- if (motion.type === "translate") {
611
- const targetTcpPosition = Object.assign({}, currentTcpPose.position);
612
- targetTcpPosition[axis] += motion.distanceMm * (direction === "-" ? -1 : 1);
613
- commands.push({
614
- settings: {
615
- limits_override: {
616
- tcp_velocity_limit: velocityInRelevantUnits
617
- }
618
- },
619
- line: {
620
- position: targetTcpPosition,
621
- orientation: currentTcpPose.orientation,
622
- coordinate_system: coordSystemId
623
- }
624
- });
625
- } else if (motion.type === "rotate") {
626
- const currentRotationVector = new Vector32(
627
- currentTcpPose.orientation.x,
628
- currentTcpPose.orientation.y,
629
- currentTcpPose.orientation.z
630
- );
631
- const currentRotationRad = currentRotationVector.length();
632
- const currentRotationDirection = currentRotationVector.clone().normalize();
633
- const differenceRotationRad = motion.distanceRads * (direction === "-" ? -1 : 1);
634
- const differenceRotationDirection = new Vector32(0, 0, 0);
635
- differenceRotationDirection[axis] = 1;
636
- const f1 = Math.cos(0.5 * differenceRotationRad) * Math.cos(0.5 * currentRotationRad);
637
- const f2 = Math.sin(0.5 * differenceRotationRad) * Math.sin(0.5 * currentRotationRad);
638
- const f3 = Math.sin(0.5 * differenceRotationRad) * Math.cos(0.5 * currentRotationRad);
639
- const f4 = Math.cos(0.5 * differenceRotationRad) * Math.sin(0.5 * currentRotationRad);
640
- const dotProduct = differenceRotationDirection.dot(
641
- currentRotationDirection
642
- );
643
- const crossProduct = differenceRotationDirection.clone().cross(currentRotationDirection);
644
- const newRotationRad = 2 * Math.acos(f1 - f2 * dotProduct);
645
- const f5 = newRotationRad / Math.sin(0.5 * newRotationRad);
646
- const targetTcpOrientation = new Vector32().addScaledVector(crossProduct, f2).addScaledVector(differenceRotationDirection, f3).addScaledVector(currentRotationDirection, f4).multiplyScalar(f5);
647
- commands.push({
648
- settings: {
649
- limits_override: {
650
- tcp_orientation_velocity_limit: velocityInRelevantUnits
651
- }
652
- },
653
- line: {
654
- position: currentTcpPose.position,
655
- orientation: targetTcpOrientation,
656
- coordinate_system: coordSystemId
657
- }
658
- });
659
- }
660
- const motionPlanRes = yield this.nova.api.motion.planMotion({
661
- motion_group: this.motionGroupId,
662
- start_joint_position: currentJoints,
663
- tcp: this.cartesianJoggingOpts.tcpId,
664
- commands
665
- });
666
- const plannedMotion = (_a = motionPlanRes.plan_successful_response) == null ? void 0 : _a.motion;
667
- if (!plannedMotion) {
668
- throw new Error(
669
- `Failed to plan jogging increment motion ${JSON.stringify(motionPlanRes)}`
670
- );
671
- }
672
- yield this.nova.api.motion.streamMoveForward(
673
- plannedMotion,
674
- 100,
675
- void 0,
676
- void 0,
677
- void 0,
678
- {
679
- // Might take a while at low velocity
680
- timeout: 1e3 * 60
681
- }
682
- );
683
- });
684
- }
685
- /**
686
- * Rotate a single robot joint by a fixed number of radians
687
- * Promise resolves only after the motion has completed.
688
- */
689
- runIncrementalJointRotation(_0) {
690
- return __async(this, arguments, function* ({
691
- joint,
692
- currentJoints,
693
- velocityRadsPerSec,
694
- direction,
695
- distanceRads
696
- }) {
697
- var _a;
698
- const targetJoints = [...currentJoints.joints];
699
- targetJoints[joint] += distanceRads * (direction === "-" ? -1 : 1);
700
- const jointVelocityLimits = new Array(
701
- currentJoints.joints.length
702
- ).fill(velocityRadsPerSec);
703
- const motionPlanRes = yield this.nova.api.motion.planMotion({
704
- motion_group: this.motionGroupId,
705
- start_joint_position: currentJoints,
706
- commands: [
707
- {
708
- settings: {
709
- limits_override: {
710
- joint_velocity_limits: {
711
- joints: jointVelocityLimits
712
- }
713
- }
714
- },
715
- joint_ptp: {
716
- joints: targetJoints
717
- }
718
- }
719
- ]
720
- });
721
- const plannedMotion = (_a = motionPlanRes.plan_successful_response) == null ? void 0 : _a.motion;
722
- if (!plannedMotion) {
723
- console.error("Failed to plan jogging increment motion", motionPlanRes);
724
- return;
725
- }
726
- yield this.nova.api.motion.streamMoveForward(
727
- plannedMotion,
728
- 100,
729
- void 0,
730
- void 0,
731
- void 0,
732
- {
733
- // Might take a while at low velocity
734
- timeout: 1e3 * 60
735
- }
736
- );
737
- });
738
- }
262
+ //#endregion
263
+ //#region src/lib/v1/JoggerConnection.ts
264
+ var JoggerConnection = class JoggerConnection {
265
+ static async open(nova, motionGroupId, opts = {}) {
266
+ const motionStream = await nova.connectMotionStream(motionGroupId);
267
+ return new JoggerConnection(motionStream, opts);
268
+ }
269
+ constructor(motionStream, opts = {}) {
270
+ this.motionStream = motionStream;
271
+ this.opts = opts;
272
+ this.cartesianWebsocket = null;
273
+ this.jointWebsocket = null;
274
+ this.cartesianJoggingOpts = {};
275
+ }
276
+ get motionGroupId() {
277
+ return this.motionStream.motionGroupId;
278
+ }
279
+ get nova() {
280
+ return this.motionStream.nova;
281
+ }
282
+ get numJoints() {
283
+ return this.motionStream.joints.length;
284
+ }
285
+ get activeJoggingMode() {
286
+ if (this.cartesianWebsocket) return "cartesian";
287
+ if (this.jointWebsocket) return "joint";
288
+ return "increment";
289
+ }
290
+ get activeWebsocket() {
291
+ return this.cartesianWebsocket || this.jointWebsocket;
292
+ }
293
+ async stop() {
294
+ if (this.cartesianWebsocket) this.cartesianWebsocket.sendJson({
295
+ motion_group: this.motionGroupId,
296
+ position_direction: {
297
+ x: 0,
298
+ y: 0,
299
+ z: 0
300
+ },
301
+ rotation_direction: {
302
+ x: 0,
303
+ y: 0,
304
+ z: 0
305
+ },
306
+ position_velocity: 0,
307
+ rotation_velocity: 0,
308
+ tcp: this.cartesianJoggingOpts.tcpId,
309
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
310
+ });
311
+ if (this.jointWebsocket) this.jointWebsocket.sendJson({
312
+ motion_group: this.motionGroupId,
313
+ joint_velocities: new Array(this.numJoints).fill(0)
314
+ });
315
+ }
316
+ dispose() {
317
+ if (this.cartesianWebsocket) this.cartesianWebsocket.dispose();
318
+ if (this.jointWebsocket) this.jointWebsocket.dispose();
319
+ }
320
+ setJoggingMode(mode, cartesianJoggingOpts) {
321
+ console.log("Setting jogging mode to", mode);
322
+ if (cartesianJoggingOpts) {
323
+ if (JSON.stringify(this.cartesianJoggingOpts) !== JSON.stringify(cartesianJoggingOpts)) {
324
+ if (this.cartesianWebsocket) {
325
+ this.cartesianWebsocket.dispose();
326
+ this.cartesianWebsocket = null;
327
+ }
328
+ }
329
+ this.cartesianJoggingOpts = cartesianJoggingOpts;
330
+ }
331
+ if (mode !== "cartesian" && this.cartesianWebsocket) {
332
+ this.cartesianWebsocket.dispose();
333
+ this.cartesianWebsocket = null;
334
+ }
335
+ if (mode !== "joint" && this.jointWebsocket) {
336
+ this.jointWebsocket.dispose();
337
+ this.jointWebsocket = null;
338
+ }
339
+ if (mode === "cartesian" && !this.cartesianWebsocket) {
340
+ this.cartesianWebsocket = this.nova.openReconnectingWebsocket(`/motion-groups/move-tcp`);
341
+ this.cartesianWebsocket.addEventListener("message", (ev) => {
342
+ const data = tryParseJson(ev.data);
343
+ if (data && "error" in data) if (this.opts.onError) this.opts.onError(ev.data);
344
+ else throw new Error(ev.data);
345
+ });
346
+ }
347
+ if (mode === "joint" && !this.jointWebsocket) {
348
+ this.jointWebsocket = this.nova.openReconnectingWebsocket(`/motion-groups/move-joint`);
349
+ this.jointWebsocket.addEventListener("message", (ev) => {
350
+ const data = tryParseJson(ev.data);
351
+ if (data && "error" in data) if (this.opts.onError) this.opts.onError(ev.data);
352
+ else throw new Error(ev.data);
353
+ });
354
+ }
355
+ }
356
+ /**
357
+ * Start rotation of a single robot joint at the specified velocity
358
+ */
359
+ async startJointRotation({ joint, direction, velocityRadsPerSec }) {
360
+ if (!this.jointWebsocket) throw new Error("Joint jogging websocket not connected; call setJoggingMode first");
361
+ const jointVelocities = new Array(this.numJoints).fill(0);
362
+ jointVelocities[joint] = direction === "-" ? -velocityRadsPerSec : velocityRadsPerSec;
363
+ this.jointWebsocket.sendJson({
364
+ motion_group: this.motionGroupId,
365
+ joint_velocities: jointVelocities
366
+ });
367
+ }
368
+ /**
369
+ * Start the TCP moving along a specified axis at a given velocity
370
+ */
371
+ async startTCPTranslation({ axis, direction, velocityMmPerSec }) {
372
+ if (!this.cartesianWebsocket) throw new Error("Cartesian jogging websocket not connected; call setJoggingMode first");
373
+ const zeroVector = {
374
+ x: 0,
375
+ y: 0,
376
+ z: 0
377
+ };
378
+ const joggingVector = Object.assign({}, zeroVector);
379
+ joggingVector[axis] = direction === "-" ? -1 : 1;
380
+ this.cartesianWebsocket.sendJson({
381
+ motion_group: this.motionGroupId,
382
+ position_direction: joggingVector,
383
+ rotation_direction: zeroVector,
384
+ position_velocity: velocityMmPerSec,
385
+ rotation_velocity: 0,
386
+ tcp: this.cartesianJoggingOpts.tcpId,
387
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
388
+ });
389
+ }
390
+ /**
391
+ * Start the TCP rotating around a specified axis at a given velocity
392
+ */
393
+ async startTCPRotation({ axis, direction, velocityRadsPerSec }) {
394
+ if (!this.cartesianWebsocket) throw new Error("Cartesian jogging websocket not connected; call setJoggingMode first");
395
+ const zeroVector = {
396
+ x: 0,
397
+ y: 0,
398
+ z: 0
399
+ };
400
+ const joggingVector = Object.assign({}, zeroVector);
401
+ joggingVector[axis] = direction === "-" ? -1 : 1;
402
+ this.cartesianWebsocket.sendJson({
403
+ motion_group: this.motionGroupId,
404
+ position_direction: zeroVector,
405
+ rotation_direction: joggingVector,
406
+ position_velocity: 0,
407
+ rotation_velocity: velocityRadsPerSec,
408
+ tcp: this.cartesianJoggingOpts.tcpId,
409
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
410
+ });
411
+ }
412
+ /**
413
+ * Move the robot by a fixed distance in a single cartesian
414
+ * axis, either rotating or translating relative to the TCP.
415
+ * Promise resolves only after the motion has completed.
416
+ */
417
+ async runIncrementalCartesianMotion({ currentTcpPose, currentJoints, coordSystemId, velocityInRelevantUnits, axis, direction, motion }) {
418
+ const commands = [];
419
+ if (!isSameCoordinateSystem(currentTcpPose.coordinate_system, coordSystemId)) throw new Error(`Current TCP pose coordinate system ${currentTcpPose.coordinate_system} does not match target coordinate system ${coordSystemId}`);
420
+ if (motion.type === "translate") {
421
+ const targetTcpPosition = Object.assign({}, currentTcpPose.position);
422
+ targetTcpPosition[axis] += motion.distanceMm * (direction === "-" ? -1 : 1);
423
+ commands.push({
424
+ settings: { limits_override: { tcp_velocity_limit: velocityInRelevantUnits } },
425
+ line: {
426
+ position: targetTcpPosition,
427
+ orientation: currentTcpPose.orientation,
428
+ coordinate_system: coordSystemId
429
+ }
430
+ });
431
+ } else if (motion.type === "rotate") {
432
+ const currentRotationVector = new Vector3$1(currentTcpPose.orientation.x, currentTcpPose.orientation.y, currentTcpPose.orientation.z);
433
+ const currentRotationRad = currentRotationVector.length();
434
+ const currentRotationDirection = currentRotationVector.clone().normalize();
435
+ const differenceRotationRad = motion.distanceRads * (direction === "-" ? -1 : 1);
436
+ const differenceRotationDirection = new Vector3$1(0, 0, 0);
437
+ differenceRotationDirection[axis] = 1;
438
+ const f1 = Math.cos(.5 * differenceRotationRad) * Math.cos(.5 * currentRotationRad);
439
+ const f2 = Math.sin(.5 * differenceRotationRad) * Math.sin(.5 * currentRotationRad);
440
+ const f3 = Math.sin(.5 * differenceRotationRad) * Math.cos(.5 * currentRotationRad);
441
+ const f4 = Math.cos(.5 * differenceRotationRad) * Math.sin(.5 * currentRotationRad);
442
+ const dotProduct = differenceRotationDirection.dot(currentRotationDirection);
443
+ const crossProduct = differenceRotationDirection.clone().cross(currentRotationDirection);
444
+ const newRotationRad = 2 * Math.acos(f1 - f2 * dotProduct);
445
+ const f5 = newRotationRad / Math.sin(.5 * newRotationRad);
446
+ const targetTcpOrientation = new Vector3$1().addScaledVector(crossProduct, f2).addScaledVector(differenceRotationDirection, f3).addScaledVector(currentRotationDirection, f4).multiplyScalar(f5);
447
+ commands.push({
448
+ settings: { limits_override: { tcp_orientation_velocity_limit: velocityInRelevantUnits } },
449
+ line: {
450
+ position: currentTcpPose.position,
451
+ orientation: targetTcpOrientation,
452
+ coordinate_system: coordSystemId
453
+ }
454
+ });
455
+ }
456
+ const motionPlanRes = await this.nova.api.motion.planMotion({
457
+ motion_group: this.motionGroupId,
458
+ start_joint_position: currentJoints,
459
+ tcp: this.cartesianJoggingOpts.tcpId,
460
+ commands
461
+ });
462
+ const plannedMotion = motionPlanRes.plan_successful_response?.motion;
463
+ if (!plannedMotion) throw new Error(`Failed to plan jogging increment motion ${JSON.stringify(motionPlanRes)}`);
464
+ await this.nova.api.motion.streamMoveForward(plannedMotion, 100, void 0, void 0, void 0, { timeout: 1e3 * 60 });
465
+ }
466
+ /**
467
+ * Rotate a single robot joint by a fixed number of radians
468
+ * Promise resolves only after the motion has completed.
469
+ */
470
+ async runIncrementalJointRotation({ joint, currentJoints, velocityRadsPerSec, direction, distanceRads }) {
471
+ const targetJoints = [...currentJoints.joints];
472
+ targetJoints[joint] += distanceRads * (direction === "-" ? -1 : 1);
473
+ const jointVelocityLimits = new Array(currentJoints.joints.length).fill(velocityRadsPerSec);
474
+ const motionPlanRes = await this.nova.api.motion.planMotion({
475
+ motion_group: this.motionGroupId,
476
+ start_joint_position: currentJoints,
477
+ commands: [{
478
+ settings: { limits_override: { joint_velocity_limits: { joints: jointVelocityLimits } } },
479
+ joint_ptp: { joints: targetJoints }
480
+ }]
481
+ });
482
+ const plannedMotion = motionPlanRes.plan_successful_response?.motion;
483
+ if (!plannedMotion) {
484
+ console.error("Failed to plan jogging increment motion", motionPlanRes);
485
+ return;
486
+ }
487
+ await this.nova.api.motion.streamMoveForward(plannedMotion, 100, void 0, void 0, void 0, { timeout: 1e3 * 60 });
488
+ }
739
489
  };
740
490
 
741
- // src/lib/v1/MotionStreamConnection.ts
742
- import { makeAutoObservable as makeAutoObservable2, runInAction as runInAction2 } from "mobx";
743
- import { Vector3 as Vector33 } from "three";
744
- var MOTION_DELTA_THRESHOLD2 = 1e-4;
491
+ //#endregion
492
+ //#region src/lib/v1/MotionStreamConnection.ts
493
+ const MOTION_DELTA_THRESHOLD = 1e-4;
745
494
  function unwrapRotationVector(newRotationVectorApi, currentRotationVectorApi) {
746
- const currentRotationVector = new Vector33(
747
- currentRotationVectorApi.x,
748
- currentRotationVectorApi.y,
749
- currentRotationVectorApi.z
750
- );
751
- const newRotationVector = new Vector33(
752
- newRotationVectorApi.x,
753
- newRotationVectorApi.y,
754
- newRotationVectorApi.z
755
- );
756
- const currentAngle = currentRotationVector.length();
757
- const currentAxis = currentRotationVector.normalize();
758
- let newAngle = newRotationVector.length();
759
- let newAxis = newRotationVector.normalize();
760
- if (newAxis.dot(currentAxis) < 0) {
761
- newAngle = -newAngle;
762
- newAxis = newAxis.multiplyScalar(-1);
763
- }
764
- let angleDifference = newAngle - currentAngle;
765
- angleDifference -= 2 * Math.PI * Math.floor((angleDifference + Math.PI) / (2 * Math.PI));
766
- newAngle = currentAngle + angleDifference;
767
- return newAxis.multiplyScalar(newAngle);
495
+ const currentRotationVector = new Vector3(currentRotationVectorApi.x, currentRotationVectorApi.y, currentRotationVectorApi.z);
496
+ const newRotationVector = new Vector3(newRotationVectorApi.x, newRotationVectorApi.y, newRotationVectorApi.z);
497
+ const currentAngle = currentRotationVector.length();
498
+ const currentAxis = currentRotationVector.normalize();
499
+ let newAngle = newRotationVector.length();
500
+ let newAxis = newRotationVector.normalize();
501
+ if (newAxis.dot(currentAxis) < 0) {
502
+ newAngle = -newAngle;
503
+ newAxis = newAxis.multiplyScalar(-1);
504
+ }
505
+ let angleDifference = newAngle - currentAngle;
506
+ angleDifference -= 2 * Math.PI * Math.floor((angleDifference + Math.PI) / (2 * Math.PI));
507
+ newAngle = currentAngle + angleDifference;
508
+ return newAxis.multiplyScalar(newAngle);
768
509
  }
769
- var MotionStreamConnection = class _MotionStreamConnection {
770
- constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket) {
771
- this.nova = nova;
772
- this.controller = controller;
773
- this.motionGroup = motionGroup;
774
- this.initialMotionState = initialMotionState;
775
- this.motionStateSocket = motionStateSocket;
776
- this.rapidlyChangingMotionState = initialMotionState;
777
- motionStateSocket.addEventListener("message", (event) => {
778
- var _a;
779
- const motionStateResponse = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result;
780
- if (!motionStateResponse) {
781
- throw new Error(
782
- `Failed to get motion state for ${this.motionGroupId}: ${event.data}`
783
- );
784
- }
785
- if (!jointValuesEqual(
786
- this.rapidlyChangingMotionState.state.joint_position.joints,
787
- motionStateResponse.state.joint_position.joints,
788
- MOTION_DELTA_THRESHOLD2
789
- )) {
790
- runInAction2(() => {
791
- this.rapidlyChangingMotionState.state = motionStateResponse.state;
792
- });
793
- }
794
- if (!tcpPoseEqual(
795
- this.rapidlyChangingMotionState.tcp_pose,
796
- motionStateResponse.tcp_pose,
797
- MOTION_DELTA_THRESHOLD2
798
- )) {
799
- runInAction2(() => {
800
- if (this.rapidlyChangingMotionState.tcp_pose == null) {
801
- this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
802
- } else {
803
- this.rapidlyChangingMotionState.tcp_pose = {
804
- position: motionStateResponse.tcp_pose.position,
805
- orientation: unwrapRotationVector(
806
- motionStateResponse.tcp_pose.orientation,
807
- this.rapidlyChangingMotionState.tcp_pose.orientation
808
- ),
809
- tcp: motionStateResponse.tcp_pose.tcp,
810
- coordinate_system: motionStateResponse.tcp_pose.coordinate_system
811
- };
812
- }
813
- });
814
- }
815
- });
816
- makeAutoObservable2(this);
817
- }
818
- static open(nova, motionGroupId) {
819
- return __async(this, null, function* () {
820
- var _a;
821
- const { instances: controllers } = yield nova.api.controller.listControllers();
822
- const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
823
- const controller = controllers.find((c) => c.controller === controllerId);
824
- const motionGroup = controller == null ? void 0 : controller.physical_motion_groups.find(
825
- (mg) => mg.motion_group === motionGroupId
826
- );
827
- if (!controller || !motionGroup) {
828
- throw new Error(
829
- `Controller ${controllerId} or motion group ${motionGroupId} not found`
830
- );
831
- }
832
- const motionStateSocket = nova.openReconnectingWebsocket(
833
- `/motion-groups/${motionGroupId}/state-stream`
834
- );
835
- const firstMessage = yield motionStateSocket.firstMessage();
836
- console.log("got first message", firstMessage);
837
- const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result;
838
- if (!initialMotionState) {
839
- throw new Error(
840
- `Unable to parse initial motion state message ${firstMessage.data}`
841
- );
842
- }
843
- console.log(
844
- `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:
845
- `,
846
- initialMotionState
847
- );
848
- return new _MotionStreamConnection(
849
- nova,
850
- controller,
851
- motionGroup,
852
- initialMotionState,
853
- motionStateSocket
854
- );
855
- });
856
- }
857
- get motionGroupId() {
858
- return this.motionGroup.motion_group;
859
- }
860
- get controllerId() {
861
- return this.controller.controller;
862
- }
863
- get modelFromController() {
864
- return this.motionGroup.model_from_controller;
865
- }
866
- get wandelscriptIdentifier() {
867
- const num = this.motionGroupId.split("@")[0];
868
- return `${this.controllerId.replaceAll("-", "_")}_${num}`;
869
- }
870
- get joints() {
871
- return this.initialMotionState.state.joint_position.joints.map((_, i) => {
872
- return {
873
- index: i
874
- };
875
- });
876
- }
877
- dispose() {
878
- this.motionStateSocket.close();
879
- }
510
+ /**
511
+ * Store representing the current state of a connected motion group.
512
+ */
513
+ var MotionStreamConnection = class MotionStreamConnection {
514
+ static async open(nova, motionGroupId) {
515
+ const { instances: controllers } = await nova.api.controller.listControllers();
516
+ const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
517
+ const controller = controllers.find((c) => c.controller === controllerId);
518
+ const motionGroup = controller?.physical_motion_groups.find((mg) => mg.motion_group === motionGroupId);
519
+ if (!controller || !motionGroup) throw new Error(`Controller ${controllerId} or motion group ${motionGroupId} not found`);
520
+ const motionStateSocket = nova.openReconnectingWebsocket(`/motion-groups/${motionGroupId}/state-stream`);
521
+ const firstMessage = await motionStateSocket.firstMessage();
522
+ console.log("got first message", firstMessage);
523
+ const initialMotionState = tryParseJson(firstMessage.data)?.result;
524
+ if (!initialMotionState) throw new Error(`Unable to parse initial motion state message ${firstMessage.data}`);
525
+ console.log(`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\n `, initialMotionState);
526
+ return new MotionStreamConnection(nova, controller, motionGroup, initialMotionState, motionStateSocket);
527
+ }
528
+ constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket) {
529
+ this.nova = nova;
530
+ this.controller = controller;
531
+ this.motionGroup = motionGroup;
532
+ this.initialMotionState = initialMotionState;
533
+ this.motionStateSocket = motionStateSocket;
534
+ this.rapidlyChangingMotionState = initialMotionState;
535
+ motionStateSocket.addEventListener("message", (event) => {
536
+ const motionStateResponse = tryParseJson(event.data)?.result;
537
+ if (!motionStateResponse) throw new Error(`Failed to get motion state for ${this.motionGroupId}: ${event.data}`);
538
+ if (!jointValuesEqual(this.rapidlyChangingMotionState.state.joint_position.joints, motionStateResponse.state.joint_position.joints, MOTION_DELTA_THRESHOLD)) runInAction(() => {
539
+ this.rapidlyChangingMotionState.state = motionStateResponse.state;
540
+ });
541
+ if (!tcpPoseEqual(this.rapidlyChangingMotionState.tcp_pose, motionStateResponse.tcp_pose, MOTION_DELTA_THRESHOLD)) runInAction(() => {
542
+ if (this.rapidlyChangingMotionState.tcp_pose == null) this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
543
+ else this.rapidlyChangingMotionState.tcp_pose = {
544
+ position: motionStateResponse.tcp_pose.position,
545
+ orientation: unwrapRotationVector(motionStateResponse.tcp_pose.orientation, this.rapidlyChangingMotionState.tcp_pose.orientation),
546
+ tcp: motionStateResponse.tcp_pose.tcp,
547
+ coordinate_system: motionStateResponse.tcp_pose.coordinate_system
548
+ };
549
+ });
550
+ });
551
+ makeAutoObservable(this);
552
+ }
553
+ get motionGroupId() {
554
+ return this.motionGroup.motion_group;
555
+ }
556
+ get controllerId() {
557
+ return this.controller.controller;
558
+ }
559
+ get modelFromController() {
560
+ return this.motionGroup.model_from_controller;
561
+ }
562
+ get wandelscriptIdentifier() {
563
+ const num = this.motionGroupId.split("@")[0];
564
+ return `${this.controllerId.replaceAll("-", "_")}_${num}`;
565
+ }
566
+ get joints() {
567
+ return this.initialMotionState.state.joint_position.joints.map((_, i) => {
568
+ return { index: i };
569
+ });
570
+ }
571
+ dispose() {
572
+ this.motionStateSocket.close();
573
+ }
880
574
  };
881
575
 
882
- // src/lib/v1/NovaCellAPIClient.ts
883
- import {
884
- ApplicationApi,
885
- CellApi,
886
- ControllerApi,
887
- ControllerIOsApi,
888
- CoordinateSystemsApi,
889
- DeviceConfigurationApi,
890
- LibraryProgramApi,
891
- LibraryProgramMetadataApi,
892
- LibraryRecipeApi,
893
- LibraryRecipeMetadataApi,
894
- MotionApi,
895
- MotionGroupApi,
896
- MotionGroupInfosApi,
897
- MotionGroupJoggingApi,
898
- MotionGroupKinematicApi,
899
- ProgramApi,
900
- ProgramValuesApi,
901
- StoreCollisionComponentsApi,
902
- StoreCollisionScenesApi,
903
- StoreObjectApi,
904
- SystemApi,
905
- VirtualRobotApi,
906
- VirtualRobotBehaviorApi,
907
- VirtualRobotModeApi,
908
- VirtualRobotSetupApi
909
- } from "@wandelbots/nova-api/v1";
910
- import axios from "axios";
576
+ //#endregion
577
+ //#region src/lib/v1/NovaCellAPIClient.ts
578
+ /**
579
+ * API client providing type-safe access to all the Nova API REST endpoints
580
+ * associated with a specific cell id.
581
+ */
911
582
  var NovaCellAPIClient = class {
912
- constructor(cellId, opts) {
913
- this.cellId = cellId;
914
- this.opts = opts;
915
- this.system = this.withUnwrappedResponsesOnly(SystemApi);
916
- this.cell = this.withUnwrappedResponsesOnly(CellApi);
917
- this.deviceConfig = this.withCellId(DeviceConfigurationApi);
918
- this.motionGroup = this.withCellId(MotionGroupApi);
919
- this.motionGroupInfos = this.withCellId(MotionGroupInfosApi);
920
- this.controller = this.withCellId(ControllerApi);
921
- this.program = this.withCellId(ProgramApi);
922
- this.programValues = this.withCellId(ProgramValuesApi);
923
- this.controllerIOs = this.withCellId(ControllerIOsApi);
924
- this.motionGroupKinematic = this.withCellId(MotionGroupKinematicApi);
925
- this.motion = this.withCellId(MotionApi);
926
- this.coordinateSystems = this.withCellId(CoordinateSystemsApi);
927
- this.application = this.withCellId(ApplicationApi);
928
- this.applicationGlobal = this.withUnwrappedResponsesOnly(ApplicationApi);
929
- this.motionGroupJogging = this.withCellId(MotionGroupJoggingApi);
930
- this.virtualRobot = this.withCellId(VirtualRobotApi);
931
- this.virtualRobotSetup = this.withCellId(VirtualRobotSetupApi);
932
- this.virtualRobotMode = this.withCellId(VirtualRobotModeApi);
933
- this.virtualRobotBehavior = this.withCellId(VirtualRobotBehaviorApi);
934
- this.libraryProgramMetadata = this.withCellId(LibraryProgramMetadataApi);
935
- this.libraryProgram = this.withCellId(LibraryProgramApi);
936
- this.libraryRecipeMetadata = this.withCellId(LibraryRecipeMetadataApi);
937
- this.libraryRecipe = this.withCellId(LibraryRecipeApi);
938
- this.storeObject = this.withCellId(StoreObjectApi);
939
- this.storeCollisionComponents = this.withCellId(
940
- StoreCollisionComponentsApi
941
- );
942
- this.storeCollisionScenes = this.withCellId(StoreCollisionScenesApi);
943
- }
944
- /**
945
- * Some TypeScript sorcery which alters the API class methods so you don't
946
- * have to pass the cell id to every single one, and de-encapsulates the
947
- * response data
948
- */
949
- withCellId(ApiConstructor) {
950
- var _a, _b;
951
- const apiClient = new ApiConstructor(
952
- __spreadProps(__spreadValues({}, this.opts), {
953
- isJsonMime: (mime) => {
954
- return mime === "application/json";
955
- }
956
- }),
957
- (_a = this.opts.basePath) != null ? _a : "",
958
- (_b = this.opts.axiosInstance) != null ? _b : axios.create()
959
- );
960
- for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) {
961
- if (key !== "constructor" && typeof apiClient[key] === "function") {
962
- const originalFunction = apiClient[key];
963
- apiClient[key] = (...args) => {
964
- return originalFunction.apply(apiClient, [this.cellId, ...args]).then((res) => res.data);
965
- };
966
- }
967
- }
968
- return apiClient;
969
- }
970
- /**
971
- * As withCellId, but only does the response unwrapping
972
- */
973
- withUnwrappedResponsesOnly(ApiConstructor) {
974
- var _a, _b;
975
- const apiClient = new ApiConstructor(
976
- __spreadProps(__spreadValues({}, this.opts), {
977
- isJsonMime: (mime) => {
978
- return mime === "application/json";
979
- }
980
- }),
981
- (_a = this.opts.basePath) != null ? _a : "",
982
- (_b = this.opts.axiosInstance) != null ? _b : axios.create()
983
- );
984
- for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) {
985
- if (key !== "constructor" && typeof apiClient[key] === "function") {
986
- const originalFunction = apiClient[key];
987
- apiClient[key] = (...args) => {
988
- return originalFunction.apply(apiClient, args).then((res) => res.data);
989
- };
990
- }
991
- }
992
- return apiClient;
993
- }
583
+ constructor(cellId, opts) {
584
+ this.cellId = cellId;
585
+ this.opts = opts;
586
+ this.system = this.withUnwrappedResponsesOnly(SystemApi);
587
+ this.cell = this.withUnwrappedResponsesOnly(CellApi);
588
+ this.deviceConfig = this.withCellId(DeviceConfigurationApi);
589
+ this.motionGroup = this.withCellId(MotionGroupApi);
590
+ this.motionGroupInfos = this.withCellId(MotionGroupInfosApi);
591
+ this.controller = this.withCellId(ControllerApi);
592
+ this.program = this.withCellId(ProgramApi);
593
+ this.programValues = this.withCellId(ProgramValuesApi);
594
+ this.controllerIOs = this.withCellId(ControllerIOsApi);
595
+ this.motionGroupKinematic = this.withCellId(MotionGroupKinematicApi);
596
+ this.motion = this.withCellId(MotionApi);
597
+ this.coordinateSystems = this.withCellId(CoordinateSystemsApi);
598
+ this.application = this.withCellId(ApplicationApi);
599
+ this.applicationGlobal = this.withUnwrappedResponsesOnly(ApplicationApi);
600
+ this.motionGroupJogging = this.withCellId(MotionGroupJoggingApi);
601
+ this.virtualRobot = this.withCellId(VirtualRobotApi);
602
+ this.virtualRobotSetup = this.withCellId(VirtualRobotSetupApi);
603
+ this.virtualRobotMode = this.withCellId(VirtualRobotModeApi);
604
+ this.virtualRobotBehavior = this.withCellId(VirtualRobotBehaviorApi);
605
+ this.libraryProgramMetadata = this.withCellId(LibraryProgramMetadataApi);
606
+ this.libraryProgram = this.withCellId(LibraryProgramApi);
607
+ this.libraryRecipeMetadata = this.withCellId(LibraryRecipeMetadataApi);
608
+ this.libraryRecipe = this.withCellId(LibraryRecipeApi);
609
+ this.storeObject = this.withCellId(StoreObjectApi);
610
+ this.storeCollisionComponents = this.withCellId(StoreCollisionComponentsApi);
611
+ this.storeCollisionScenes = this.withCellId(StoreCollisionScenesApi);
612
+ }
613
+ /**
614
+ * Some TypeScript sorcery which alters the API class methods so you don't
615
+ * have to pass the cell id to every single one, and de-encapsulates the
616
+ * response data
617
+ */
618
+ withCellId(ApiConstructor) {
619
+ const apiClient = new ApiConstructor({
620
+ ...this.opts,
621
+ isJsonMime: (mime) => {
622
+ return mime === "application/json";
623
+ }
624
+ }, this.opts.basePath ?? "", this.opts.axiosInstance ?? axios.create());
625
+ for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) if (key !== "constructor" && typeof apiClient[key] === "function") {
626
+ const originalFunction = apiClient[key];
627
+ apiClient[key] = (...args) => {
628
+ return originalFunction.apply(apiClient, [this.cellId, ...args]).then((res) => res.data);
629
+ };
630
+ }
631
+ return apiClient;
632
+ }
633
+ /**
634
+ * As withCellId, but only does the response unwrapping
635
+ */
636
+ withUnwrappedResponsesOnly(ApiConstructor) {
637
+ const apiClient = new ApiConstructor({
638
+ ...this.opts,
639
+ isJsonMime: (mime) => {
640
+ return mime === "application/json";
641
+ }
642
+ }, this.opts.basePath ?? "", this.opts.axiosInstance ?? axios.create());
643
+ for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) if (key !== "constructor" && typeof apiClient[key] === "function") {
644
+ const originalFunction = apiClient[key];
645
+ apiClient[key] = (...args) => {
646
+ return originalFunction.apply(apiClient, args).then((res) => res.data);
647
+ };
648
+ }
649
+ return apiClient;
650
+ }
994
651
  };
995
652
 
996
- // src/lib/v1/NovaClient.ts
997
- import axios2, { isAxiosError } from "axios";
998
- import urlJoin from "url-join";
999
-
1000
- // src/lib/v1/mock/MockNovaInstance.ts
1001
- import { AxiosError } from "axios";
1002
- import * as pathToRegexp from "path-to-regexp";
653
+ //#endregion
654
+ //#region src/lib/v1/mock/MockNovaInstance.ts
655
+ /**
656
+ * EXPERIMENTAL
657
+ * Ultra-simplified mock Nova server for testing stuff
658
+ */
1003
659
  var MockNovaInstance = class {
1004
- constructor() {
1005
- this.connections = [];
1006
- }
1007
- handleAPIRequest(config) {
1008
- return __async(this, null, function* () {
1009
- var _a, _b, _c;
1010
- const apiHandlers = [
1011
- {
1012
- method: "GET",
1013
- path: "/cells/:cellId/controllers",
1014
- handle() {
1015
- return {
1016
- instances: [
1017
- {
1018
- controller: "mock-ur5e",
1019
- model_name: "UniversalRobots::Controller",
1020
- host: "mock-ur5e",
1021
- allow_software_install_on_controller: true,
1022
- physical_motion_groups: [
1023
- {
1024
- motion_group: "0@mock-ur5e",
1025
- name_from_controller: "UR5e",
1026
- active: false,
1027
- model_from_controller: "UniversalRobots_UR5e"
1028
- }
1029
- ],
1030
- has_error: false,
1031
- error_details: ""
1032
- }
1033
- ]
1034
- };
1035
- }
1036
- },
1037
- {
1038
- method: "GET",
1039
- path: "/cells/:cellId/controllers/:controllerId",
1040
- handle() {
1041
- return {
1042
- configuration: {
1043
- kind: "VirtualController",
1044
- manufacturer: "universalrobots",
1045
- position: "[0,-1.571,-1.571,-1.571,1.571,-1.571,0]",
1046
- type: "universalrobots-ur5e"
1047
- },
1048
- name: "mock-ur5"
1049
- };
1050
- }
1051
- },
1052
- {
1053
- method: "GET",
1054
- path: "/cells/:cellId/motion-groups/:motionGroupId/specification",
1055
- handle() {
1056
- return {
1057
- dh_parameters: [
1058
- {
1059
- alpha: 1.5707963267948966,
1060
- theta: 0,
1061
- a: 0,
1062
- d: 162.25,
1063
- reverse_rotation_direction: false
1064
- },
1065
- {
1066
- alpha: 0,
1067
- theta: 0,
1068
- a: -425,
1069
- d: 0,
1070
- reverse_rotation_direction: false
1071
- },
1072
- {
1073
- alpha: 0,
1074
- theta: 0,
1075
- a: -392.2,
1076
- d: 0,
1077
- reverse_rotation_direction: false
1078
- },
1079
- {
1080
- alpha: 1.5707963267948966,
1081
- theta: 0,
1082
- a: 0,
1083
- d: 133.3,
1084
- reverse_rotation_direction: false
1085
- },
1086
- {
1087
- alpha: -1.5707963267948966,
1088
- theta: 0,
1089
- a: 0,
1090
- d: 99.7,
1091
- reverse_rotation_direction: false
1092
- },
1093
- {
1094
- alpha: 0,
1095
- theta: 0,
1096
- a: 0,
1097
- d: 99.6,
1098
- reverse_rotation_direction: false
1099
- }
1100
- ],
1101
- mechanical_joint_limits: [
1102
- {
1103
- joint: "JOINTNAME_AXIS_1",
1104
- lower_limit: -6.335545063018799,
1105
- upper_limit: 6.335545063018799,
1106
- unlimited: false
1107
- },
1108
- {
1109
- joint: "JOINTNAME_AXIS_2",
1110
- lower_limit: -6.335545063018799,
1111
- upper_limit: 6.335545063018799,
1112
- unlimited: false
1113
- },
1114
- {
1115
- joint: "JOINTNAME_AXIS_3",
1116
- lower_limit: -6.335545063018799,
1117
- upper_limit: 6.335545063018799,
1118
- unlimited: false
1119
- },
1120
- {
1121
- joint: "JOINTNAME_AXIS_4",
1122
- lower_limit: -6.335545063018799,
1123
- upper_limit: 6.335545063018799,
1124
- unlimited: false
1125
- },
1126
- {
1127
- joint: "JOINTNAME_AXIS_5",
1128
- lower_limit: -6.335545063018799,
1129
- upper_limit: 6.335545063018799,
1130
- unlimited: false
1131
- },
1132
- {
1133
- joint: "JOINTNAME_AXIS_6",
1134
- lower_limit: -6.335545063018799,
1135
- upper_limit: 6.335545063018799,
1136
- unlimited: false
1137
- }
1138
- ]
1139
- };
1140
- }
1141
- },
1142
- {
1143
- method: "GET",
1144
- path: "/cells/:cellId/motion-groups/:motionGroupId/safety-setup",
1145
- handle() {
1146
- return {
1147
- safety_settings: [
1148
- {
1149
- safety_state: "SAFETY_NORMAL",
1150
- settings: {
1151
- joint_position_limits: [
1152
- {
1153
- joint: "JOINTNAME_AXIS_1",
1154
- lower_limit: -2.96705961227417,
1155
- upper_limit: 2.96705961227417,
1156
- unlimited: false
1157
- },
1158
- {
1159
- joint: "JOINTNAME_AXIS_2",
1160
- lower_limit: -1.7453292608261108,
1161
- upper_limit: 2.7925267219543457,
1162
- unlimited: false
1163
- },
1164
- {
1165
- joint: "JOINTNAME_AXIS_3",
1166
- lower_limit: -3.3161256313323975,
1167
- upper_limit: 0.40142571926116943,
1168
- unlimited: false
1169
- },
1170
- {
1171
- joint: "JOINTNAME_AXIS_4",
1172
- lower_limit: -3.4906585216522217,
1173
- upper_limit: 3.4906585216522217,
1174
- unlimited: false
1175
- },
1176
- {
1177
- joint: "JOINTNAME_AXIS_5",
1178
- lower_limit: -2.4434609413146973,
1179
- upper_limit: 2.4434609413146973,
1180
- unlimited: false
1181
- },
1182
- {
1183
- joint: "JOINTNAME_AXIS_6",
1184
- lower_limit: -4.71238899230957,
1185
- upper_limit: 4.71238899230957,
1186
- unlimited: false
1187
- }
1188
- ],
1189
- joint_velocity_limits: [
1190
- {
1191
- joint: "JOINTNAME_AXIS_1",
1192
- limit: 3.1415927410125732
1193
- },
1194
- {
1195
- joint: "JOINTNAME_AXIS_2",
1196
- limit: 3.1415927410125732
1197
- },
1198
- {
1199
- joint: "JOINTNAME_AXIS_3",
1200
- limit: 3.4906585216522217
1201
- },
1202
- {
1203
- joint: "JOINTNAME_AXIS_4",
1204
- limit: 6.108652591705322
1205
- },
1206
- {
1207
- joint: "JOINTNAME_AXIS_5",
1208
- limit: 6.108652591705322
1209
- },
1210
- {
1211
- joint: "JOINTNAME_AXIS_6",
1212
- limit: 6.981317043304443
1213
- }
1214
- ],
1215
- joint_acceleration_limits: [],
1216
- joint_torque_limits: [],
1217
- tcp_velocity_limit: 1800
1218
- }
1219
- }
1220
- ],
1221
- safety_zones: [
1222
- {
1223
- id: 1,
1224
- priority: 0,
1225
- geometry: {
1226
- compound: {
1227
- child_geometries: [
1228
- {
1229
- convex_hull: {
1230
- vertices: [
1231
- {
1232
- x: -800,
1233
- y: -1330,
1234
- z: -1820
1235
- },
1236
- {
1237
- x: 1650,
1238
- y: -1330,
1239
- z: -1820
1240
- },
1241
- {
1242
- x: 1650,
1243
- y: 1330,
1244
- z: -1820
1245
- },
1246
- {
1247
- x: -800,
1248
- y: 1330,
1249
- z: -1820
1250
- }
1251
- ]
1252
- },
1253
- init_pose: {
1254
- position: {
1255
- x: 0,
1256
- y: 0,
1257
- z: 0
1258
- },
1259
- orientation: {
1260
- x: 0,
1261
- y: 0,
1262
- z: 0,
1263
- w: 1
1264
- }
1265
- },
1266
- id: "box"
1267
- },
1268
- {
1269
- convex_hull: {
1270
- vertices: [
1271
- {
1272
- x: -800,
1273
- y: -1330,
1274
- z: -1820
1275
- },
1276
- {
1277
- x: 1650,
1278
- y: -1330,
1279
- z: -1820
1280
- },
1281
- {
1282
- x: 1650,
1283
- y: -1330,
1284
- z: 1500
1285
- },
1286
- {
1287
- x: -800,
1288
- y: -1330,
1289
- z: 1500
1290
- }
1291
- ]
1292
- },
1293
- init_pose: {
1294
- position: {
1295
- x: 0,
1296
- y: 0,
1297
- z: 0
1298
- },
1299
- orientation: {
1300
- x: 0,
1301
- y: 0,
1302
- z: 0,
1303
- w: 1
1304
- }
1305
- },
1306
- id: "box"
1307
- },
1308
- {
1309
- convex_hull: {
1310
- vertices: [
1311
- {
1312
- x: -800,
1313
- y: -1330,
1314
- z: -1820
1315
- },
1316
- {
1317
- x: -800,
1318
- y: 1330,
1319
- z: -1820
1320
- },
1321
- {
1322
- x: -800,
1323
- y: 1330,
1324
- z: 1500
1325
- },
1326
- {
1327
- x: -800,
1328
- y: -1330,
1329
- z: 1500
1330
- }
1331
- ]
1332
- },
1333
- init_pose: {
1334
- position: {
1335
- x: 0,
1336
- y: 0,
1337
- z: 0
1338
- },
1339
- orientation: {
1340
- x: 0,
1341
- y: 0,
1342
- z: 0,
1343
- w: 1
1344
- }
1345
- },
1346
- id: "box"
1347
- },
1348
- {
1349
- convex_hull: {
1350
- vertices: [
1351
- {
1352
- x: 1650,
1353
- y: 1330,
1354
- z: 1500
1355
- },
1356
- {
1357
- x: -800,
1358
- y: 1330,
1359
- z: 1500
1360
- },
1361
- {
1362
- x: -800,
1363
- y: -1330,
1364
- z: 1500
1365
- },
1366
- {
1367
- x: 1650,
1368
- y: -1330,
1369
- z: 1500
1370
- }
1371
- ]
1372
- },
1373
- init_pose: {
1374
- position: {
1375
- x: 0,
1376
- y: 0,
1377
- z: 0
1378
- },
1379
- orientation: {
1380
- x: 0,
1381
- y: 0,
1382
- z: 0,
1383
- w: 1
1384
- }
1385
- },
1386
- id: "box"
1387
- },
1388
- {
1389
- convex_hull: {
1390
- vertices: [
1391
- {
1392
- x: 1650,
1393
- y: 1330,
1394
- z: 1500
1395
- },
1396
- {
1397
- x: -800,
1398
- y: 1330,
1399
- z: 1500
1400
- },
1401
- {
1402
- x: -800,
1403
- y: 1330,
1404
- z: -1820
1405
- },
1406
- {
1407
- x: 1650,
1408
- y: 1330,
1409
- z: -1820
1410
- }
1411
- ]
1412
- },
1413
- init_pose: {
1414
- position: {
1415
- x: 0,
1416
- y: 0,
1417
- z: 0
1418
- },
1419
- orientation: {
1420
- x: 0,
1421
- y: 0,
1422
- z: 0,
1423
- w: 1
1424
- }
1425
- },
1426
- id: "box"
1427
- },
1428
- {
1429
- convex_hull: {
1430
- vertices: [
1431
- {
1432
- x: 1650,
1433
- y: 1330,
1434
- z: 1500
1435
- },
1436
- {
1437
- x: 1650,
1438
- y: -1330,
1439
- z: 1500
1440
- },
1441
- {
1442
- x: 1650,
1443
- y: -1330,
1444
- z: -1820
1445
- },
1446
- {
1447
- x: 1650,
1448
- y: 1330,
1449
- z: -1820
1450
- }
1451
- ]
1452
- },
1453
- init_pose: {
1454
- position: {
1455
- x: 0,
1456
- y: 0,
1457
- z: 0
1458
- },
1459
- orientation: {
1460
- x: 0,
1461
- y: 0,
1462
- z: 0,
1463
- w: 1
1464
- }
1465
- },
1466
- id: "box"
1467
- }
1468
- ]
1469
- },
1470
- init_pose: {
1471
- position: {
1472
- x: 0,
1473
- y: 0,
1474
- z: 0
1475
- },
1476
- orientation: {
1477
- x: 0,
1478
- y: 0,
1479
- z: 0,
1480
- w: 1
1481
- }
1482
- },
1483
- id: "Cell workzone"
1484
- },
1485
- motion_group_uid: 1
1486
- },
1487
- {
1488
- id: 2,
1489
- priority: 0,
1490
- geometry: {
1491
- convex_hull: {
1492
- vertices: [
1493
- {
1494
- x: 1650,
1495
- y: 1330,
1496
- z: -1850
1497
- },
1498
- {
1499
- x: 865,
1500
- y: 1330,
1501
- z: -1850
1502
- },
1503
- {
1504
- x: 865,
1505
- y: -720,
1506
- z: -1850
1507
- },
1508
- {
1509
- x: 1650,
1510
- y: -720,
1511
- z: -1850
1512
- },
1513
- {
1514
- x: 1650,
1515
- y: 1330,
1516
- z: -920
1517
- },
1518
- {
1519
- x: 865,
1520
- y: 1330,
1521
- z: -920
1522
- },
1523
- {
1524
- x: 865,
1525
- y: -720,
1526
- z: -920
1527
- },
1528
- {
1529
- x: 1650,
1530
- y: -720,
1531
- z: -920
1532
- }
1533
- ]
1534
- },
1535
- init_pose: {
1536
- position: {
1537
- x: 0,
1538
- y: 0,
1539
- z: 0
1540
- },
1541
- orientation: {
1542
- x: 0,
1543
- y: 0,
1544
- z: 0,
1545
- w: 1
1546
- }
1547
- },
1548
- id: "Transport"
1549
- },
1550
- motion_group_uid: 1
1551
- },
1552
- {
1553
- id: 3,
1554
- priority: 0,
1555
- geometry: {
1556
- convex_hull: {
1557
- vertices: [
1558
- {
1559
- x: 1650,
1560
- y: 1330,
1561
- z: -600
1562
- },
1563
- {
1564
- x: 865,
1565
- y: 1330,
1566
- z: -600
1567
- },
1568
- {
1569
- x: 865,
1570
- y: 430,
1571
- z: -600
1572
- },
1573
- {
1574
- x: 1650,
1575
- y: 430,
1576
- z: -600
1577
- },
1578
- {
1579
- x: 1650,
1580
- y: 1330,
1581
- z: -1250
1582
- },
1583
- {
1584
- x: 865,
1585
- y: 1330,
1586
- z: -1250
1587
- },
1588
- {
1589
- x: 865,
1590
- y: 430,
1591
- z: -1250
1592
- },
1593
- {
1594
- x: 1650,
1595
- y: 430,
1596
- z: -1250
1597
- }
1598
- ]
1599
- },
1600
- init_pose: {
1601
- position: {
1602
- x: 0,
1603
- y: 0,
1604
- z: 0
1605
- },
1606
- orientation: {
1607
- x: 0,
1608
- y: 0,
1609
- z: 0,
1610
- w: 1
1611
- }
1612
- },
1613
- id: "Tunel"
1614
- },
1615
- motion_group_uid: 1
1616
- },
1617
- {
1618
- id: 4,
1619
- priority: 0,
1620
- geometry: {
1621
- convex_hull: {
1622
- vertices: [
1623
- {
1624
- x: 1650,
1625
- y: -760,
1626
- z: -440
1627
- },
1628
- {
1629
- x: 900,
1630
- y: -760,
1631
- z: -440
1632
- },
1633
- {
1634
- x: 900,
1635
- y: -1330,
1636
- z: -440
1637
- },
1638
- {
1639
- x: 1650,
1640
- y: -1330,
1641
- z: -440
1642
- },
1643
- {
1644
- x: 1650,
1645
- y: -760,
1646
- z: -1800
1647
- },
1648
- {
1649
- x: 900,
1650
- y: -760,
1651
- z: -1800
1652
- },
1653
- {
1654
- x: 900,
1655
- y: -1330,
1656
- z: -1800
1657
- },
1658
- {
1659
- x: 1650,
1660
- y: -1330,
1661
- z: -1800
1662
- }
1663
- ]
1664
- },
1665
- init_pose: {
1666
- position: {
1667
- x: 0,
1668
- y: 0,
1669
- z: 0
1670
- },
1671
- orientation: {
1672
- x: 0,
1673
- y: 0,
1674
- z: 0,
1675
- w: 1
1676
- }
1677
- },
1678
- id: "Fanuc controller"
1679
- },
1680
- motion_group_uid: 1
1681
- },
1682
- {
1683
- id: 6,
1684
- priority: 0,
1685
- geometry: {
1686
- convex_hull: {
1687
- vertices: [
1688
- {
1689
- x: -200,
1690
- y: -200,
1691
- z: -1900
1692
- },
1693
- {
1694
- x: 200,
1695
- y: -200,
1696
- z: -1900
1697
- },
1698
- {
1699
- x: 200,
1700
- y: 200,
1701
- z: -1900
1702
- },
1703
- {
1704
- x: -200,
1705
- y: 200,
1706
- z: -1900
1707
- },
1708
- {
1709
- x: -200,
1710
- y: -200,
1711
- z: -350
1712
- },
1713
- {
1714
- x: 200,
1715
- y: -200,
1716
- z: -350
1717
- },
1718
- {
1719
- x: 200,
1720
- y: 200,
1721
- z: -350
1722
- },
1723
- {
1724
- x: -200,
1725
- y: 200,
1726
- z: -350
1727
- }
1728
- ]
1729
- },
1730
- init_pose: {
1731
- position: {
1732
- x: 0,
1733
- y: 0,
1734
- z: 0
1735
- },
1736
- orientation: {
1737
- x: 0,
1738
- y: 0,
1739
- z: 0,
1740
- w: 1
1741
- }
1742
- },
1743
- id: "Robot base"
1744
- },
1745
- motion_group_uid: 1
1746
- }
1747
- ],
1748
- robot_model_geometries: [
1749
- {
1750
- link_index: 1,
1751
- geometry: {
1752
- sphere: {
1753
- radius: 270
1754
- },
1755
- init_pose: {
1756
- position: {
1757
- x: -70,
1758
- y: -70,
1759
- z: -50
1760
- },
1761
- orientation: {
1762
- x: 0,
1763
- y: 0,
1764
- z: 0,
1765
- w: 1
1766
- }
1767
- },
1768
- id: "link1_sphere"
1769
- }
1770
- },
1771
- {
1772
- link_index: 2,
1773
- geometry: {
1774
- capsule: {
1775
- radius: 160,
1776
- cylinder_height: 800
1777
- },
1778
- init_pose: {
1779
- position: {
1780
- x: -450,
1781
- y: 40,
1782
- z: 170
1783
- },
1784
- orientation: {
1785
- x: 0,
1786
- y: -Math.SQRT1_2,
1787
- z: 0,
1788
- w: Math.SQRT1_2
1789
- }
1790
- },
1791
- id: "link2_capsule"
1792
- }
1793
- },
1794
- {
1795
- link_index: 3,
1796
- geometry: {
1797
- sphere: {
1798
- radius: 270
1799
- },
1800
- init_pose: {
1801
- position: {
1802
- x: -110,
1803
- y: 10,
1804
- z: -100
1805
- },
1806
- orientation: {
1807
- x: 0,
1808
- y: 0,
1809
- z: 0,
1810
- w: 1
1811
- }
1812
- },
1813
- id: "link3_sphere"
1814
- }
1815
- },
1816
- {
1817
- link_index: 4,
1818
- geometry: {
1819
- capsule: {
1820
- radius: 110,
1821
- cylinder_height: 600
1822
- },
1823
- init_pose: {
1824
- position: {
1825
- x: 0,
1826
- y: 300,
1827
- z: 40
1828
- },
1829
- orientation: {
1830
- x: -Math.SQRT1_2,
1831
- y: 0,
1832
- z: 0,
1833
- w: Math.SQRT1_2
1834
- }
1835
- },
1836
- id: "link4_capsule"
1837
- }
1838
- },
1839
- {
1840
- link_index: 5,
1841
- geometry: {
1842
- sphere: {
1843
- radius: 75
1844
- },
1845
- init_pose: {
1846
- position: {
1847
- x: 0,
1848
- y: 0,
1849
- z: -50
1850
- },
1851
- orientation: {
1852
- x: 0,
1853
- y: 0,
1854
- z: 0,
1855
- w: 1
1856
- }
1857
- },
1858
- id: "link5_sphere"
1859
- }
1860
- }
1861
- ],
1862
- tool_geometries: []
1863
- };
1864
- }
1865
- },
1866
- {
1867
- method: "GET",
1868
- path: "/cells/:cellId/coordinate-systems",
1869
- handle() {
1870
- return {
1871
- coordinatesystems: [
1872
- {
1873
- coordinate_system: "",
1874
- name: "world",
1875
- reference_uid: "",
1876
- position: {
1877
- x: 0,
1878
- y: 0,
1879
- z: 0
1880
- },
1881
- rotation: {
1882
- angles: [0, 0, 0],
1883
- type: "ROTATION_VECTOR"
1884
- }
1885
- }
1886
- ]
1887
- };
1888
- }
1889
- },
1890
- {
1891
- method: "GET",
1892
- path: "/cells/:cellId/motion-groups/:motionGroupId/tcps",
1893
- handle() {
1894
- return {
1895
- tcps: [
1896
- {
1897
- id: "Flange",
1898
- readable_name: "Default-Flange",
1899
- position: {
1900
- x: 0,
1901
- y: 0,
1902
- z: 0
1903
- },
1904
- rotation: {
1905
- angles: [0, 0, 0, 0],
1906
- type: "ROTATION_VECTOR"
1907
- }
1908
- },
1909
- {
1910
- id: "complex-tcp-position",
1911
- readable_name: "Complex TCP Position",
1912
- position: {
1913
- x: -200,
1914
- y: 300,
1915
- z: 150
1916
- },
1917
- rotation: {
1918
- angles: [
1919
- -0.12139440409113832,
1920
- -0.06356210998212003,
1921
- -0.2023240068185639,
1922
- 0
1923
- ],
1924
- type: "ROTATION_VECTOR"
1925
- }
1926
- }
1927
- ]
1928
- };
1929
- }
1930
- }
1931
- ];
1932
- const method = ((_a = config.method) == null ? void 0 : _a.toUpperCase()) || "GET";
1933
- const path = `/cells${(_c = (_b = config.url) == null ? void 0 : _b.split("/cells")[1]) == null ? void 0 : _c.split("?")[0]}`;
1934
- for (const handler of apiHandlers) {
1935
- const match2 = pathToRegexp.match(handler.path)(path || "");
1936
- if (method === handler.method && match2) {
1937
- const json = handler.handle();
1938
- return {
1939
- status: 200,
1940
- statusText: "Success",
1941
- data: JSON.stringify(json),
1942
- headers: {},
1943
- config,
1944
- request: {
1945
- responseURL: config.url
1946
- }
1947
- };
1948
- }
1949
- }
1950
- throw new AxiosError(
1951
- `No mock handler matched this request: ${method} ${path}`,
1952
- "404",
1953
- config
1954
- );
1955
- });
1956
- }
1957
- handleWebsocketConnection(socket) {
1958
- this.connections.push(socket);
1959
- setTimeout(() => {
1960
- socket.dispatchEvent(new Event("open"));
1961
- console.log("Websocket connection opened from", socket.url);
1962
- if (socket.url.includes("/state-stream")) {
1963
- socket.dispatchEvent(
1964
- new MessageEvent("message", {
1965
- data: JSON.stringify(defaultMotionState)
1966
- })
1967
- );
1968
- }
1969
- if (socket.url.includes("/move-joint")) {
1970
- socket.dispatchEvent(
1971
- new MessageEvent("message", {
1972
- data: JSON.stringify({
1973
- result: {
1974
- motion_group: "0@ur",
1975
- state: {
1976
- controller: "ur",
1977
- operation_mode: "OPERATION_MODE_AUTO",
1978
- safety_state: "SAFETY_STATE_NORMAL",
1979
- timestamp: "2024-09-18T12:48:26.096266444Z",
1980
- velocity_override: 100,
1981
- motion_groups: [
1982
- {
1983
- motion_group: "0@ur",
1984
- controller: "ur",
1985
- joint_position: {
1986
- joints: [
1987
- 1.3492152690887451,
1988
- -1.5659207105636597,
1989
- 1.6653711795806885,
1990
- -1.0991662740707397,
1991
- -1.829018235206604,
1992
- 1.264623761177063
1993
- ]
1994
- },
1995
- joint_velocity: {
1996
- joints: [0, 0, 0, 0, 0, 0]
1997
- },
1998
- flange_pose: {
1999
- position: {
2000
- x: 6.437331889439328,
2001
- y: -628.4123774830913,
2002
- z: 577.0569957147832
2003
- },
2004
- orientation: {
2005
- x: -1.683333649797158,
2006
- y: -1.9783363827298732,
2007
- z: -0.4928031860165713
2008
- },
2009
- coordinate_system: ""
2010
- },
2011
- tcp_pose: {
2012
- position: {
2013
- x: 6.437331889439328,
2014
- y: -628.4123774830913,
2015
- z: 577.0569957147832
2016
- },
2017
- orientation: {
2018
- x: -1.683333649797158,
2019
- y: -1.9783363827298732,
2020
- z: -0.4928031860165713
2021
- },
2022
- coordinate_system: "",
2023
- tcp: "Flange"
2024
- },
2025
- velocity: {
2026
- linear: {
2027
- x: 0,
2028
- y: 0,
2029
- z: 0
2030
- },
2031
- angular: {
2032
- x: -0,
2033
- y: 0,
2034
- z: 0
2035
- },
2036
- coordinate_system: ""
2037
- },
2038
- force: {
2039
- force: {
2040
- x: 0,
2041
- y: 0,
2042
- z: 0
2043
- },
2044
- moment: {
2045
- x: 0,
2046
- y: 0,
2047
- z: 0
2048
- },
2049
- coordinate_system: ""
2050
- },
2051
- joint_limit_reached: {
2052
- limit_reached: [
2053
- false,
2054
- false,
2055
- false,
2056
- false,
2057
- false,
2058
- false
2059
- ]
2060
- },
2061
- joint_current: {
2062
- joints: [0, 0, 0, 0, 0, 0]
2063
- },
2064
- sequence_number: "671259"
2065
- }
2066
- ],
2067
- sequence_number: "671259"
2068
- },
2069
- movement_state: "MOVEMENT_STATE_MOVING"
2070
- }
2071
- })
2072
- })
2073
- );
2074
- }
2075
- if (socket.url.includes("/move-tcp")) {
2076
- socket.dispatchEvent(
2077
- new MessageEvent("message", {
2078
- data: JSON.stringify({
2079
- result: {
2080
- motion_group: "0@ur",
2081
- state: {
2082
- controller: "ur",
2083
- operation_mode: "OPERATION_MODE_AUTO",
2084
- safety_state: "SAFETY_STATE_NORMAL",
2085
- timestamp: "2024-09-18T12:43:12.188335774Z",
2086
- velocity_override: 100,
2087
- motion_groups: [
2088
- {
2089
- motion_group: "0@ur",
2090
- controller: "ur",
2091
- joint_position: {
2092
- joints: [
2093
- 1.3352527618408203,
2094
- -1.5659207105636597,
2095
- 1.6653711795806885,
2096
- -1.110615611076355,
2097
- -1.829018235206604,
2098
- 1.264623761177063
2099
- ]
2100
- },
2101
- joint_velocity: {
2102
- joints: [0, 0, 0, 0, 0, 0]
2103
- },
2104
- flange_pose: {
2105
- position: {
2106
- x: -2.763015284002938,
2107
- y: -630.2151479701106,
2108
- z: 577.524509114342
2109
- },
2110
- orientation: {
2111
- x: -1.704794877102097,
2112
- y: -1.9722372952861567,
2113
- z: -0.4852079204210754
2114
- },
2115
- coordinate_system: ""
2116
- },
2117
- tcp_pose: {
2118
- position: {
2119
- x: -2.763015284002938,
2120
- y: -630.2151479701106,
2121
- z: 577.524509114342
2122
- },
2123
- orientation: {
2124
- x: -1.704794877102097,
2125
- y: -1.9722372952861567,
2126
- z: -0.4852079204210754
2127
- },
2128
- coordinate_system: "",
2129
- tcp: "Flange"
2130
- },
2131
- velocity: {
2132
- linear: {
2133
- x: 0,
2134
- y: 0,
2135
- z: 0
2136
- },
2137
- angular: {
2138
- x: -0,
2139
- y: 0,
2140
- z: 0
2141
- },
2142
- coordinate_system: ""
2143
- },
2144
- force: {
2145
- force: {
2146
- x: 0,
2147
- y: 0,
2148
- z: 0
2149
- },
2150
- moment: {
2151
- x: 0,
2152
- y: 0,
2153
- z: 0
2154
- },
2155
- coordinate_system: ""
2156
- },
2157
- joint_limit_reached: {
2158
- limit_reached: [
2159
- false,
2160
- false,
2161
- false,
2162
- false,
2163
- false,
2164
- false
2165
- ]
2166
- },
2167
- joint_current: {
2168
- joints: [0, 0, 0, 0, 0, 0]
2169
- },
2170
- sequence_number: "627897"
2171
- }
2172
- ],
2173
- sequence_number: "627897"
2174
- },
2175
- movement_state: "MOVEMENT_STATE_MOVING"
2176
- }
2177
- })
2178
- })
2179
- );
2180
- }
2181
- }, 10);
2182
- }
2183
- handleWebsocketMessage(socket, message) {
2184
- console.log(`Received message on ${socket.url}`, message);
2185
- }
2186
- };
2187
- var defaultMotionState = {
2188
- result: {
2189
- state: {
2190
- motion_group: "0@universalrobots-ur5e",
2191
- controller: "universalrobots-ur5e",
2192
- joint_position: {
2193
- joints: [
2194
- 1.1699999570846558,
2195
- -1.5700000524520874,
2196
- 1.3600000143051147,
2197
- 1.0299999713897705,
2198
- 1.2899999618530273,
2199
- 1.2799999713897705
2200
- ]
2201
- },
2202
- joint_velocity: {
2203
- joints: [0, 0, 0, 0, 0, 0]
2204
- },
2205
- flange_pose: {
2206
- position: {
2207
- x: 1.3300010259703043,
2208
- y: -409.2680714682808,
2209
- z: 531.0203477065281
2210
- },
2211
- orientation: {
2212
- x: 1.7564919306270736,
2213
- y: -1.7542521568325058,
2214
- z: 0.7326972590614671
2215
- },
2216
- coordinate_system: ""
2217
- },
2218
- tcp_pose: {
2219
- position: {
2220
- x: 1.3300010259703043,
2221
- y: -409.2680714682808,
2222
- z: 531.0203477065281
2223
- },
2224
- orientation: {
2225
- x: 1.7564919306270736,
2226
- y: -1.7542521568325058,
2227
- z: 0.7326972590614671
2228
- },
2229
- coordinate_system: "",
2230
- tcp: "Flange"
2231
- },
2232
- velocity: {
2233
- linear: {
2234
- x: 0,
2235
- y: 0,
2236
- z: 0
2237
- },
2238
- angular: {
2239
- x: 0,
2240
- y: 0,
2241
- z: 0
2242
- },
2243
- coordinate_system: ""
2244
- },
2245
- force: {
2246
- force: {
2247
- x: 0,
2248
- y: 0,
2249
- z: 0
2250
- },
2251
- moment: {
2252
- x: 0,
2253
- y: 0,
2254
- z: 0
2255
- },
2256
- coordinate_system: ""
2257
- },
2258
- joint_limit_reached: {
2259
- limit_reached: [false, false, false, false, false, false]
2260
- },
2261
- joint_current: {
2262
- joints: [0, 0, 0, 0, 0, 0]
2263
- },
2264
- sequence_number: "1"
2265
- },
2266
- tcp_pose: {
2267
- position: {
2268
- x: 302.90748476115556,
2269
- y: -152.87065869452337,
2270
- z: 424.0454619321661
2271
- },
2272
- orientation: {
2273
- x: 2.3403056115045353,
2274
- y: -1.1706836379431356,
2275
- z: 0.9772511964246311
2276
- },
2277
- coordinate_system: "",
2278
- tcp: "Flange"
2279
- }
2280
- }
660
+ constructor() {
661
+ this.connections = [];
662
+ }
663
+ async handleAPIRequest(config) {
664
+ const apiHandlers = [
665
+ {
666
+ method: "GET",
667
+ path: "/cells/:cellId/controllers",
668
+ handle() {
669
+ return { instances: [{
670
+ controller: "mock-ur5e",
671
+ model_name: "UniversalRobots::Controller",
672
+ host: "mock-ur5e",
673
+ allow_software_install_on_controller: true,
674
+ physical_motion_groups: [{
675
+ motion_group: "0@mock-ur5e",
676
+ name_from_controller: "UR5e",
677
+ active: false,
678
+ model_from_controller: "UniversalRobots_UR5e"
679
+ }],
680
+ has_error: false,
681
+ error_details: ""
682
+ }] };
683
+ }
684
+ },
685
+ {
686
+ method: "GET",
687
+ path: "/cells/:cellId/controllers/:controllerId",
688
+ handle() {
689
+ return {
690
+ configuration: {
691
+ kind: "VirtualController",
692
+ manufacturer: "universalrobots",
693
+ position: "[0,-1.571,-1.571,-1.571,1.571,-1.571,0]",
694
+ type: "universalrobots-ur5e"
695
+ },
696
+ name: "mock-ur5"
697
+ };
698
+ }
699
+ },
700
+ {
701
+ method: "GET",
702
+ path: "/cells/:cellId/motion-groups/:motionGroupId/specification",
703
+ handle() {
704
+ return {
705
+ dh_parameters: [
706
+ {
707
+ alpha: 1.5707963267948966,
708
+ theta: 0,
709
+ a: 0,
710
+ d: 162.25,
711
+ reverse_rotation_direction: false
712
+ },
713
+ {
714
+ alpha: 0,
715
+ theta: 0,
716
+ a: -425,
717
+ d: 0,
718
+ reverse_rotation_direction: false
719
+ },
720
+ {
721
+ alpha: 0,
722
+ theta: 0,
723
+ a: -392.2,
724
+ d: 0,
725
+ reverse_rotation_direction: false
726
+ },
727
+ {
728
+ alpha: 1.5707963267948966,
729
+ theta: 0,
730
+ a: 0,
731
+ d: 133.3,
732
+ reverse_rotation_direction: false
733
+ },
734
+ {
735
+ alpha: -1.5707963267948966,
736
+ theta: 0,
737
+ a: 0,
738
+ d: 99.7,
739
+ reverse_rotation_direction: false
740
+ },
741
+ {
742
+ alpha: 0,
743
+ theta: 0,
744
+ a: 0,
745
+ d: 99.6,
746
+ reverse_rotation_direction: false
747
+ }
748
+ ],
749
+ mechanical_joint_limits: [
750
+ {
751
+ joint: "JOINTNAME_AXIS_1",
752
+ lower_limit: -6.335545063018799,
753
+ upper_limit: 6.335545063018799,
754
+ unlimited: false
755
+ },
756
+ {
757
+ joint: "JOINTNAME_AXIS_2",
758
+ lower_limit: -6.335545063018799,
759
+ upper_limit: 6.335545063018799,
760
+ unlimited: false
761
+ },
762
+ {
763
+ joint: "JOINTNAME_AXIS_3",
764
+ lower_limit: -6.335545063018799,
765
+ upper_limit: 6.335545063018799,
766
+ unlimited: false
767
+ },
768
+ {
769
+ joint: "JOINTNAME_AXIS_4",
770
+ lower_limit: -6.335545063018799,
771
+ upper_limit: 6.335545063018799,
772
+ unlimited: false
773
+ },
774
+ {
775
+ joint: "JOINTNAME_AXIS_5",
776
+ lower_limit: -6.335545063018799,
777
+ upper_limit: 6.335545063018799,
778
+ unlimited: false
779
+ },
780
+ {
781
+ joint: "JOINTNAME_AXIS_6",
782
+ lower_limit: -6.335545063018799,
783
+ upper_limit: 6.335545063018799,
784
+ unlimited: false
785
+ }
786
+ ]
787
+ };
788
+ }
789
+ },
790
+ {
791
+ method: "GET",
792
+ path: "/cells/:cellId/motion-groups/:motionGroupId/safety-setup",
793
+ handle() {
794
+ return {
795
+ safety_settings: [{
796
+ safety_state: "SAFETY_NORMAL",
797
+ settings: {
798
+ joint_position_limits: [
799
+ {
800
+ joint: "JOINTNAME_AXIS_1",
801
+ lower_limit: -2.96705961227417,
802
+ upper_limit: 2.96705961227417,
803
+ unlimited: false
804
+ },
805
+ {
806
+ joint: "JOINTNAME_AXIS_2",
807
+ lower_limit: -1.7453292608261108,
808
+ upper_limit: 2.7925267219543457,
809
+ unlimited: false
810
+ },
811
+ {
812
+ joint: "JOINTNAME_AXIS_3",
813
+ lower_limit: -3.3161256313323975,
814
+ upper_limit: .40142571926116943,
815
+ unlimited: false
816
+ },
817
+ {
818
+ joint: "JOINTNAME_AXIS_4",
819
+ lower_limit: -3.4906585216522217,
820
+ upper_limit: 3.4906585216522217,
821
+ unlimited: false
822
+ },
823
+ {
824
+ joint: "JOINTNAME_AXIS_5",
825
+ lower_limit: -2.4434609413146973,
826
+ upper_limit: 2.4434609413146973,
827
+ unlimited: false
828
+ },
829
+ {
830
+ joint: "JOINTNAME_AXIS_6",
831
+ lower_limit: -4.71238899230957,
832
+ upper_limit: 4.71238899230957,
833
+ unlimited: false
834
+ }
835
+ ],
836
+ joint_velocity_limits: [
837
+ {
838
+ joint: "JOINTNAME_AXIS_1",
839
+ limit: 3.1415927410125732
840
+ },
841
+ {
842
+ joint: "JOINTNAME_AXIS_2",
843
+ limit: 3.1415927410125732
844
+ },
845
+ {
846
+ joint: "JOINTNAME_AXIS_3",
847
+ limit: 3.4906585216522217
848
+ },
849
+ {
850
+ joint: "JOINTNAME_AXIS_4",
851
+ limit: 6.108652591705322
852
+ },
853
+ {
854
+ joint: "JOINTNAME_AXIS_5",
855
+ limit: 6.108652591705322
856
+ },
857
+ {
858
+ joint: "JOINTNAME_AXIS_6",
859
+ limit: 6.981317043304443
860
+ }
861
+ ],
862
+ joint_acceleration_limits: [],
863
+ joint_torque_limits: [],
864
+ tcp_velocity_limit: 1800
865
+ }
866
+ }],
867
+ safety_zones: [
868
+ {
869
+ id: 1,
870
+ priority: 0,
871
+ geometry: {
872
+ compound: { child_geometries: [
873
+ {
874
+ convex_hull: { vertices: [
875
+ {
876
+ x: -800,
877
+ y: -1330,
878
+ z: -1820
879
+ },
880
+ {
881
+ x: 1650,
882
+ y: -1330,
883
+ z: -1820
884
+ },
885
+ {
886
+ x: 1650,
887
+ y: 1330,
888
+ z: -1820
889
+ },
890
+ {
891
+ x: -800,
892
+ y: 1330,
893
+ z: -1820
894
+ }
895
+ ] },
896
+ init_pose: {
897
+ position: {
898
+ x: 0,
899
+ y: 0,
900
+ z: 0
901
+ },
902
+ orientation: {
903
+ x: 0,
904
+ y: 0,
905
+ z: 0,
906
+ w: 1
907
+ }
908
+ },
909
+ id: "box"
910
+ },
911
+ {
912
+ convex_hull: { vertices: [
913
+ {
914
+ x: -800,
915
+ y: -1330,
916
+ z: -1820
917
+ },
918
+ {
919
+ x: 1650,
920
+ y: -1330,
921
+ z: -1820
922
+ },
923
+ {
924
+ x: 1650,
925
+ y: -1330,
926
+ z: 1500
927
+ },
928
+ {
929
+ x: -800,
930
+ y: -1330,
931
+ z: 1500
932
+ }
933
+ ] },
934
+ init_pose: {
935
+ position: {
936
+ x: 0,
937
+ y: 0,
938
+ z: 0
939
+ },
940
+ orientation: {
941
+ x: 0,
942
+ y: 0,
943
+ z: 0,
944
+ w: 1
945
+ }
946
+ },
947
+ id: "box"
948
+ },
949
+ {
950
+ convex_hull: { vertices: [
951
+ {
952
+ x: -800,
953
+ y: -1330,
954
+ z: -1820
955
+ },
956
+ {
957
+ x: -800,
958
+ y: 1330,
959
+ z: -1820
960
+ },
961
+ {
962
+ x: -800,
963
+ y: 1330,
964
+ z: 1500
965
+ },
966
+ {
967
+ x: -800,
968
+ y: -1330,
969
+ z: 1500
970
+ }
971
+ ] },
972
+ init_pose: {
973
+ position: {
974
+ x: 0,
975
+ y: 0,
976
+ z: 0
977
+ },
978
+ orientation: {
979
+ x: 0,
980
+ y: 0,
981
+ z: 0,
982
+ w: 1
983
+ }
984
+ },
985
+ id: "box"
986
+ },
987
+ {
988
+ convex_hull: { vertices: [
989
+ {
990
+ x: 1650,
991
+ y: 1330,
992
+ z: 1500
993
+ },
994
+ {
995
+ x: -800,
996
+ y: 1330,
997
+ z: 1500
998
+ },
999
+ {
1000
+ x: -800,
1001
+ y: -1330,
1002
+ z: 1500
1003
+ },
1004
+ {
1005
+ x: 1650,
1006
+ y: -1330,
1007
+ z: 1500
1008
+ }
1009
+ ] },
1010
+ init_pose: {
1011
+ position: {
1012
+ x: 0,
1013
+ y: 0,
1014
+ z: 0
1015
+ },
1016
+ orientation: {
1017
+ x: 0,
1018
+ y: 0,
1019
+ z: 0,
1020
+ w: 1
1021
+ }
1022
+ },
1023
+ id: "box"
1024
+ },
1025
+ {
1026
+ convex_hull: { vertices: [
1027
+ {
1028
+ x: 1650,
1029
+ y: 1330,
1030
+ z: 1500
1031
+ },
1032
+ {
1033
+ x: -800,
1034
+ y: 1330,
1035
+ z: 1500
1036
+ },
1037
+ {
1038
+ x: -800,
1039
+ y: 1330,
1040
+ z: -1820
1041
+ },
1042
+ {
1043
+ x: 1650,
1044
+ y: 1330,
1045
+ z: -1820
1046
+ }
1047
+ ] },
1048
+ init_pose: {
1049
+ position: {
1050
+ x: 0,
1051
+ y: 0,
1052
+ z: 0
1053
+ },
1054
+ orientation: {
1055
+ x: 0,
1056
+ y: 0,
1057
+ z: 0,
1058
+ w: 1
1059
+ }
1060
+ },
1061
+ id: "box"
1062
+ },
1063
+ {
1064
+ convex_hull: { vertices: [
1065
+ {
1066
+ x: 1650,
1067
+ y: 1330,
1068
+ z: 1500
1069
+ },
1070
+ {
1071
+ x: 1650,
1072
+ y: -1330,
1073
+ z: 1500
1074
+ },
1075
+ {
1076
+ x: 1650,
1077
+ y: -1330,
1078
+ z: -1820
1079
+ },
1080
+ {
1081
+ x: 1650,
1082
+ y: 1330,
1083
+ z: -1820
1084
+ }
1085
+ ] },
1086
+ init_pose: {
1087
+ position: {
1088
+ x: 0,
1089
+ y: 0,
1090
+ z: 0
1091
+ },
1092
+ orientation: {
1093
+ x: 0,
1094
+ y: 0,
1095
+ z: 0,
1096
+ w: 1
1097
+ }
1098
+ },
1099
+ id: "box"
1100
+ }
1101
+ ] },
1102
+ init_pose: {
1103
+ position: {
1104
+ x: 0,
1105
+ y: 0,
1106
+ z: 0
1107
+ },
1108
+ orientation: {
1109
+ x: 0,
1110
+ y: 0,
1111
+ z: 0,
1112
+ w: 1
1113
+ }
1114
+ },
1115
+ id: "Cell workzone"
1116
+ },
1117
+ motion_group_uid: 1
1118
+ },
1119
+ {
1120
+ id: 2,
1121
+ priority: 0,
1122
+ geometry: {
1123
+ convex_hull: { vertices: [
1124
+ {
1125
+ x: 1650,
1126
+ y: 1330,
1127
+ z: -1850
1128
+ },
1129
+ {
1130
+ x: 865,
1131
+ y: 1330,
1132
+ z: -1850
1133
+ },
1134
+ {
1135
+ x: 865,
1136
+ y: -720,
1137
+ z: -1850
1138
+ },
1139
+ {
1140
+ x: 1650,
1141
+ y: -720,
1142
+ z: -1850
1143
+ },
1144
+ {
1145
+ x: 1650,
1146
+ y: 1330,
1147
+ z: -920
1148
+ },
1149
+ {
1150
+ x: 865,
1151
+ y: 1330,
1152
+ z: -920
1153
+ },
1154
+ {
1155
+ x: 865,
1156
+ y: -720,
1157
+ z: -920
1158
+ },
1159
+ {
1160
+ x: 1650,
1161
+ y: -720,
1162
+ z: -920
1163
+ }
1164
+ ] },
1165
+ init_pose: {
1166
+ position: {
1167
+ x: 0,
1168
+ y: 0,
1169
+ z: 0
1170
+ },
1171
+ orientation: {
1172
+ x: 0,
1173
+ y: 0,
1174
+ z: 0,
1175
+ w: 1
1176
+ }
1177
+ },
1178
+ id: "Transport"
1179
+ },
1180
+ motion_group_uid: 1
1181
+ },
1182
+ {
1183
+ id: 3,
1184
+ priority: 0,
1185
+ geometry: {
1186
+ convex_hull: { vertices: [
1187
+ {
1188
+ x: 1650,
1189
+ y: 1330,
1190
+ z: -600
1191
+ },
1192
+ {
1193
+ x: 865,
1194
+ y: 1330,
1195
+ z: -600
1196
+ },
1197
+ {
1198
+ x: 865,
1199
+ y: 430,
1200
+ z: -600
1201
+ },
1202
+ {
1203
+ x: 1650,
1204
+ y: 430,
1205
+ z: -600
1206
+ },
1207
+ {
1208
+ x: 1650,
1209
+ y: 1330,
1210
+ z: -1250
1211
+ },
1212
+ {
1213
+ x: 865,
1214
+ y: 1330,
1215
+ z: -1250
1216
+ },
1217
+ {
1218
+ x: 865,
1219
+ y: 430,
1220
+ z: -1250
1221
+ },
1222
+ {
1223
+ x: 1650,
1224
+ y: 430,
1225
+ z: -1250
1226
+ }
1227
+ ] },
1228
+ init_pose: {
1229
+ position: {
1230
+ x: 0,
1231
+ y: 0,
1232
+ z: 0
1233
+ },
1234
+ orientation: {
1235
+ x: 0,
1236
+ y: 0,
1237
+ z: 0,
1238
+ w: 1
1239
+ }
1240
+ },
1241
+ id: "Tunel"
1242
+ },
1243
+ motion_group_uid: 1
1244
+ },
1245
+ {
1246
+ id: 4,
1247
+ priority: 0,
1248
+ geometry: {
1249
+ convex_hull: { vertices: [
1250
+ {
1251
+ x: 1650,
1252
+ y: -760,
1253
+ z: -440
1254
+ },
1255
+ {
1256
+ x: 900,
1257
+ y: -760,
1258
+ z: -440
1259
+ },
1260
+ {
1261
+ x: 900,
1262
+ y: -1330,
1263
+ z: -440
1264
+ },
1265
+ {
1266
+ x: 1650,
1267
+ y: -1330,
1268
+ z: -440
1269
+ },
1270
+ {
1271
+ x: 1650,
1272
+ y: -760,
1273
+ z: -1800
1274
+ },
1275
+ {
1276
+ x: 900,
1277
+ y: -760,
1278
+ z: -1800
1279
+ },
1280
+ {
1281
+ x: 900,
1282
+ y: -1330,
1283
+ z: -1800
1284
+ },
1285
+ {
1286
+ x: 1650,
1287
+ y: -1330,
1288
+ z: -1800
1289
+ }
1290
+ ] },
1291
+ init_pose: {
1292
+ position: {
1293
+ x: 0,
1294
+ y: 0,
1295
+ z: 0
1296
+ },
1297
+ orientation: {
1298
+ x: 0,
1299
+ y: 0,
1300
+ z: 0,
1301
+ w: 1
1302
+ }
1303
+ },
1304
+ id: "Fanuc controller"
1305
+ },
1306
+ motion_group_uid: 1
1307
+ },
1308
+ {
1309
+ id: 6,
1310
+ priority: 0,
1311
+ geometry: {
1312
+ convex_hull: { vertices: [
1313
+ {
1314
+ x: -200,
1315
+ y: -200,
1316
+ z: -1900
1317
+ },
1318
+ {
1319
+ x: 200,
1320
+ y: -200,
1321
+ z: -1900
1322
+ },
1323
+ {
1324
+ x: 200,
1325
+ y: 200,
1326
+ z: -1900
1327
+ },
1328
+ {
1329
+ x: -200,
1330
+ y: 200,
1331
+ z: -1900
1332
+ },
1333
+ {
1334
+ x: -200,
1335
+ y: -200,
1336
+ z: -350
1337
+ },
1338
+ {
1339
+ x: 200,
1340
+ y: -200,
1341
+ z: -350
1342
+ },
1343
+ {
1344
+ x: 200,
1345
+ y: 200,
1346
+ z: -350
1347
+ },
1348
+ {
1349
+ x: -200,
1350
+ y: 200,
1351
+ z: -350
1352
+ }
1353
+ ] },
1354
+ init_pose: {
1355
+ position: {
1356
+ x: 0,
1357
+ y: 0,
1358
+ z: 0
1359
+ },
1360
+ orientation: {
1361
+ x: 0,
1362
+ y: 0,
1363
+ z: 0,
1364
+ w: 1
1365
+ }
1366
+ },
1367
+ id: "Robot base"
1368
+ },
1369
+ motion_group_uid: 1
1370
+ }
1371
+ ],
1372
+ robot_model_geometries: [
1373
+ {
1374
+ link_index: 1,
1375
+ geometry: {
1376
+ sphere: { radius: 270 },
1377
+ init_pose: {
1378
+ position: {
1379
+ x: -70,
1380
+ y: -70,
1381
+ z: -50
1382
+ },
1383
+ orientation: {
1384
+ x: 0,
1385
+ y: 0,
1386
+ z: 0,
1387
+ w: 1
1388
+ }
1389
+ },
1390
+ id: "link1_sphere"
1391
+ }
1392
+ },
1393
+ {
1394
+ link_index: 2,
1395
+ geometry: {
1396
+ capsule: {
1397
+ radius: 160,
1398
+ cylinder_height: 800
1399
+ },
1400
+ init_pose: {
1401
+ position: {
1402
+ x: -450,
1403
+ y: 40,
1404
+ z: 170
1405
+ },
1406
+ orientation: {
1407
+ x: 0,
1408
+ y: -Math.SQRT1_2,
1409
+ z: 0,
1410
+ w: Math.SQRT1_2
1411
+ }
1412
+ },
1413
+ id: "link2_capsule"
1414
+ }
1415
+ },
1416
+ {
1417
+ link_index: 3,
1418
+ geometry: {
1419
+ sphere: { radius: 270 },
1420
+ init_pose: {
1421
+ position: {
1422
+ x: -110,
1423
+ y: 10,
1424
+ z: -100
1425
+ },
1426
+ orientation: {
1427
+ x: 0,
1428
+ y: 0,
1429
+ z: 0,
1430
+ w: 1
1431
+ }
1432
+ },
1433
+ id: "link3_sphere"
1434
+ }
1435
+ },
1436
+ {
1437
+ link_index: 4,
1438
+ geometry: {
1439
+ capsule: {
1440
+ radius: 110,
1441
+ cylinder_height: 600
1442
+ },
1443
+ init_pose: {
1444
+ position: {
1445
+ x: 0,
1446
+ y: 300,
1447
+ z: 40
1448
+ },
1449
+ orientation: {
1450
+ x: -Math.SQRT1_2,
1451
+ y: 0,
1452
+ z: 0,
1453
+ w: Math.SQRT1_2
1454
+ }
1455
+ },
1456
+ id: "link4_capsule"
1457
+ }
1458
+ },
1459
+ {
1460
+ link_index: 5,
1461
+ geometry: {
1462
+ sphere: { radius: 75 },
1463
+ init_pose: {
1464
+ position: {
1465
+ x: 0,
1466
+ y: 0,
1467
+ z: -50
1468
+ },
1469
+ orientation: {
1470
+ x: 0,
1471
+ y: 0,
1472
+ z: 0,
1473
+ w: 1
1474
+ }
1475
+ },
1476
+ id: "link5_sphere"
1477
+ }
1478
+ }
1479
+ ],
1480
+ tool_geometries: []
1481
+ };
1482
+ }
1483
+ },
1484
+ {
1485
+ method: "GET",
1486
+ path: "/cells/:cellId/coordinate-systems",
1487
+ handle() {
1488
+ return { coordinatesystems: [{
1489
+ coordinate_system: "",
1490
+ name: "world",
1491
+ reference_uid: "",
1492
+ position: {
1493
+ x: 0,
1494
+ y: 0,
1495
+ z: 0
1496
+ },
1497
+ rotation: {
1498
+ angles: [
1499
+ 0,
1500
+ 0,
1501
+ 0
1502
+ ],
1503
+ type: "ROTATION_VECTOR"
1504
+ }
1505
+ }] };
1506
+ }
1507
+ },
1508
+ {
1509
+ method: "GET",
1510
+ path: "/cells/:cellId/motion-groups/:motionGroupId/tcps",
1511
+ handle() {
1512
+ return { tcps: [{
1513
+ id: "Flange",
1514
+ readable_name: "Default-Flange",
1515
+ position: {
1516
+ x: 0,
1517
+ y: 0,
1518
+ z: 0
1519
+ },
1520
+ rotation: {
1521
+ angles: [
1522
+ 0,
1523
+ 0,
1524
+ 0,
1525
+ 0
1526
+ ],
1527
+ type: "ROTATION_VECTOR"
1528
+ }
1529
+ }, {
1530
+ id: "complex-tcp-position",
1531
+ readable_name: "Complex TCP Position",
1532
+ position: {
1533
+ x: -200,
1534
+ y: 300,
1535
+ z: 150
1536
+ },
1537
+ rotation: {
1538
+ angles: [
1539
+ -.12139440409113832,
1540
+ -.06356210998212003,
1541
+ -.2023240068185639,
1542
+ 0
1543
+ ],
1544
+ type: "ROTATION_VECTOR"
1545
+ }
1546
+ }] };
1547
+ }
1548
+ }
1549
+ ];
1550
+ const method = config.method?.toUpperCase() || "GET";
1551
+ const path = `/cells${config.url?.split("/cells")[1]?.split("?")[0]}`;
1552
+ for (const handler of apiHandlers) {
1553
+ const match = pathToRegexp.match(handler.path)(path || "");
1554
+ if (method === handler.method && match) {
1555
+ const json = handler.handle();
1556
+ return {
1557
+ status: 200,
1558
+ statusText: "Success",
1559
+ data: JSON.stringify(json),
1560
+ headers: {},
1561
+ config,
1562
+ request: { responseURL: config.url }
1563
+ };
1564
+ }
1565
+ }
1566
+ throw new AxiosError(`No mock handler matched this request: ${method} ${path}`, "404", config);
1567
+ }
1568
+ handleWebsocketConnection(socket) {
1569
+ this.connections.push(socket);
1570
+ setTimeout(() => {
1571
+ socket.dispatchEvent(new Event("open"));
1572
+ console.log("Websocket connection opened from", socket.url);
1573
+ if (socket.url.includes("/state-stream")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify(defaultMotionState) }));
1574
+ if (socket.url.includes("/move-joint")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify({ result: {
1575
+ motion_group: "0@ur",
1576
+ state: {
1577
+ controller: "ur",
1578
+ operation_mode: "OPERATION_MODE_AUTO",
1579
+ safety_state: "SAFETY_STATE_NORMAL",
1580
+ timestamp: "2024-09-18T12:48:26.096266444Z",
1581
+ velocity_override: 100,
1582
+ motion_groups: [{
1583
+ motion_group: "0@ur",
1584
+ controller: "ur",
1585
+ joint_position: { joints: [
1586
+ 1.3492152690887451,
1587
+ -1.5659207105636597,
1588
+ 1.6653711795806885,
1589
+ -1.0991662740707397,
1590
+ -1.829018235206604,
1591
+ 1.264623761177063
1592
+ ] },
1593
+ joint_velocity: { joints: [
1594
+ 0,
1595
+ 0,
1596
+ 0,
1597
+ 0,
1598
+ 0,
1599
+ 0
1600
+ ] },
1601
+ flange_pose: {
1602
+ position: {
1603
+ x: 6.437331889439328,
1604
+ y: -628.4123774830913,
1605
+ z: 577.0569957147832
1606
+ },
1607
+ orientation: {
1608
+ x: -1.683333649797158,
1609
+ y: -1.9783363827298732,
1610
+ z: -.4928031860165713
1611
+ },
1612
+ coordinate_system: ""
1613
+ },
1614
+ tcp_pose: {
1615
+ position: {
1616
+ x: 6.437331889439328,
1617
+ y: -628.4123774830913,
1618
+ z: 577.0569957147832
1619
+ },
1620
+ orientation: {
1621
+ x: -1.683333649797158,
1622
+ y: -1.9783363827298732,
1623
+ z: -.4928031860165713
1624
+ },
1625
+ coordinate_system: "",
1626
+ tcp: "Flange"
1627
+ },
1628
+ velocity: {
1629
+ linear: {
1630
+ x: 0,
1631
+ y: 0,
1632
+ z: 0
1633
+ },
1634
+ angular: {
1635
+ x: -0,
1636
+ y: 0,
1637
+ z: 0
1638
+ },
1639
+ coordinate_system: ""
1640
+ },
1641
+ force: {
1642
+ force: {
1643
+ x: 0,
1644
+ y: 0,
1645
+ z: 0
1646
+ },
1647
+ moment: {
1648
+ x: 0,
1649
+ y: 0,
1650
+ z: 0
1651
+ },
1652
+ coordinate_system: ""
1653
+ },
1654
+ joint_limit_reached: { limit_reached: [
1655
+ false,
1656
+ false,
1657
+ false,
1658
+ false,
1659
+ false,
1660
+ false
1661
+ ] },
1662
+ joint_current: { joints: [
1663
+ 0,
1664
+ 0,
1665
+ 0,
1666
+ 0,
1667
+ 0,
1668
+ 0
1669
+ ] },
1670
+ sequence_number: "671259"
1671
+ }],
1672
+ sequence_number: "671259"
1673
+ },
1674
+ movement_state: "MOVEMENT_STATE_MOVING"
1675
+ } }) }));
1676
+ if (socket.url.includes("/move-tcp")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify({ result: {
1677
+ motion_group: "0@ur",
1678
+ state: {
1679
+ controller: "ur",
1680
+ operation_mode: "OPERATION_MODE_AUTO",
1681
+ safety_state: "SAFETY_STATE_NORMAL",
1682
+ timestamp: "2024-09-18T12:43:12.188335774Z",
1683
+ velocity_override: 100,
1684
+ motion_groups: [{
1685
+ motion_group: "0@ur",
1686
+ controller: "ur",
1687
+ joint_position: { joints: [
1688
+ 1.3352527618408203,
1689
+ -1.5659207105636597,
1690
+ 1.6653711795806885,
1691
+ -1.110615611076355,
1692
+ -1.829018235206604,
1693
+ 1.264623761177063
1694
+ ] },
1695
+ joint_velocity: { joints: [
1696
+ 0,
1697
+ 0,
1698
+ 0,
1699
+ 0,
1700
+ 0,
1701
+ 0
1702
+ ] },
1703
+ flange_pose: {
1704
+ position: {
1705
+ x: -2.763015284002938,
1706
+ y: -630.2151479701106,
1707
+ z: 577.524509114342
1708
+ },
1709
+ orientation: {
1710
+ x: -1.704794877102097,
1711
+ y: -1.9722372952861567,
1712
+ z: -.4852079204210754
1713
+ },
1714
+ coordinate_system: ""
1715
+ },
1716
+ tcp_pose: {
1717
+ position: {
1718
+ x: -2.763015284002938,
1719
+ y: -630.2151479701106,
1720
+ z: 577.524509114342
1721
+ },
1722
+ orientation: {
1723
+ x: -1.704794877102097,
1724
+ y: -1.9722372952861567,
1725
+ z: -.4852079204210754
1726
+ },
1727
+ coordinate_system: "",
1728
+ tcp: "Flange"
1729
+ },
1730
+ velocity: {
1731
+ linear: {
1732
+ x: 0,
1733
+ y: 0,
1734
+ z: 0
1735
+ },
1736
+ angular: {
1737
+ x: -0,
1738
+ y: 0,
1739
+ z: 0
1740
+ },
1741
+ coordinate_system: ""
1742
+ },
1743
+ force: {
1744
+ force: {
1745
+ x: 0,
1746
+ y: 0,
1747
+ z: 0
1748
+ },
1749
+ moment: {
1750
+ x: 0,
1751
+ y: 0,
1752
+ z: 0
1753
+ },
1754
+ coordinate_system: ""
1755
+ },
1756
+ joint_limit_reached: { limit_reached: [
1757
+ false,
1758
+ false,
1759
+ false,
1760
+ false,
1761
+ false,
1762
+ false
1763
+ ] },
1764
+ joint_current: { joints: [
1765
+ 0,
1766
+ 0,
1767
+ 0,
1768
+ 0,
1769
+ 0,
1770
+ 0
1771
+ ] },
1772
+ sequence_number: "627897"
1773
+ }],
1774
+ sequence_number: "627897"
1775
+ },
1776
+ movement_state: "MOVEMENT_STATE_MOVING"
1777
+ } }) }));
1778
+ }, 10);
1779
+ }
1780
+ handleWebsocketMessage(socket, message) {
1781
+ console.log(`Received message on ${socket.url}`, message);
1782
+ }
2281
1783
  };
1784
+ const defaultMotionState = { result: {
1785
+ state: {
1786
+ motion_group: "0@universalrobots-ur5e",
1787
+ controller: "universalrobots-ur5e",
1788
+ joint_position: { joints: [
1789
+ 1.1699999570846558,
1790
+ -1.5700000524520874,
1791
+ 1.3600000143051147,
1792
+ 1.0299999713897705,
1793
+ 1.2899999618530273,
1794
+ 1.2799999713897705
1795
+ ] },
1796
+ joint_velocity: { joints: [
1797
+ 0,
1798
+ 0,
1799
+ 0,
1800
+ 0,
1801
+ 0,
1802
+ 0
1803
+ ] },
1804
+ flange_pose: {
1805
+ position: {
1806
+ x: 1.3300010259703043,
1807
+ y: -409.2680714682808,
1808
+ z: 531.0203477065281
1809
+ },
1810
+ orientation: {
1811
+ x: 1.7564919306270736,
1812
+ y: -1.7542521568325058,
1813
+ z: .7326972590614671
1814
+ },
1815
+ coordinate_system: ""
1816
+ },
1817
+ tcp_pose: {
1818
+ position: {
1819
+ x: 1.3300010259703043,
1820
+ y: -409.2680714682808,
1821
+ z: 531.0203477065281
1822
+ },
1823
+ orientation: {
1824
+ x: 1.7564919306270736,
1825
+ y: -1.7542521568325058,
1826
+ z: .7326972590614671
1827
+ },
1828
+ coordinate_system: "",
1829
+ tcp: "Flange"
1830
+ },
1831
+ velocity: {
1832
+ linear: {
1833
+ x: 0,
1834
+ y: 0,
1835
+ z: 0
1836
+ },
1837
+ angular: {
1838
+ x: 0,
1839
+ y: 0,
1840
+ z: 0
1841
+ },
1842
+ coordinate_system: ""
1843
+ },
1844
+ force: {
1845
+ force: {
1846
+ x: 0,
1847
+ y: 0,
1848
+ z: 0
1849
+ },
1850
+ moment: {
1851
+ x: 0,
1852
+ y: 0,
1853
+ z: 0
1854
+ },
1855
+ coordinate_system: ""
1856
+ },
1857
+ joint_limit_reached: { limit_reached: [
1858
+ false,
1859
+ false,
1860
+ false,
1861
+ false,
1862
+ false,
1863
+ false
1864
+ ] },
1865
+ joint_current: { joints: [
1866
+ 0,
1867
+ 0,
1868
+ 0,
1869
+ 0,
1870
+ 0,
1871
+ 0
1872
+ ] },
1873
+ sequence_number: "1"
1874
+ },
1875
+ tcp_pose: {
1876
+ position: {
1877
+ x: 302.90748476115556,
1878
+ y: -152.87065869452337,
1879
+ z: 424.0454619321661
1880
+ },
1881
+ orientation: {
1882
+ x: 2.3403056115045353,
1883
+ y: -1.1706836379431356,
1884
+ z: .9772511964246311
1885
+ },
1886
+ coordinate_system: "",
1887
+ tcp: "Flange"
1888
+ }
1889
+ } };
2282
1890
 
2283
- // src/lib/v1/NovaClient.ts
1891
+ //#endregion
1892
+ //#region src/lib/v1/NovaClient.ts
1893
+ /**
1894
+ * Client for connecting to a Nova instance and controlling robots.
1895
+ */
2284
1896
  var NovaClient = class {
2285
- constructor(config) {
2286
- this.authPromise = null;
2287
- this.accessToken = null;
2288
- var _a;
2289
- const cellId = (_a = config.cellId) != null ? _a : "cell";
2290
- this.config = __spreadValues({
2291
- cellId
2292
- }, config);
2293
- this.accessToken = config.accessToken || availableStorage.getString("wbjs.access_token") || null;
2294
- if (this.config.instanceUrl === "https://mock.example.com") {
2295
- this.mock = new MockNovaInstance();
2296
- }
2297
- const axiosInstance = axios2.create({
2298
- baseURL: urlJoin(this.config.instanceUrl, "/api/v1"),
2299
- // TODO - backend needs to set proper CORS headers for this
2300
- headers: typeof window !== "undefined" && window.location.origin.includes("localhost") ? {} : {
2301
- // Identify the client to the backend for logging purposes
2302
- "X-Wandelbots-Client": "Wandelbots-Nova-JS-SDK"
2303
- }
2304
- });
2305
- axiosInstance.interceptors.request.use((request) => __async(this, null, function* () {
2306
- if (!request.headers.Authorization) {
2307
- if (this.accessToken) {
2308
- request.headers.Authorization = `Bearer ${this.accessToken}`;
2309
- } else if (this.config.username && this.config.password) {
2310
- request.headers.Authorization = `Basic ${btoa(`${config.username}:${config.password}`)}`;
2311
- }
2312
- }
2313
- return request;
2314
- }));
2315
- if (typeof window !== "undefined") {
2316
- axiosInstance.interceptors.response.use(
2317
- (r) => r,
2318
- (error) => __async(this, null, function* () {
2319
- var _a2, _b;
2320
- if (isAxiosError(error)) {
2321
- if (((_a2 = error.response) == null ? void 0 : _a2.status) === 401) {
2322
- try {
2323
- yield this.renewAuthentication();
2324
- if (error.config) {
2325
- if (this.accessToken) {
2326
- error.config.headers.Authorization = `Bearer ${this.accessToken}`;
2327
- } else {
2328
- delete error.config.headers.Authorization;
2329
- }
2330
- return axiosInstance.request(error.config);
2331
- }
2332
- } catch (err) {
2333
- return Promise.reject(err);
2334
- }
2335
- } else if (((_b = error.response) == null ? void 0 : _b.status) === 503) {
2336
- const res = yield fetch(window.location.href);
2337
- if (res.status === 503) {
2338
- window.location.reload();
2339
- }
2340
- }
2341
- }
2342
- return Promise.reject(error);
2343
- })
2344
- );
2345
- }
2346
- this.api = new NovaCellAPIClient(cellId, __spreadProps(__spreadValues({}, config), {
2347
- basePath: urlJoin(this.config.instanceUrl, "/api/v1"),
2348
- isJsonMime: (mime) => {
2349
- return mime === "application/json";
2350
- },
2351
- baseOptions: __spreadValues(__spreadValues({}, this.mock ? {
2352
- adapter: (config2) => {
2353
- return this.mock.handleAPIRequest(config2);
2354
- }
2355
- } : {}), config.baseOptions),
2356
- axiosInstance
2357
- }));
2358
- }
2359
- renewAuthentication() {
2360
- return __async(this, null, function* () {
2361
- if (this.authPromise) {
2362
- return;
2363
- }
2364
- this.authPromise = loginWithAuth0(this.config.instanceUrl);
2365
- try {
2366
- this.accessToken = yield this.authPromise;
2367
- if (this.accessToken) {
2368
- availableStorage.setString("wbjs.access_token", this.accessToken);
2369
- } else {
2370
- availableStorage.delete("wbjs.access_token");
2371
- }
2372
- } finally {
2373
- this.authPromise = null;
2374
- }
2375
- });
2376
- }
2377
- makeWebsocketURL(path) {
2378
- const url = new URL(
2379
- urlJoin(
2380
- this.config.instanceUrl,
2381
- `/api/v1/cells/${this.config.cellId}`,
2382
- path
2383
- )
2384
- );
2385
- url.protocol = url.protocol.replace("http", "ws");
2386
- url.protocol = url.protocol.replace("https", "wss");
2387
- if (this.accessToken) {
2388
- url.searchParams.append("token", this.accessToken);
2389
- } else if (this.config.username && this.config.password) {
2390
- url.username = this.config.username;
2391
- url.password = this.config.password;
2392
- }
2393
- return url.toString();
2394
- }
2395
- /**
2396
- * Retrieve an AutoReconnectingWebsocket to the given path on the Nova instance.
2397
- * If you explicitly want to reconnect an existing websocket, call `reconnect`
2398
- * on the returned object.
2399
- */
2400
- openReconnectingWebsocket(path) {
2401
- return new AutoReconnectingWebsocket(this.makeWebsocketURL(path), {
2402
- mock: this.mock
2403
- });
2404
- }
2405
- /**
2406
- * Connect to the motion state websocket(s) for a given motion group
2407
- */
2408
- connectMotionStream(motionGroupId) {
2409
- return __async(this, null, function* () {
2410
- return yield MotionStreamConnection.open(this, motionGroupId);
2411
- });
2412
- }
2413
- /**
2414
- * Connect to the jogging websocket(s) for a given motion group
2415
- */
2416
- connectJogger(motionGroupId) {
2417
- return __async(this, null, function* () {
2418
- return yield JoggerConnection.open(this, motionGroupId);
2419
- });
2420
- }
2421
- connectMotionGroups(motionGroupIds) {
2422
- return __async(this, null, function* () {
2423
- const { instances } = yield this.api.controller.listControllers();
2424
- return Promise.all(
2425
- motionGroupIds.map(
2426
- (motionGroupId) => ConnectedMotionGroup.connect(this, motionGroupId, instances)
2427
- )
2428
- );
2429
- });
2430
- }
2431
- connectMotionGroup(motionGroupId) {
2432
- return __async(this, null, function* () {
2433
- const motionGroups = yield this.connectMotionGroups([motionGroupId]);
2434
- return motionGroups[0];
2435
- });
2436
- }
1897
+ constructor(config) {
1898
+ this.authPromise = null;
1899
+ this.accessToken = null;
1900
+ const cellId = config.cellId ?? "cell";
1901
+ this.config = {
1902
+ cellId,
1903
+ ...config
1904
+ };
1905
+ this.accessToken = config.accessToken || availableStorage.getString("wbjs.access_token") || null;
1906
+ if (this.config.instanceUrl === "https://mock.example.com") this.mock = new MockNovaInstance();
1907
+ const axiosInstance = axios.create({
1908
+ baseURL: urlJoin(this.config.instanceUrl, "/api/v1"),
1909
+ headers: typeof window !== "undefined" && window.location.origin.includes("localhost") ? {} : { "X-Wandelbots-Client": "Wandelbots-Nova-JS-SDK" }
1910
+ });
1911
+ axiosInstance.interceptors.request.use(async (request) => {
1912
+ if (!request.headers.Authorization) {
1913
+ if (this.accessToken) request.headers.Authorization = `Bearer ${this.accessToken}`;
1914
+ else if (this.config.username && this.config.password) request.headers.Authorization = `Basic ${btoa(`${config.username}:${config.password}`)}`;
1915
+ }
1916
+ return request;
1917
+ });
1918
+ if (typeof window !== "undefined") axiosInstance.interceptors.response.use((r) => r, async (error) => {
1919
+ if (isAxiosError(error)) {
1920
+ if (error.response?.status === 401) try {
1921
+ await this.renewAuthentication();
1922
+ if (error.config) {
1923
+ if (this.accessToken) error.config.headers.Authorization = `Bearer ${this.accessToken}`;
1924
+ else delete error.config.headers.Authorization;
1925
+ return axiosInstance.request(error.config);
1926
+ }
1927
+ } catch (err) {
1928
+ return Promise.reject(err);
1929
+ }
1930
+ else if (error.response?.status === 503) {
1931
+ if ((await fetch(window.location.href)).status === 503) window.location.reload();
1932
+ }
1933
+ }
1934
+ return Promise.reject(error);
1935
+ });
1936
+ this.api = new NovaCellAPIClient(cellId, {
1937
+ ...config,
1938
+ basePath: urlJoin(this.config.instanceUrl, "/api/v1"),
1939
+ isJsonMime: (mime) => {
1940
+ return mime === "application/json";
1941
+ },
1942
+ baseOptions: {
1943
+ ...this.mock ? { adapter: (config$1) => {
1944
+ return this.mock.handleAPIRequest(config$1);
1945
+ } } : {},
1946
+ ...config.baseOptions
1947
+ },
1948
+ axiosInstance
1949
+ });
1950
+ }
1951
+ async renewAuthentication() {
1952
+ if (this.authPromise) return;
1953
+ this.authPromise = loginWithAuth0(this.config.instanceUrl);
1954
+ try {
1955
+ this.accessToken = await this.authPromise;
1956
+ if (this.accessToken) availableStorage.setString("wbjs.access_token", this.accessToken);
1957
+ else availableStorage.delete("wbjs.access_token");
1958
+ } finally {
1959
+ this.authPromise = null;
1960
+ }
1961
+ }
1962
+ makeWebsocketURL(path) {
1963
+ const url = new URL(urlJoin(this.config.instanceUrl, `/api/v1/cells/${this.config.cellId}`, path));
1964
+ url.protocol = url.protocol.replace("http", "ws");
1965
+ url.protocol = url.protocol.replace("https", "wss");
1966
+ if (this.accessToken) url.searchParams.append("token", this.accessToken);
1967
+ else if (this.config.username && this.config.password) {
1968
+ url.username = this.config.username;
1969
+ url.password = this.config.password;
1970
+ }
1971
+ return url.toString();
1972
+ }
1973
+ /**
1974
+ * Retrieve an AutoReconnectingWebsocket to the given path on the Nova instance.
1975
+ * If you explicitly want to reconnect an existing websocket, call `reconnect`
1976
+ * on the returned object.
1977
+ */
1978
+ openReconnectingWebsocket(path) {
1979
+ return new AutoReconnectingWebsocket(this.makeWebsocketURL(path), { mock: this.mock });
1980
+ }
1981
+ /**
1982
+ * Connect to the motion state websocket(s) for a given motion group
1983
+ */
1984
+ async connectMotionStream(motionGroupId) {
1985
+ return await MotionStreamConnection.open(this, motionGroupId);
1986
+ }
1987
+ /**
1988
+ * Connect to the jogging websocket(s) for a given motion group
1989
+ */
1990
+ async connectJogger(motionGroupId) {
1991
+ return await JoggerConnection.open(this, motionGroupId);
1992
+ }
1993
+ async connectMotionGroups(motionGroupIds) {
1994
+ const { instances } = await this.api.controller.listControllers();
1995
+ return Promise.all(motionGroupIds.map((motionGroupId) => ConnectedMotionGroup.connect(this, motionGroupId, instances)));
1996
+ }
1997
+ async connectMotionGroup(motionGroupId) {
1998
+ return (await this.connectMotionGroups([motionGroupId]))[0];
1999
+ }
2437
2000
  };
2438
2001
 
2439
- // src/lib/v1/ProgramStateConnection.ts
2440
- import { AxiosError as AxiosError2 } from "axios";
2441
- import { makeAutoObservable as makeAutoObservable3, runInAction as runInAction3 } from "mobx";
2442
- var ProgramState = /* @__PURE__ */ ((ProgramState2) => {
2443
- ProgramState2["NotStarted"] = "not started";
2444
- ProgramState2["Running"] = "running";
2445
- ProgramState2["Stopped"] = "stopped";
2446
- ProgramState2["Failed"] = "failed";
2447
- ProgramState2["Completed"] = "completed";
2448
- return ProgramState2;
2449
- })(ProgramState || {});
2002
+ //#endregion
2003
+ //#region src/lib/v1/ProgramStateConnection.ts
2004
+ let ProgramState = /* @__PURE__ */ function(ProgramState$1) {
2005
+ ProgramState$1["NotStarted"] = "not started";
2006
+ ProgramState$1["Running"] = "running";
2007
+ ProgramState$1["Stopped"] = "stopped";
2008
+ ProgramState$1["Failed"] = "failed";
2009
+ ProgramState$1["Completed"] = "completed";
2010
+ return ProgramState$1;
2011
+ }({});
2012
+ /**
2013
+ * Interface for running Wandelscript programs on the Nova instance and
2014
+ * tracking their progress and output
2015
+ */
2450
2016
  var ProgramStateConnection = class {
2451
- constructor(nova) {
2452
- this.nova = nova;
2453
- this.currentProgram = {};
2454
- this.logs = [];
2455
- this.executionState = "idle";
2456
- this.currentlyExecutingProgramRunnerId = null;
2457
- makeAutoObservable3(this, {}, { autoBind: true });
2458
- this.programStateSocket = nova.openReconnectingWebsocket(`/programs/state`);
2459
- this.programStateSocket.addEventListener("message", (ev) => {
2460
- const msg = tryParseJson(ev.data);
2461
- if (!msg) {
2462
- console.error("Failed to parse program state message", ev.data);
2463
- return;
2464
- }
2465
- if (msg.type === "update") {
2466
- this.handleProgramStateMessage(msg);
2467
- }
2468
- });
2469
- }
2470
- /** Handle a program state update from the backend */
2471
- handleProgramStateMessage(msg) {
2472
- return __async(this, null, function* () {
2473
- var _a;
2474
- const { runner } = msg;
2475
- if (runner.id !== this.currentlyExecutingProgramRunnerId) return;
2476
- if (runner.state === "failed" /* Failed */) {
2477
- try {
2478
- const runnerState = yield this.nova.api.program.getProgramRunner(
2479
- runner.id
2480
- );
2481
- const stdout = runnerState.stdout;
2482
- if (stdout) {
2483
- this.log(stdout);
2484
- }
2485
- this.logError(
2486
- `Program runner ${runner.id} failed with error: ${runnerState.error}
2487
- ${runnerState.traceback}`
2488
- );
2489
- } catch (err) {
2490
- this.logError(
2491
- `Failed to retrieve results for program ${runner.id}: ${err}`
2492
- );
2493
- }
2494
- this.currentProgram.state = "failed" /* Failed */;
2495
- this.gotoIdleState();
2496
- } else if (runner.state === "stopped" /* Stopped */) {
2497
- try {
2498
- const runnerState = yield this.nova.api.program.getProgramRunner(
2499
- runner.id
2500
- );
2501
- const stdout = runnerState.stdout;
2502
- if (stdout) {
2503
- this.log(stdout);
2504
- }
2505
- this.currentProgram.state = "stopped" /* Stopped */;
2506
- this.log(`Program runner ${runner.id} stopped`);
2507
- } catch (err) {
2508
- this.logError(
2509
- `Failed to retrieve results for program ${runner.id}: ${err}`
2510
- );
2511
- }
2512
- this.gotoIdleState();
2513
- } else if (runner.state === "completed" /* Completed */) {
2514
- try {
2515
- const runnerState = yield this.nova.api.program.getProgramRunner(
2516
- runner.id
2517
- );
2518
- const stdout = runnerState.stdout;
2519
- if (stdout) {
2520
- this.log(stdout);
2521
- }
2522
- this.log(
2523
- `Program runner ${runner.id} finished successfully in ${(_a = runner.execution_time) == null ? void 0 : _a.toFixed(2)} seconds`
2524
- );
2525
- this.currentProgram.state = "completed" /* Completed */;
2526
- } catch (err) {
2527
- this.logError(
2528
- `Failed to retrieve results for program ${runner.id}: ${err}`
2529
- );
2530
- }
2531
- this.gotoIdleState();
2532
- } else if (runner.state === "running" /* Running */) {
2533
- this.currentProgram.state = "running" /* Running */;
2534
- this.log(`Program runner ${runner.id} now running`);
2535
- } else if (runner.state !== "not started" /* NotStarted */) {
2536
- console.error(runner);
2537
- this.logError(
2538
- `Program runner ${runner.id} entered unexpected state: ${runner.state}`
2539
- );
2540
- this.currentProgram.state = "not started" /* NotStarted */;
2541
- this.gotoIdleState();
2542
- }
2543
- });
2544
- }
2545
- /** Call when a program is no longer executing */
2546
- gotoIdleState() {
2547
- runInAction3(() => {
2548
- this.executionState = "idle";
2549
- });
2550
- this.currentlyExecutingProgramRunnerId = null;
2551
- }
2552
- executeProgram(wandelscript, initial_state, activeRobot) {
2553
- return __async(this, null, function* () {
2554
- this.currentProgram = {
2555
- wandelscript,
2556
- state: "not started" /* NotStarted */
2557
- };
2558
- const { currentProgram: openProgram } = this;
2559
- if (!openProgram) return;
2560
- runInAction3(() => {
2561
- this.executionState = "starting";
2562
- });
2563
- if (activeRobot) {
2564
- try {
2565
- yield this.nova.api.motionGroupJogging.stopJogging(
2566
- activeRobot.motionGroupId
2567
- );
2568
- } catch (err) {
2569
- console.error(err);
2570
- }
2571
- }
2572
- const trimmedCode = openProgram.wandelscript.replaceAll(/^\s*$/gm, "");
2573
- try {
2574
- const programRunnerRef = yield this.nova.api.program.createProgramRunner(
2575
- {
2576
- code: trimmedCode,
2577
- initial_state,
2578
- // @ts-expect-error legacy code - check if param still used
2579
- default_robot: activeRobot == null ? void 0 : activeRobot.wandelscriptIdentifier
2580
- },
2581
- {
2582
- headers: {
2583
- "Content-Type": "application/json"
2584
- }
2585
- }
2586
- );
2587
- this.log(`Created program runner ${programRunnerRef.id}"`);
2588
- runInAction3(() => {
2589
- this.executionState = "executing";
2590
- });
2591
- this.currentlyExecutingProgramRunnerId = programRunnerRef.id;
2592
- } catch (error) {
2593
- if (error instanceof AxiosError2 && error.response && error.request) {
2594
- this.logError(
2595
- `${error.response.status} ${error.response.statusText} from ${error.response.config.url} ${JSON.stringify(error.response.data)}`
2596
- );
2597
- } else {
2598
- this.logError(JSON.stringify(error));
2599
- }
2600
- runInAction3(() => {
2601
- this.executionState = "idle";
2602
- });
2603
- }
2604
- });
2605
- }
2606
- stopProgram() {
2607
- return __async(this, null, function* () {
2608
- if (!this.currentlyExecutingProgramRunnerId) return;
2609
- runInAction3(() => {
2610
- this.executionState = "stopping";
2611
- });
2612
- try {
2613
- yield this.nova.api.program.stopProgramRunner(
2614
- this.currentlyExecutingProgramRunnerId
2615
- );
2616
- } catch (err) {
2617
- runInAction3(() => {
2618
- this.executionState = "executing";
2619
- });
2620
- throw err;
2621
- }
2622
- });
2623
- }
2624
- reset() {
2625
- this.currentProgram = {};
2626
- }
2627
- log(message) {
2628
- console.log(message);
2629
- this.logs.push({
2630
- timestamp: Date.now(),
2631
- message
2632
- });
2633
- }
2634
- logError(message) {
2635
- console.log(message);
2636
- this.logs.push({
2637
- timestamp: Date.now(),
2638
- message,
2639
- level: "error"
2640
- });
2641
- }
2642
- };
2643
- export {
2644
- ConnectedMotionGroup,
2645
- JoggerConnection,
2646
- MotionStreamConnection,
2647
- NovaCellAPIClient,
2648
- NovaClient,
2649
- ProgramState,
2650
- ProgramStateConnection,
2651
- getLatestTrajectories
2017
+ constructor(nova) {
2018
+ this.nova = nova;
2019
+ this.currentProgram = {};
2020
+ this.logs = [];
2021
+ this.executionState = "idle";
2022
+ this.currentlyExecutingProgramRunnerId = null;
2023
+ makeAutoObservable(this, {}, { autoBind: true });
2024
+ this.programStateSocket = nova.openReconnectingWebsocket(`/programs/state`);
2025
+ this.programStateSocket.addEventListener("message", (ev) => {
2026
+ const msg = tryParseJson(ev.data);
2027
+ if (!msg) {
2028
+ console.error("Failed to parse program state message", ev.data);
2029
+ return;
2030
+ }
2031
+ if (msg.type === "update") this.handleProgramStateMessage(msg);
2032
+ });
2033
+ }
2034
+ /** Handle a program state update from the backend */
2035
+ async handleProgramStateMessage(msg) {
2036
+ const { runner } = msg;
2037
+ if (runner.id !== this.currentlyExecutingProgramRunnerId) return;
2038
+ if (runner.state === ProgramState.Failed) {
2039
+ try {
2040
+ const runnerState = await this.nova.api.program.getProgramRunner(runner.id);
2041
+ const stdout = runnerState.stdout;
2042
+ if (stdout) this.log(stdout);
2043
+ this.logError(`Program runner ${runner.id} failed with error: ${runnerState.error}\n${runnerState.traceback}`);
2044
+ } catch (err) {
2045
+ this.logError(`Failed to retrieve results for program ${runner.id}: ${err}`);
2046
+ }
2047
+ this.currentProgram.state = ProgramState.Failed;
2048
+ this.gotoIdleState();
2049
+ } else if (runner.state === ProgramState.Stopped) {
2050
+ try {
2051
+ const stdout = (await this.nova.api.program.getProgramRunner(runner.id)).stdout;
2052
+ if (stdout) this.log(stdout);
2053
+ this.currentProgram.state = ProgramState.Stopped;
2054
+ this.log(`Program runner ${runner.id} stopped`);
2055
+ } catch (err) {
2056
+ this.logError(`Failed to retrieve results for program ${runner.id}: ${err}`);
2057
+ }
2058
+ this.gotoIdleState();
2059
+ } else if (runner.state === ProgramState.Completed) {
2060
+ try {
2061
+ const stdout = (await this.nova.api.program.getProgramRunner(runner.id)).stdout;
2062
+ if (stdout) this.log(stdout);
2063
+ this.log(`Program runner ${runner.id} finished successfully in ${runner.execution_time?.toFixed(2)} seconds`);
2064
+ this.currentProgram.state = ProgramState.Completed;
2065
+ } catch (err) {
2066
+ this.logError(`Failed to retrieve results for program ${runner.id}: ${err}`);
2067
+ }
2068
+ this.gotoIdleState();
2069
+ } else if (runner.state === ProgramState.Running) {
2070
+ this.currentProgram.state = ProgramState.Running;
2071
+ this.log(`Program runner ${runner.id} now running`);
2072
+ } else if (runner.state !== ProgramState.NotStarted) {
2073
+ console.error(runner);
2074
+ this.logError(`Program runner ${runner.id} entered unexpected state: ${runner.state}`);
2075
+ this.currentProgram.state = ProgramState.NotStarted;
2076
+ this.gotoIdleState();
2077
+ }
2078
+ }
2079
+ /** Call when a program is no longer executing */
2080
+ gotoIdleState() {
2081
+ runInAction(() => {
2082
+ this.executionState = "idle";
2083
+ });
2084
+ this.currentlyExecutingProgramRunnerId = null;
2085
+ }
2086
+ async executeProgram(wandelscript, initial_state, activeRobot) {
2087
+ this.currentProgram = {
2088
+ wandelscript,
2089
+ state: ProgramState.NotStarted
2090
+ };
2091
+ const { currentProgram: openProgram } = this;
2092
+ if (!openProgram) return;
2093
+ runInAction(() => {
2094
+ this.executionState = "starting";
2095
+ });
2096
+ if (activeRobot) try {
2097
+ await this.nova.api.motionGroupJogging.stopJogging(activeRobot.motionGroupId);
2098
+ } catch (err) {
2099
+ console.error(err);
2100
+ }
2101
+ const trimmedCode = openProgram.wandelscript.replaceAll(/^\s*$/gm, "");
2102
+ try {
2103
+ const programRunnerRef = await this.nova.api.program.createProgramRunner({
2104
+ code: trimmedCode,
2105
+ initial_state,
2106
+ default_robot: activeRobot?.wandelscriptIdentifier
2107
+ }, { headers: { "Content-Type": "application/json" } });
2108
+ this.log(`Created program runner ${programRunnerRef.id}"`);
2109
+ runInAction(() => {
2110
+ this.executionState = "executing";
2111
+ });
2112
+ this.currentlyExecutingProgramRunnerId = programRunnerRef.id;
2113
+ } catch (error) {
2114
+ if (error instanceof AxiosError && error.response && error.request) this.logError(`${error.response.status} ${error.response.statusText} from ${error.response.config.url} ${JSON.stringify(error.response.data)}`);
2115
+ else this.logError(JSON.stringify(error));
2116
+ runInAction(() => {
2117
+ this.executionState = "idle";
2118
+ });
2119
+ }
2120
+ }
2121
+ async stopProgram() {
2122
+ if (!this.currentlyExecutingProgramRunnerId) return;
2123
+ runInAction(() => {
2124
+ this.executionState = "stopping";
2125
+ });
2126
+ try {
2127
+ await this.nova.api.program.stopProgramRunner(this.currentlyExecutingProgramRunnerId);
2128
+ } catch (err) {
2129
+ runInAction(() => {
2130
+ this.executionState = "executing";
2131
+ });
2132
+ throw err;
2133
+ }
2134
+ }
2135
+ reset() {
2136
+ this.currentProgram = {};
2137
+ }
2138
+ log(message) {
2139
+ console.log(message);
2140
+ this.logs.push({
2141
+ timestamp: Date.now(),
2142
+ message
2143
+ });
2144
+ }
2145
+ logError(message) {
2146
+ console.log(message);
2147
+ this.logs.push({
2148
+ timestamp: Date.now(),
2149
+ message,
2150
+ level: "error"
2151
+ });
2152
+ }
2652
2153
  };
2154
+
2155
+ //#endregion
2156
+ export { ConnectedMotionGroup, JoggerConnection, MotionStreamConnection, NovaCellAPIClient, NovaClient, ProgramState, ProgramStateConnection, getLatestTrajectories };
2653
2157
  //# sourceMappingURL=index.js.map