@wandelbots/nova-js 3.2.0 → 3.3.0

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 (104) hide show
  1. package/README.md +32 -136
  2. package/dist/AutoReconnectingWebsocket-Qcrbm3Kb.d.cts +69 -0
  3. package/dist/AutoReconnectingWebsocket-Qcrbm3Kb.d.cts.map +1 -0
  4. package/dist/AutoReconnectingWebsocket-dHe-kceU.d.mts +69 -0
  5. package/dist/AutoReconnectingWebsocket-dHe-kceU.d.mts.map +1 -0
  6. package/dist/LoginWithAuth0-CBD9BXXz.cjs +264 -0
  7. package/dist/LoginWithAuth0-CBD9BXXz.cjs.map +1 -0
  8. package/dist/LoginWithAuth0-wQB-Sol1.mjs +217 -0
  9. package/dist/LoginWithAuth0-wQB-Sol1.mjs.map +1 -0
  10. package/dist/NovaClient-B8XM3OPO.mjs +2057 -0
  11. package/dist/NovaClient-B8XM3OPO.mjs.map +1 -0
  12. package/dist/NovaClient-CV7ooIkD.d.cts +349 -0
  13. package/dist/NovaClient-CV7ooIkD.d.cts.map +1 -0
  14. package/dist/NovaClient-D2EItmiH.cjs +2137 -0
  15. package/dist/NovaClient-D2EItmiH.cjs.map +1 -0
  16. package/dist/NovaClient-qJnHcx2s.d.mts +349 -0
  17. package/dist/NovaClient-qJnHcx2s.d.mts.map +1 -0
  18. package/dist/index.cjs +42 -386
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +73 -0
  21. package/dist/index.d.cts.map +1 -0
  22. package/dist/index.d.mts +73 -0
  23. package/dist/index.d.mts.map +1 -0
  24. package/dist/index.mjs +36 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/lib/v1/index.cjs +190 -2940
  27. package/dist/lib/v1/index.cjs.map +1 -1
  28. package/dist/lib/v1/index.d.cts +62 -0
  29. package/dist/lib/v1/index.d.cts.map +1 -0
  30. package/dist/lib/v1/index.d.mts +62 -0
  31. package/dist/lib/v1/index.d.mts.map +1 -0
  32. package/dist/lib/v1/index.mjs +182 -0
  33. package/dist/lib/v1/index.mjs.map +1 -0
  34. package/dist/lib/v2/index.cjs +1821 -1468
  35. package/dist/lib/v2/index.cjs.map +1 -1
  36. package/dist/lib/v2/index.d.cts +118 -0
  37. package/dist/lib/v2/index.d.cts.map +1 -0
  38. package/dist/lib/v2/index.d.mts +118 -0
  39. package/dist/lib/v2/index.d.mts.map +1 -0
  40. package/dist/lib/v2/index.mjs +1822 -0
  41. package/dist/lib/v2/index.mjs.map +1 -0
  42. package/package.json +21 -19
  43. package/src/LoginWithAuth0.ts +12 -12
  44. package/src/index.ts +2 -0
  45. package/src/lib/converters.ts +5 -23
  46. package/src/lib/v1/MotionStreamConnection.ts +0 -1
  47. package/src/lib/v1/NovaClient.ts +18 -0
  48. package/src/lib/v1/index.ts +6 -0
  49. package/src/lib/v1/mock/MockNovaInstance.ts +0 -1
  50. package/src/lib/v1/wandelscriptUtils.ts +22 -0
  51. package/src/lib/v2/NovaClient.ts +14 -7
  52. package/src/lib/v2/index.ts +1 -0
  53. package/src/lib/v2/mock/MockNovaInstance.ts +411 -21
  54. package/src/lib/v2/wandelscriptUtils.ts +27 -0
  55. package/dist/LoginWithAuth0.d.ts +0 -7
  56. package/dist/LoginWithAuth0.d.ts.map +0 -1
  57. package/dist/chunk-B2C22PTK.js +0 -53
  58. package/dist/chunk-B2C22PTK.js.map +0 -1
  59. package/dist/chunk-I3PUV6ZD.js +0 -286
  60. package/dist/chunk-I3PUV6ZD.js.map +0 -1
  61. package/dist/index.d.ts +0 -6
  62. package/dist/index.d.ts.map +0 -1
  63. package/dist/index.js +0 -60
  64. package/dist/index.js.map +0 -1
  65. package/dist/lib/AutoReconnectingWebsocket.d.ts +0 -43
  66. package/dist/lib/AutoReconnectingWebsocket.d.ts.map +0 -1
  67. package/dist/lib/availableStorage.d.ts +0 -15
  68. package/dist/lib/availableStorage.d.ts.map +0 -1
  69. package/dist/lib/converters.d.ts +0 -26
  70. package/dist/lib/converters.d.ts.map +0 -1
  71. package/dist/lib/errorHandling.d.ts +0 -15
  72. package/dist/lib/errorHandling.d.ts.map +0 -1
  73. package/dist/lib/v1/ConnectedMotionGroup.d.ts +0 -77
  74. package/dist/lib/v1/ConnectedMotionGroup.d.ts.map +0 -1
  75. package/dist/lib/v1/JoggerConnection.d.ts +0 -94
  76. package/dist/lib/v1/JoggerConnection.d.ts.map +0 -1
  77. package/dist/lib/v1/MotionStreamConnection.d.ts +0 -26
  78. package/dist/lib/v1/MotionStreamConnection.d.ts.map +0 -1
  79. package/dist/lib/v1/NovaCellAPIClient.d.ts +0 -68
  80. package/dist/lib/v1/NovaCellAPIClient.d.ts.map +0 -1
  81. package/dist/lib/v1/NovaClient.d.ts +0 -67
  82. package/dist/lib/v1/NovaClient.d.ts.map +0 -1
  83. package/dist/lib/v1/ProgramStateConnection.d.ts +0 -57
  84. package/dist/lib/v1/ProgramStateConnection.d.ts.map +0 -1
  85. package/dist/lib/v1/getLatestTrajectories.d.ts +0 -4
  86. package/dist/lib/v1/getLatestTrajectories.d.ts.map +0 -1
  87. package/dist/lib/v1/index.d.ts +0 -9
  88. package/dist/lib/v1/index.d.ts.map +0 -1
  89. package/dist/lib/v1/index.js +0 -2653
  90. package/dist/lib/v1/index.js.map +0 -1
  91. package/dist/lib/v1/mock/MockNovaInstance.d.ts +0 -13
  92. package/dist/lib/v1/mock/MockNovaInstance.d.ts.map +0 -1
  93. package/dist/lib/v1/motionStateUpdate.d.ts +0 -4
  94. package/dist/lib/v1/motionStateUpdate.d.ts.map +0 -1
  95. package/dist/lib/v2/NovaCellAPIClient.d.ts +0 -62
  96. package/dist/lib/v2/NovaCellAPIClient.d.ts.map +0 -1
  97. package/dist/lib/v2/NovaClient.d.ts +0 -60
  98. package/dist/lib/v2/NovaClient.d.ts.map +0 -1
  99. package/dist/lib/v2/index.d.ts +0 -4
  100. package/dist/lib/v2/index.d.ts.map +0 -1
  101. package/dist/lib/v2/index.js +0 -1196
  102. package/dist/lib/v2/index.js.map +0 -1
  103. package/dist/lib/v2/mock/MockNovaInstance.d.ts +0 -13
  104. package/dist/lib/v2/mock/MockNovaInstance.d.ts.map +0 -1
@@ -0,0 +1,2137 @@
1
+ const require_LoginWithAuth0 = require('./LoginWithAuth0-CBD9BXXz.cjs');
2
+ let axios = require("axios");
3
+ axios = require_LoginWithAuth0.__toESM(axios);
4
+ let url_join = require("url-join");
5
+ url_join = require_LoginWithAuth0.__toESM(url_join);
6
+ let mobx = require("mobx");
7
+ let three = require("three");
8
+ three = require_LoginWithAuth0.__toESM(three);
9
+ let three_src_math_Vector3_js = require("three/src/math/Vector3.js");
10
+ let __wandelbots_nova_api_v1 = require("@wandelbots/nova-api/v1");
11
+ let path_to_regexp = require("path-to-regexp");
12
+ path_to_regexp = require_LoginWithAuth0.__toESM(path_to_regexp);
13
+
14
+ //#region src/lib/converters.ts
15
+ /** Try to parse something as JSON; return undefined if we can't */
16
+ function tryParseJson(json) {
17
+ try {
18
+ return JSON.parse(json);
19
+ } catch {
20
+ return;
21
+ }
22
+ }
23
+ /** Try to turn something into JSON; return undefined if we can't */
24
+ function tryStringifyJson(json) {
25
+ try {
26
+ return JSON.stringify(json);
27
+ } catch {
28
+ return;
29
+ }
30
+ }
31
+ /**
32
+ * Converts object parameters to query string.
33
+ * e.g. { a: "1", b: "2" } => "?a=1&b=2"
34
+ * {} => ""
35
+ */
36
+ function makeUrlQueryString(obj) {
37
+ const str = new URLSearchParams(obj).toString();
38
+ return str ? `?${str}` : "";
39
+ }
40
+ /** Convert radians to degrees */
41
+ function radiansToDegrees(radians) {
42
+ return radians * (180 / Math.PI);
43
+ }
44
+ /** Convert degrees to radians */
45
+ function degreesToRadians(degrees) {
46
+ return degrees * (Math.PI / 180);
47
+ }
48
+ /**
49
+ * Check for coordinate system id equivalence, accounting for the "world" default
50
+ * on empty/undefined values.
51
+ */
52
+ function isSameCoordinateSystem(firstCoordSystem, secondCoordSystem) {
53
+ if (!firstCoordSystem) firstCoordSystem = "world";
54
+ if (!secondCoordSystem) secondCoordSystem = "world";
55
+ return firstCoordSystem === secondCoordSystem;
56
+ }
57
+ /**
58
+ * Helpful const for converting {x, y, z} to [x, y, z] and vice versa
59
+ */
60
+ const XYZ_TO_VECTOR = {
61
+ x: 0,
62
+ y: 1,
63
+ z: 2
64
+ };
65
+
66
+ //#endregion
67
+ //#region src/lib/v1/wandelscriptUtils.ts
68
+ /**
69
+ * Convert a Pose object representing a motion group position
70
+ * into a string which represents that pose in Wandelscript.
71
+ */
72
+ function poseToWandelscriptString(pose) {
73
+ const position = [
74
+ pose.position.x,
75
+ pose.position.y,
76
+ pose.position.z
77
+ ];
78
+ const orientation = [
79
+ pose.orientation?.x ?? 0,
80
+ pose.orientation?.y ?? 0,
81
+ pose.orientation?.z ?? 0
82
+ ];
83
+ const positionValues = position.map((v) => v.toFixed(1));
84
+ const rotationValues = orientation.map((v) => v.toFixed(4));
85
+ return `(${positionValues.concat(rotationValues).join(", ")})`;
86
+ }
87
+
88
+ //#endregion
89
+ //#region src/lib/v1/motionStateUpdate.ts
90
+ function jointValuesEqual(oldJointValues, newJointValues, changeDeltaThreshold) {
91
+ if (newJointValues.length !== oldJointValues.length) return true;
92
+ for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) if (Math.abs(newJointValues[jointIndex] - oldJointValues[jointIndex]) > changeDeltaThreshold) return false;
93
+ return true;
94
+ }
95
+ function tcpPoseEqual(oldTcp, newTcp, changeDeltaThreshold) {
96
+ if (oldTcp === void 0 && newTcp || oldTcp && newTcp === void 0) return false;
97
+ if (oldTcp === void 0 || newTcp === void 0) return true;
98
+ let changedDelta = 0;
99
+ changedDelta += Math.abs(oldTcp.orientation.x - newTcp.orientation.x);
100
+ changedDelta += Math.abs(oldTcp.orientation.y - newTcp.orientation.y);
101
+ changedDelta += Math.abs(oldTcp.orientation.z - newTcp.orientation.z);
102
+ changedDelta += Math.abs(oldTcp.position.x - newTcp.position.x);
103
+ changedDelta += Math.abs(oldTcp.position.y - newTcp.position.y);
104
+ changedDelta += Math.abs(oldTcp.position.z - newTcp.position.z);
105
+ if (changedDelta > changeDeltaThreshold) return false;
106
+ return oldTcp.coordinate_system === newTcp.coordinate_system && oldTcp.tcp === newTcp.tcp;
107
+ }
108
+
109
+ //#endregion
110
+ //#region src/lib/v1/ConnectedMotionGroup.ts
111
+ const MOTION_DELTA_THRESHOLD$1 = 1e-4;
112
+ /**
113
+ * Store representing the current state of a connected motion group.
114
+ */
115
+ var ConnectedMotionGroup = class ConnectedMotionGroup {
116
+ static async connect(nova, motionGroupId, controllers) {
117
+ const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
118
+ const controller = controllers.find((c) => c.controller === controllerId);
119
+ const motionGroup = controller?.physical_motion_groups.find((mg) => mg.motion_group === motionGroupId);
120
+ if (!controller || !motionGroup) throw new Error(`Controller ${controllerId} or motion group ${motionGroupId} not found`);
121
+ const motionStateSocket = nova.openReconnectingWebsocket(`/motion-groups/${motionGroupId}/state-stream`);
122
+ const firstMessage = await motionStateSocket.firstMessage();
123
+ const initialMotionState = tryParseJson(firstMessage.data)?.result;
124
+ if (!initialMotionState) throw new Error(`Unable to parse initial motion state message ${firstMessage.data}`);
125
+ console.log(`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\n `, initialMotionState);
126
+ const isVirtual = (await nova.api.controller.getRobotController(controller.controller)).configuration.kind === "VirtualController";
127
+ const mounting = await (async () => {
128
+ try {
129
+ return await nova.api.motionGroupInfos.getMounting(motionGroup.motion_group);
130
+ } catch (err) {
131
+ console.error(`Error fetching mounting for ${motionGroup.motion_group}`, err);
132
+ return null;
133
+ }
134
+ })();
135
+ const controllerStateSocket = nova.openReconnectingWebsocket(`/controllers/${controller.controller}/state-stream?response_rate=1000`);
136
+ const firstControllerMessage = await controllerStateSocket.firstMessage();
137
+ const initialControllerState = tryParseJson(firstControllerMessage.data)?.result;
138
+ if (!initialControllerState) throw new Error(`Unable to parse initial controller state message ${firstControllerMessage.data}`);
139
+ console.log(`Connected controller state websocket to controller ${controller.controller}. Initial state:\n `, initialControllerState);
140
+ const { tcps } = await nova.api.motionGroupInfos.listTcps(motionGroupId);
141
+ return new ConnectedMotionGroup(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, await nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId), await nova.api.motionGroupInfos.getSafetySetup(motionGroupId), mounting, initialControllerState, controllerStateSocket);
142
+ }
143
+ constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup, mounting, initialControllerState, controllerStateSocket) {
144
+ this.nova = nova;
145
+ this.controller = controller;
146
+ this.motionGroup = motionGroup;
147
+ this.initialMotionState = initialMotionState;
148
+ this.motionStateSocket = motionStateSocket;
149
+ this.isVirtual = isVirtual;
150
+ this.tcps = tcps;
151
+ this.motionGroupSpecification = motionGroupSpecification;
152
+ this.safetySetup = safetySetup;
153
+ this.mounting = mounting;
154
+ this.initialControllerState = initialControllerState;
155
+ this.controllerStateSocket = controllerStateSocket;
156
+ this.connectedJoggingCartesianSocket = null;
157
+ this.connectedJoggingJointsSocket = null;
158
+ this.joggingVelocity = 10;
159
+ this.activationState = "inactive";
160
+ this.rapidlyChangingMotionState = initialMotionState;
161
+ this.controllerState = initialControllerState;
162
+ controllerStateSocket.addEventListener("message", (event) => {
163
+ const data = tryParseJson(event.data)?.result;
164
+ if (!data) return;
165
+ (0, mobx.runInAction)(() => {
166
+ this.controllerState = data;
167
+ });
168
+ });
169
+ motionStateSocket.addEventListener("message", (event) => {
170
+ const motionStateResponse = tryParseJson(event.data)?.result;
171
+ if (!motionStateResponse) throw new Error(`Failed to get motion state for ${this.motionGroupId}: ${event.data}`);
172
+ if (!jointValuesEqual(this.rapidlyChangingMotionState.state.joint_position.joints, motionStateResponse.state.joint_position.joints, MOTION_DELTA_THRESHOLD$1)) (0, mobx.runInAction)(() => {
173
+ this.rapidlyChangingMotionState.state = motionStateResponse.state;
174
+ });
175
+ if (!tcpPoseEqual(this.rapidlyChangingMotionState.tcp_pose, motionStateResponse.tcp_pose, MOTION_DELTA_THRESHOLD$1)) (0, mobx.runInAction)(() => {
176
+ this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
177
+ });
178
+ });
179
+ (0, mobx.makeAutoObservable)(this);
180
+ }
181
+ get motionGroupId() {
182
+ return this.motionGroup.motion_group;
183
+ }
184
+ get controllerId() {
185
+ return this.controller.controller;
186
+ }
187
+ get modelFromController() {
188
+ return this.motionGroup.model_from_controller;
189
+ }
190
+ get wandelscriptIdentifier() {
191
+ const num = this.motionGroupId.split("@")[0];
192
+ return `${this.controllerId.replaceAll("-", "_")}_${num}`;
193
+ }
194
+ /** Jogging velocity in radians for rotation and joint movement */
195
+ get joggingVelocityRads() {
196
+ return this.joggingVelocity * Math.PI / 180;
197
+ }
198
+ get joints() {
199
+ return this.initialMotionState.state.joint_position.joints.map((_, i) => {
200
+ return { index: i };
201
+ });
202
+ }
203
+ get dhParameters() {
204
+ return this.motionGroupSpecification.dh_parameters;
205
+ }
206
+ get safetyZones() {
207
+ return this.safetySetup.safety_zones;
208
+ }
209
+ /** Gets the robot mounting position offset in 3D viz coordinates */
210
+ get mountingPosition() {
211
+ if (!this.mounting) return [
212
+ 0,
213
+ 0,
214
+ 0
215
+ ];
216
+ return [
217
+ this.mounting.pose.position.x / 1e3,
218
+ this.mounting.pose.position.y / 1e3,
219
+ this.mounting.pose.position.z / 1e3
220
+ ];
221
+ }
222
+ /** Gets the robot mounting position rotation in 3D viz coordinates */
223
+ get mountingQuaternion() {
224
+ const rotationVector = new three.Vector3(this.mounting?.pose.orientation?.x || 0, this.mounting?.pose.orientation?.y || 0, this.mounting?.pose.orientation?.z || 0);
225
+ const magnitude = rotationVector.length();
226
+ const axis = rotationVector.normalize();
227
+ return new three.Quaternion().setFromAxisAngle(axis, magnitude);
228
+ }
229
+ /**
230
+ * Whether the controller is currently in a safety state
231
+ * corresponding to an emergency stop
232
+ */
233
+ get isEstopActive() {
234
+ return ["SAFETY_STATE_ROBOT_EMERGENCY_STOP", "SAFETY_STATE_DEVICE_EMERGENCY_STOP"].includes(this.controllerState.safety_state);
235
+ }
236
+ /**
237
+ * Whether the controller is in a safety state
238
+ * that may be non-functional for robot pad purposes
239
+ */
240
+ get isMoveableSafetyState() {
241
+ return ["SAFETY_STATE_NORMAL", "SAFETY_STATE_REDUCED"].includes(this.controllerState.safety_state);
242
+ }
243
+ /**
244
+ * Whether the controller is in an operation mode that allows movement
245
+ */
246
+ get isMoveableOperationMode() {
247
+ return [
248
+ "OPERATION_MODE_AUTO",
249
+ "OPERATION_MODE_MANUAL",
250
+ "OPERATION_MODE_MANUAL_T1",
251
+ "OPERATION_MODE_MANUAL_T2"
252
+ ].includes(this.controllerState.operation_mode);
253
+ }
254
+ /**
255
+ * Whether the robot is currently active and can be moved, based on the
256
+ * safety state, operation mode and servo toggle activation state.
257
+ */
258
+ get canBeMoved() {
259
+ return this.isMoveableSafetyState && this.isMoveableOperationMode && this.activationState === "active";
260
+ }
261
+ async deactivate() {
262
+ if (this.activationState !== "active") {
263
+ console.error("Tried to deactivate while already deactivating");
264
+ return;
265
+ }
266
+ (0, mobx.runInAction)(() => {
267
+ this.activationState = "deactivating";
268
+ });
269
+ try {
270
+ await this.nova.api.controller.setDefaultMode(this.controllerId, "MODE_MONITOR");
271
+ (0, mobx.runInAction)(() => {
272
+ this.activationState = "inactive";
273
+ });
274
+ } catch (err) {
275
+ (0, mobx.runInAction)(() => {
276
+ this.activationState = "active";
277
+ });
278
+ throw err;
279
+ }
280
+ }
281
+ async activate() {
282
+ if (this.activationState !== "inactive") {
283
+ console.error("Tried to activate while already activating");
284
+ return;
285
+ }
286
+ (0, mobx.runInAction)(() => {
287
+ this.activationState = "activating";
288
+ });
289
+ try {
290
+ await this.nova.api.controller.setDefaultMode(this.controllerId, "MODE_CONTROL");
291
+ (0, mobx.runInAction)(() => {
292
+ this.activationState = "active";
293
+ });
294
+ } catch (err) {
295
+ (0, mobx.runInAction)(() => {
296
+ this.activationState = "inactive";
297
+ });
298
+ throw err;
299
+ }
300
+ }
301
+ toggleActivation() {
302
+ if (this.activationState === "inactive") this.activate();
303
+ else if (this.activationState === "active") this.deactivate();
304
+ }
305
+ dispose() {
306
+ this.motionStateSocket.close();
307
+ if (this.connectedJoggingCartesianSocket) this.connectedJoggingCartesianSocket.close();
308
+ if (this.connectedJoggingJointsSocket) this.connectedJoggingJointsSocket.close();
309
+ }
310
+ setJoggingVelocity(velocity) {
311
+ this.joggingVelocity = velocity;
312
+ }
313
+ };
314
+
315
+ //#endregion
316
+ //#region src/lib/v1/JoggerConnection.ts
317
+ var JoggerConnection = class JoggerConnection {
318
+ static async open(nova, motionGroupId, opts = {}) {
319
+ return new JoggerConnection(await nova.connectMotionStream(motionGroupId), opts);
320
+ }
321
+ constructor(motionStream, opts = {}) {
322
+ this.motionStream = motionStream;
323
+ this.opts = opts;
324
+ this.cartesianWebsocket = null;
325
+ this.jointWebsocket = null;
326
+ this.cartesianJoggingOpts = {};
327
+ }
328
+ get motionGroupId() {
329
+ return this.motionStream.motionGroupId;
330
+ }
331
+ get nova() {
332
+ return this.motionStream.nova;
333
+ }
334
+ get numJoints() {
335
+ return this.motionStream.joints.length;
336
+ }
337
+ get activeJoggingMode() {
338
+ if (this.cartesianWebsocket) return "cartesian";
339
+ if (this.jointWebsocket) return "joint";
340
+ return "increment";
341
+ }
342
+ get activeWebsocket() {
343
+ return this.cartesianWebsocket || this.jointWebsocket;
344
+ }
345
+ async stop() {
346
+ if (this.cartesianWebsocket) this.cartesianWebsocket.sendJson({
347
+ motion_group: this.motionGroupId,
348
+ position_direction: {
349
+ x: 0,
350
+ y: 0,
351
+ z: 0
352
+ },
353
+ rotation_direction: {
354
+ x: 0,
355
+ y: 0,
356
+ z: 0
357
+ },
358
+ position_velocity: 0,
359
+ rotation_velocity: 0,
360
+ tcp: this.cartesianJoggingOpts.tcpId,
361
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
362
+ });
363
+ if (this.jointWebsocket) this.jointWebsocket.sendJson({
364
+ motion_group: this.motionGroupId,
365
+ joint_velocities: new Array(this.numJoints).fill(0)
366
+ });
367
+ }
368
+ dispose() {
369
+ if (this.cartesianWebsocket) this.cartesianWebsocket.dispose();
370
+ if (this.jointWebsocket) this.jointWebsocket.dispose();
371
+ }
372
+ setJoggingMode(mode, cartesianJoggingOpts) {
373
+ console.log("Setting jogging mode to", mode);
374
+ if (cartesianJoggingOpts) {
375
+ if (JSON.stringify(this.cartesianJoggingOpts) !== JSON.stringify(cartesianJoggingOpts)) {
376
+ if (this.cartesianWebsocket) {
377
+ this.cartesianWebsocket.dispose();
378
+ this.cartesianWebsocket = null;
379
+ }
380
+ }
381
+ this.cartesianJoggingOpts = cartesianJoggingOpts;
382
+ }
383
+ if (mode !== "cartesian" && this.cartesianWebsocket) {
384
+ this.cartesianWebsocket.dispose();
385
+ this.cartesianWebsocket = null;
386
+ }
387
+ if (mode !== "joint" && this.jointWebsocket) {
388
+ this.jointWebsocket.dispose();
389
+ this.jointWebsocket = null;
390
+ }
391
+ if (mode === "cartesian" && !this.cartesianWebsocket) {
392
+ this.cartesianWebsocket = this.nova.openReconnectingWebsocket(`/motion-groups/move-tcp`);
393
+ this.cartesianWebsocket.addEventListener("message", (ev) => {
394
+ const data = tryParseJson(ev.data);
395
+ if (data && "error" in data) if (this.opts.onError) this.opts.onError(ev.data);
396
+ else throw new Error(ev.data);
397
+ });
398
+ }
399
+ if (mode === "joint" && !this.jointWebsocket) {
400
+ this.jointWebsocket = this.nova.openReconnectingWebsocket(`/motion-groups/move-joint`);
401
+ this.jointWebsocket.addEventListener("message", (ev) => {
402
+ const data = tryParseJson(ev.data);
403
+ if (data && "error" in data) if (this.opts.onError) this.opts.onError(ev.data);
404
+ else throw new Error(ev.data);
405
+ });
406
+ }
407
+ }
408
+ /**
409
+ * Start rotation of a single robot joint at the specified velocity
410
+ */
411
+ async startJointRotation({ joint, direction, velocityRadsPerSec }) {
412
+ if (!this.jointWebsocket) throw new Error("Joint jogging websocket not connected; call setJoggingMode first");
413
+ const jointVelocities = new Array(this.numJoints).fill(0);
414
+ jointVelocities[joint] = direction === "-" ? -velocityRadsPerSec : velocityRadsPerSec;
415
+ this.jointWebsocket.sendJson({
416
+ motion_group: this.motionGroupId,
417
+ joint_velocities: jointVelocities
418
+ });
419
+ }
420
+ /**
421
+ * Start the TCP moving along a specified axis at a given velocity
422
+ */
423
+ async startTCPTranslation({ axis, direction, velocityMmPerSec }) {
424
+ if (!this.cartesianWebsocket) throw new Error("Cartesian jogging websocket not connected; call setJoggingMode first");
425
+ const zeroVector = {
426
+ x: 0,
427
+ y: 0,
428
+ z: 0
429
+ };
430
+ const joggingVector = Object.assign({}, zeroVector);
431
+ joggingVector[axis] = direction === "-" ? -1 : 1;
432
+ this.cartesianWebsocket.sendJson({
433
+ motion_group: this.motionGroupId,
434
+ position_direction: joggingVector,
435
+ rotation_direction: zeroVector,
436
+ position_velocity: velocityMmPerSec,
437
+ rotation_velocity: 0,
438
+ tcp: this.cartesianJoggingOpts.tcpId,
439
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
440
+ });
441
+ }
442
+ /**
443
+ * Start the TCP rotating around a specified axis at a given velocity
444
+ */
445
+ async startTCPRotation({ axis, direction, velocityRadsPerSec }) {
446
+ if (!this.cartesianWebsocket) throw new Error("Cartesian jogging websocket not connected; call setJoggingMode first");
447
+ const zeroVector = {
448
+ x: 0,
449
+ y: 0,
450
+ z: 0
451
+ };
452
+ const joggingVector = Object.assign({}, zeroVector);
453
+ joggingVector[axis] = direction === "-" ? -1 : 1;
454
+ this.cartesianWebsocket.sendJson({
455
+ motion_group: this.motionGroupId,
456
+ position_direction: zeroVector,
457
+ rotation_direction: joggingVector,
458
+ position_velocity: 0,
459
+ rotation_velocity: velocityRadsPerSec,
460
+ tcp: this.cartesianJoggingOpts.tcpId,
461
+ coordinate_system: this.cartesianJoggingOpts.coordSystemId
462
+ });
463
+ }
464
+ /**
465
+ * Move the robot by a fixed distance in a single cartesian
466
+ * axis, either rotating or translating relative to the TCP.
467
+ * Promise resolves only after the motion has completed.
468
+ */
469
+ async runIncrementalCartesianMotion({ currentTcpPose, currentJoints, coordSystemId, velocityInRelevantUnits, axis, direction, motion }) {
470
+ const commands = [];
471
+ if (!isSameCoordinateSystem(currentTcpPose.coordinate_system, coordSystemId)) throw new Error(`Current TCP pose coordinate system ${currentTcpPose.coordinate_system} does not match target coordinate system ${coordSystemId}`);
472
+ if (motion.type === "translate") {
473
+ const targetTcpPosition = Object.assign({}, currentTcpPose.position);
474
+ targetTcpPosition[axis] += motion.distanceMm * (direction === "-" ? -1 : 1);
475
+ commands.push({
476
+ settings: { limits_override: { tcp_velocity_limit: velocityInRelevantUnits } },
477
+ line: {
478
+ position: targetTcpPosition,
479
+ orientation: currentTcpPose.orientation,
480
+ coordinate_system: coordSystemId
481
+ }
482
+ });
483
+ } else if (motion.type === "rotate") {
484
+ const currentRotationVector = new three_src_math_Vector3_js.Vector3(currentTcpPose.orientation.x, currentTcpPose.orientation.y, currentTcpPose.orientation.z);
485
+ const currentRotationRad = currentRotationVector.length();
486
+ const currentRotationDirection = currentRotationVector.clone().normalize();
487
+ const differenceRotationRad = motion.distanceRads * (direction === "-" ? -1 : 1);
488
+ const differenceRotationDirection = new three_src_math_Vector3_js.Vector3(0, 0, 0);
489
+ differenceRotationDirection[axis] = 1;
490
+ const f1 = Math.cos(.5 * differenceRotationRad) * Math.cos(.5 * currentRotationRad);
491
+ const f2 = Math.sin(.5 * differenceRotationRad) * Math.sin(.5 * currentRotationRad);
492
+ const f3 = Math.sin(.5 * differenceRotationRad) * Math.cos(.5 * currentRotationRad);
493
+ const f4 = Math.cos(.5 * differenceRotationRad) * Math.sin(.5 * currentRotationRad);
494
+ const dotProduct = differenceRotationDirection.dot(currentRotationDirection);
495
+ const crossProduct = differenceRotationDirection.clone().cross(currentRotationDirection);
496
+ const newRotationRad = 2 * Math.acos(f1 - f2 * dotProduct);
497
+ const f5 = newRotationRad / Math.sin(.5 * newRotationRad);
498
+ const targetTcpOrientation = new three_src_math_Vector3_js.Vector3().addScaledVector(crossProduct, f2).addScaledVector(differenceRotationDirection, f3).addScaledVector(currentRotationDirection, f4).multiplyScalar(f5);
499
+ commands.push({
500
+ settings: { limits_override: { tcp_orientation_velocity_limit: velocityInRelevantUnits } },
501
+ line: {
502
+ position: currentTcpPose.position,
503
+ orientation: targetTcpOrientation,
504
+ coordinate_system: coordSystemId
505
+ }
506
+ });
507
+ }
508
+ const motionPlanRes = await this.nova.api.motion.planMotion({
509
+ motion_group: this.motionGroupId,
510
+ start_joint_position: currentJoints,
511
+ tcp: this.cartesianJoggingOpts.tcpId,
512
+ commands
513
+ });
514
+ const plannedMotion = motionPlanRes.plan_successful_response?.motion;
515
+ if (!plannedMotion) throw new Error(`Failed to plan jogging increment motion ${JSON.stringify(motionPlanRes)}`);
516
+ await this.nova.api.motion.streamMoveForward(plannedMotion, 100, void 0, void 0, void 0, { timeout: 1e3 * 60 });
517
+ }
518
+ /**
519
+ * Rotate a single robot joint by a fixed number of radians
520
+ * Promise resolves only after the motion has completed.
521
+ */
522
+ async runIncrementalJointRotation({ joint, currentJoints, velocityRadsPerSec, direction, distanceRads }) {
523
+ const targetJoints = [...currentJoints.joints];
524
+ targetJoints[joint] += distanceRads * (direction === "-" ? -1 : 1);
525
+ const jointVelocityLimits = new Array(currentJoints.joints.length).fill(velocityRadsPerSec);
526
+ const motionPlanRes = await this.nova.api.motion.planMotion({
527
+ motion_group: this.motionGroupId,
528
+ start_joint_position: currentJoints,
529
+ commands: [{
530
+ settings: { limits_override: { joint_velocity_limits: { joints: jointVelocityLimits } } },
531
+ joint_ptp: { joints: targetJoints }
532
+ }]
533
+ });
534
+ const plannedMotion = motionPlanRes.plan_successful_response?.motion;
535
+ if (!plannedMotion) {
536
+ console.error("Failed to plan jogging increment motion", motionPlanRes);
537
+ return;
538
+ }
539
+ await this.nova.api.motion.streamMoveForward(plannedMotion, 100, void 0, void 0, void 0, { timeout: 1e3 * 60 });
540
+ }
541
+ };
542
+
543
+ //#endregion
544
+ //#region src/lib/v1/MotionStreamConnection.ts
545
+ const MOTION_DELTA_THRESHOLD = 1e-4;
546
+ function unwrapRotationVector(newRotationVectorApi, currentRotationVectorApi) {
547
+ const currentRotationVector = new three.Vector3(currentRotationVectorApi.x, currentRotationVectorApi.y, currentRotationVectorApi.z);
548
+ const newRotationVector = new three.Vector3(newRotationVectorApi.x, newRotationVectorApi.y, newRotationVectorApi.z);
549
+ const currentAngle = currentRotationVector.length();
550
+ const currentAxis = currentRotationVector.normalize();
551
+ let newAngle = newRotationVector.length();
552
+ let newAxis = newRotationVector.normalize();
553
+ if (newAxis.dot(currentAxis) < 0) {
554
+ newAngle = -newAngle;
555
+ newAxis = newAxis.multiplyScalar(-1);
556
+ }
557
+ let angleDifference = newAngle - currentAngle;
558
+ angleDifference -= 2 * Math.PI * Math.floor((angleDifference + Math.PI) / (2 * Math.PI));
559
+ newAngle = currentAngle + angleDifference;
560
+ return newAxis.multiplyScalar(newAngle);
561
+ }
562
+ /**
563
+ * Store representing the current state of a connected motion group.
564
+ */
565
+ var MotionStreamConnection = class MotionStreamConnection {
566
+ static async open(nova, motionGroupId) {
567
+ const { instances: controllers } = await nova.api.controller.listControllers();
568
+ const [_motionGroupIndex, controllerId] = motionGroupId.split("@");
569
+ const controller = controllers.find((c) => c.controller === controllerId);
570
+ const motionGroup = controller?.physical_motion_groups.find((mg) => mg.motion_group === motionGroupId);
571
+ if (!controller || !motionGroup) throw new Error(`Controller ${controllerId} or motion group ${motionGroupId} not found`);
572
+ const motionStateSocket = nova.openReconnectingWebsocket(`/motion-groups/${motionGroupId}/state-stream`);
573
+ const firstMessage = await motionStateSocket.firstMessage();
574
+ const initialMotionState = tryParseJson(firstMessage.data)?.result;
575
+ if (!initialMotionState) throw new Error(`Unable to parse initial motion state message ${firstMessage.data}`);
576
+ console.log(`Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\n `, initialMotionState);
577
+ return new MotionStreamConnection(nova, controller, motionGroup, initialMotionState, motionStateSocket);
578
+ }
579
+ constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket) {
580
+ this.nova = nova;
581
+ this.controller = controller;
582
+ this.motionGroup = motionGroup;
583
+ this.initialMotionState = initialMotionState;
584
+ this.motionStateSocket = motionStateSocket;
585
+ this.rapidlyChangingMotionState = initialMotionState;
586
+ motionStateSocket.addEventListener("message", (event) => {
587
+ const motionStateResponse = tryParseJson(event.data)?.result;
588
+ if (!motionStateResponse) throw new Error(`Failed to get motion state for ${this.motionGroupId}: ${event.data}`);
589
+ if (!jointValuesEqual(this.rapidlyChangingMotionState.state.joint_position.joints, motionStateResponse.state.joint_position.joints, MOTION_DELTA_THRESHOLD)) (0, mobx.runInAction)(() => {
590
+ this.rapidlyChangingMotionState.state = motionStateResponse.state;
591
+ });
592
+ if (!tcpPoseEqual(this.rapidlyChangingMotionState.tcp_pose, motionStateResponse.tcp_pose, MOTION_DELTA_THRESHOLD)) (0, mobx.runInAction)(() => {
593
+ if (this.rapidlyChangingMotionState.tcp_pose == null) this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose;
594
+ else this.rapidlyChangingMotionState.tcp_pose = {
595
+ position: motionStateResponse.tcp_pose.position,
596
+ orientation: unwrapRotationVector(motionStateResponse.tcp_pose.orientation, this.rapidlyChangingMotionState.tcp_pose.orientation),
597
+ tcp: motionStateResponse.tcp_pose.tcp,
598
+ coordinate_system: motionStateResponse.tcp_pose.coordinate_system
599
+ };
600
+ });
601
+ });
602
+ (0, mobx.makeAutoObservable)(this);
603
+ }
604
+ get motionGroupId() {
605
+ return this.motionGroup.motion_group;
606
+ }
607
+ get controllerId() {
608
+ return this.controller.controller;
609
+ }
610
+ get modelFromController() {
611
+ return this.motionGroup.model_from_controller;
612
+ }
613
+ get wandelscriptIdentifier() {
614
+ const num = this.motionGroupId.split("@")[0];
615
+ return `${this.controllerId.replaceAll("-", "_")}_${num}`;
616
+ }
617
+ get joints() {
618
+ return this.initialMotionState.state.joint_position.joints.map((_, i) => {
619
+ return { index: i };
620
+ });
621
+ }
622
+ dispose() {
623
+ this.motionStateSocket.close();
624
+ }
625
+ };
626
+
627
+ //#endregion
628
+ //#region src/lib/v1/NovaCellAPIClient.ts
629
+ /**
630
+ * API client providing type-safe access to all the Nova API REST endpoints
631
+ * associated with a specific cell id.
632
+ */
633
+ var NovaCellAPIClient = class {
634
+ constructor(cellId, opts) {
635
+ this.cellId = cellId;
636
+ this.opts = opts;
637
+ this.system = this.withUnwrappedResponsesOnly(__wandelbots_nova_api_v1.SystemApi);
638
+ this.cell = this.withUnwrappedResponsesOnly(__wandelbots_nova_api_v1.CellApi);
639
+ this.deviceConfig = this.withCellId(__wandelbots_nova_api_v1.DeviceConfigurationApi);
640
+ this.motionGroup = this.withCellId(__wandelbots_nova_api_v1.MotionGroupApi);
641
+ this.motionGroupInfos = this.withCellId(__wandelbots_nova_api_v1.MotionGroupInfosApi);
642
+ this.controller = this.withCellId(__wandelbots_nova_api_v1.ControllerApi);
643
+ this.program = this.withCellId(__wandelbots_nova_api_v1.ProgramApi);
644
+ this.programValues = this.withCellId(__wandelbots_nova_api_v1.ProgramValuesApi);
645
+ this.controllerIOs = this.withCellId(__wandelbots_nova_api_v1.ControllerIOsApi);
646
+ this.motionGroupKinematic = this.withCellId(__wandelbots_nova_api_v1.MotionGroupKinematicApi);
647
+ this.motion = this.withCellId(__wandelbots_nova_api_v1.MotionApi);
648
+ this.coordinateSystems = this.withCellId(__wandelbots_nova_api_v1.CoordinateSystemsApi);
649
+ this.application = this.withCellId(__wandelbots_nova_api_v1.ApplicationApi);
650
+ this.applicationGlobal = this.withUnwrappedResponsesOnly(__wandelbots_nova_api_v1.ApplicationApi);
651
+ this.motionGroupJogging = this.withCellId(__wandelbots_nova_api_v1.MotionGroupJoggingApi);
652
+ this.virtualRobot = this.withCellId(__wandelbots_nova_api_v1.VirtualRobotApi);
653
+ this.virtualRobotSetup = this.withCellId(__wandelbots_nova_api_v1.VirtualRobotSetupApi);
654
+ this.virtualRobotMode = this.withCellId(__wandelbots_nova_api_v1.VirtualRobotModeApi);
655
+ this.virtualRobotBehavior = this.withCellId(__wandelbots_nova_api_v1.VirtualRobotBehaviorApi);
656
+ this.libraryProgramMetadata = this.withCellId(__wandelbots_nova_api_v1.LibraryProgramMetadataApi);
657
+ this.libraryProgram = this.withCellId(__wandelbots_nova_api_v1.LibraryProgramApi);
658
+ this.libraryRecipeMetadata = this.withCellId(__wandelbots_nova_api_v1.LibraryRecipeMetadataApi);
659
+ this.libraryRecipe = this.withCellId(__wandelbots_nova_api_v1.LibraryRecipeApi);
660
+ this.storeObject = this.withCellId(__wandelbots_nova_api_v1.StoreObjectApi);
661
+ this.storeCollisionComponents = this.withCellId(__wandelbots_nova_api_v1.StoreCollisionComponentsApi);
662
+ this.storeCollisionScenes = this.withCellId(__wandelbots_nova_api_v1.StoreCollisionScenesApi);
663
+ }
664
+ /**
665
+ * Some TypeScript sorcery which alters the API class methods so you don't
666
+ * have to pass the cell id to every single one, and de-encapsulates the
667
+ * response data
668
+ */
669
+ withCellId(ApiConstructor) {
670
+ const apiClient = new ApiConstructor({
671
+ ...this.opts,
672
+ isJsonMime: (mime) => {
673
+ return mime === "application/json";
674
+ }
675
+ }, this.opts.basePath ?? "", this.opts.axiosInstance ?? axios.default.create());
676
+ for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) if (key !== "constructor" && typeof apiClient[key] === "function") {
677
+ const originalFunction = apiClient[key];
678
+ apiClient[key] = (...args) => {
679
+ return originalFunction.apply(apiClient, [this.cellId, ...args]).then((res) => res.data);
680
+ };
681
+ }
682
+ return apiClient;
683
+ }
684
+ /**
685
+ * As withCellId, but only does the response unwrapping
686
+ */
687
+ withUnwrappedResponsesOnly(ApiConstructor) {
688
+ const apiClient = new ApiConstructor({
689
+ ...this.opts,
690
+ isJsonMime: (mime) => {
691
+ return mime === "application/json";
692
+ }
693
+ }, this.opts.basePath ?? "", this.opts.axiosInstance ?? axios.default.create());
694
+ for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) if (key !== "constructor" && typeof apiClient[key] === "function") {
695
+ const originalFunction = apiClient[key];
696
+ apiClient[key] = (...args) => {
697
+ return originalFunction.apply(apiClient, args).then((res) => res.data);
698
+ };
699
+ }
700
+ return apiClient;
701
+ }
702
+ };
703
+
704
+ //#endregion
705
+ //#region src/lib/v1/mock/MockNovaInstance.ts
706
+ /**
707
+ * Ultra-simplified mock Nova server for testing stuff
708
+ */
709
+ var MockNovaInstance = class {
710
+ constructor() {
711
+ this.connections = [];
712
+ }
713
+ async handleAPIRequest(config) {
714
+ const apiHandlers = [
715
+ {
716
+ method: "GET",
717
+ path: "/cells/:cellId/controllers",
718
+ handle() {
719
+ return { instances: [{
720
+ controller: "mock-ur5e",
721
+ model_name: "UniversalRobots::Controller",
722
+ host: "mock-ur5e",
723
+ allow_software_install_on_controller: true,
724
+ physical_motion_groups: [{
725
+ motion_group: "0@mock-ur5e",
726
+ name_from_controller: "UR5e",
727
+ active: false,
728
+ model_from_controller: "UniversalRobots_UR5e"
729
+ }],
730
+ has_error: false,
731
+ error_details: ""
732
+ }] };
733
+ }
734
+ },
735
+ {
736
+ method: "GET",
737
+ path: "/cells/:cellId/controllers/:controllerId",
738
+ handle() {
739
+ return {
740
+ configuration: {
741
+ kind: "VirtualController",
742
+ manufacturer: "universalrobots",
743
+ position: "[0,-1.571,-1.571,-1.571,1.571,-1.571,0]",
744
+ type: "universalrobots-ur5e"
745
+ },
746
+ name: "mock-ur5"
747
+ };
748
+ }
749
+ },
750
+ {
751
+ method: "GET",
752
+ path: "/cells/:cellId/motion-groups/:motionGroupId/specification",
753
+ handle() {
754
+ return {
755
+ dh_parameters: [
756
+ {
757
+ alpha: 1.5707963267948966,
758
+ theta: 0,
759
+ a: 0,
760
+ d: 162.25,
761
+ reverse_rotation_direction: false
762
+ },
763
+ {
764
+ alpha: 0,
765
+ theta: 0,
766
+ a: -425,
767
+ d: 0,
768
+ reverse_rotation_direction: false
769
+ },
770
+ {
771
+ alpha: 0,
772
+ theta: 0,
773
+ a: -392.2,
774
+ d: 0,
775
+ reverse_rotation_direction: false
776
+ },
777
+ {
778
+ alpha: 1.5707963267948966,
779
+ theta: 0,
780
+ a: 0,
781
+ d: 133.3,
782
+ reverse_rotation_direction: false
783
+ },
784
+ {
785
+ alpha: -1.5707963267948966,
786
+ theta: 0,
787
+ a: 0,
788
+ d: 99.7,
789
+ reverse_rotation_direction: false
790
+ },
791
+ {
792
+ alpha: 0,
793
+ theta: 0,
794
+ a: 0,
795
+ d: 99.6,
796
+ reverse_rotation_direction: false
797
+ }
798
+ ],
799
+ mechanical_joint_limits: [
800
+ {
801
+ joint: "JOINTNAME_AXIS_1",
802
+ lower_limit: -6.335545063018799,
803
+ upper_limit: 6.335545063018799,
804
+ unlimited: false
805
+ },
806
+ {
807
+ joint: "JOINTNAME_AXIS_2",
808
+ lower_limit: -6.335545063018799,
809
+ upper_limit: 6.335545063018799,
810
+ unlimited: false
811
+ },
812
+ {
813
+ joint: "JOINTNAME_AXIS_3",
814
+ lower_limit: -6.335545063018799,
815
+ upper_limit: 6.335545063018799,
816
+ unlimited: false
817
+ },
818
+ {
819
+ joint: "JOINTNAME_AXIS_4",
820
+ lower_limit: -6.335545063018799,
821
+ upper_limit: 6.335545063018799,
822
+ unlimited: false
823
+ },
824
+ {
825
+ joint: "JOINTNAME_AXIS_5",
826
+ lower_limit: -6.335545063018799,
827
+ upper_limit: 6.335545063018799,
828
+ unlimited: false
829
+ },
830
+ {
831
+ joint: "JOINTNAME_AXIS_6",
832
+ lower_limit: -6.335545063018799,
833
+ upper_limit: 6.335545063018799,
834
+ unlimited: false
835
+ }
836
+ ]
837
+ };
838
+ }
839
+ },
840
+ {
841
+ method: "GET",
842
+ path: "/cells/:cellId/motion-groups/:motionGroupId/safety-setup",
843
+ handle() {
844
+ return {
845
+ safety_settings: [{
846
+ safety_state: "SAFETY_NORMAL",
847
+ settings: {
848
+ joint_position_limits: [
849
+ {
850
+ joint: "JOINTNAME_AXIS_1",
851
+ lower_limit: -2.96705961227417,
852
+ upper_limit: 2.96705961227417,
853
+ unlimited: false
854
+ },
855
+ {
856
+ joint: "JOINTNAME_AXIS_2",
857
+ lower_limit: -1.7453292608261108,
858
+ upper_limit: 2.7925267219543457,
859
+ unlimited: false
860
+ },
861
+ {
862
+ joint: "JOINTNAME_AXIS_3",
863
+ lower_limit: -3.3161256313323975,
864
+ upper_limit: .40142571926116943,
865
+ unlimited: false
866
+ },
867
+ {
868
+ joint: "JOINTNAME_AXIS_4",
869
+ lower_limit: -3.4906585216522217,
870
+ upper_limit: 3.4906585216522217,
871
+ unlimited: false
872
+ },
873
+ {
874
+ joint: "JOINTNAME_AXIS_5",
875
+ lower_limit: -2.4434609413146973,
876
+ upper_limit: 2.4434609413146973,
877
+ unlimited: false
878
+ },
879
+ {
880
+ joint: "JOINTNAME_AXIS_6",
881
+ lower_limit: -4.71238899230957,
882
+ upper_limit: 4.71238899230957,
883
+ unlimited: false
884
+ }
885
+ ],
886
+ joint_velocity_limits: [
887
+ {
888
+ joint: "JOINTNAME_AXIS_1",
889
+ limit: 3.1415927410125732
890
+ },
891
+ {
892
+ joint: "JOINTNAME_AXIS_2",
893
+ limit: 3.1415927410125732
894
+ },
895
+ {
896
+ joint: "JOINTNAME_AXIS_3",
897
+ limit: 3.4906585216522217
898
+ },
899
+ {
900
+ joint: "JOINTNAME_AXIS_4",
901
+ limit: 6.108652591705322
902
+ },
903
+ {
904
+ joint: "JOINTNAME_AXIS_5",
905
+ limit: 6.108652591705322
906
+ },
907
+ {
908
+ joint: "JOINTNAME_AXIS_6",
909
+ limit: 6.981317043304443
910
+ }
911
+ ],
912
+ joint_acceleration_limits: [],
913
+ joint_torque_limits: [],
914
+ tcp_velocity_limit: 1800
915
+ }
916
+ }],
917
+ safety_zones: [
918
+ {
919
+ id: 1,
920
+ priority: 0,
921
+ geometry: {
922
+ compound: { child_geometries: [
923
+ {
924
+ convex_hull: { vertices: [
925
+ {
926
+ x: -800,
927
+ y: -1330,
928
+ z: -1820
929
+ },
930
+ {
931
+ x: 1650,
932
+ y: -1330,
933
+ z: -1820
934
+ },
935
+ {
936
+ x: 1650,
937
+ y: 1330,
938
+ z: -1820
939
+ },
940
+ {
941
+ x: -800,
942
+ y: 1330,
943
+ z: -1820
944
+ }
945
+ ] },
946
+ init_pose: {
947
+ position: {
948
+ x: 0,
949
+ y: 0,
950
+ z: 0
951
+ },
952
+ orientation: {
953
+ x: 0,
954
+ y: 0,
955
+ z: 0,
956
+ w: 1
957
+ }
958
+ },
959
+ id: "box"
960
+ },
961
+ {
962
+ convex_hull: { vertices: [
963
+ {
964
+ x: -800,
965
+ y: -1330,
966
+ z: -1820
967
+ },
968
+ {
969
+ x: 1650,
970
+ y: -1330,
971
+ z: -1820
972
+ },
973
+ {
974
+ x: 1650,
975
+ y: -1330,
976
+ z: 1500
977
+ },
978
+ {
979
+ x: -800,
980
+ y: -1330,
981
+ z: 1500
982
+ }
983
+ ] },
984
+ init_pose: {
985
+ position: {
986
+ x: 0,
987
+ y: 0,
988
+ z: 0
989
+ },
990
+ orientation: {
991
+ x: 0,
992
+ y: 0,
993
+ z: 0,
994
+ w: 1
995
+ }
996
+ },
997
+ id: "box"
998
+ },
999
+ {
1000
+ convex_hull: { vertices: [
1001
+ {
1002
+ x: -800,
1003
+ y: -1330,
1004
+ z: -1820
1005
+ },
1006
+ {
1007
+ x: -800,
1008
+ y: 1330,
1009
+ z: -1820
1010
+ },
1011
+ {
1012
+ x: -800,
1013
+ y: 1330,
1014
+ z: 1500
1015
+ },
1016
+ {
1017
+ x: -800,
1018
+ y: -1330,
1019
+ z: 1500
1020
+ }
1021
+ ] },
1022
+ init_pose: {
1023
+ position: {
1024
+ x: 0,
1025
+ y: 0,
1026
+ z: 0
1027
+ },
1028
+ orientation: {
1029
+ x: 0,
1030
+ y: 0,
1031
+ z: 0,
1032
+ w: 1
1033
+ }
1034
+ },
1035
+ id: "box"
1036
+ },
1037
+ {
1038
+ convex_hull: { vertices: [
1039
+ {
1040
+ x: 1650,
1041
+ y: 1330,
1042
+ z: 1500
1043
+ },
1044
+ {
1045
+ x: -800,
1046
+ y: 1330,
1047
+ z: 1500
1048
+ },
1049
+ {
1050
+ x: -800,
1051
+ y: -1330,
1052
+ z: 1500
1053
+ },
1054
+ {
1055
+ x: 1650,
1056
+ y: -1330,
1057
+ z: 1500
1058
+ }
1059
+ ] },
1060
+ init_pose: {
1061
+ position: {
1062
+ x: 0,
1063
+ y: 0,
1064
+ z: 0
1065
+ },
1066
+ orientation: {
1067
+ x: 0,
1068
+ y: 0,
1069
+ z: 0,
1070
+ w: 1
1071
+ }
1072
+ },
1073
+ id: "box"
1074
+ },
1075
+ {
1076
+ convex_hull: { vertices: [
1077
+ {
1078
+ x: 1650,
1079
+ y: 1330,
1080
+ z: 1500
1081
+ },
1082
+ {
1083
+ x: -800,
1084
+ y: 1330,
1085
+ z: 1500
1086
+ },
1087
+ {
1088
+ x: -800,
1089
+ y: 1330,
1090
+ z: -1820
1091
+ },
1092
+ {
1093
+ x: 1650,
1094
+ y: 1330,
1095
+ z: -1820
1096
+ }
1097
+ ] },
1098
+ init_pose: {
1099
+ position: {
1100
+ x: 0,
1101
+ y: 0,
1102
+ z: 0
1103
+ },
1104
+ orientation: {
1105
+ x: 0,
1106
+ y: 0,
1107
+ z: 0,
1108
+ w: 1
1109
+ }
1110
+ },
1111
+ id: "box"
1112
+ },
1113
+ {
1114
+ convex_hull: { vertices: [
1115
+ {
1116
+ x: 1650,
1117
+ y: 1330,
1118
+ z: 1500
1119
+ },
1120
+ {
1121
+ x: 1650,
1122
+ y: -1330,
1123
+ z: 1500
1124
+ },
1125
+ {
1126
+ x: 1650,
1127
+ y: -1330,
1128
+ z: -1820
1129
+ },
1130
+ {
1131
+ x: 1650,
1132
+ y: 1330,
1133
+ z: -1820
1134
+ }
1135
+ ] },
1136
+ init_pose: {
1137
+ position: {
1138
+ x: 0,
1139
+ y: 0,
1140
+ z: 0
1141
+ },
1142
+ orientation: {
1143
+ x: 0,
1144
+ y: 0,
1145
+ z: 0,
1146
+ w: 1
1147
+ }
1148
+ },
1149
+ id: "box"
1150
+ }
1151
+ ] },
1152
+ init_pose: {
1153
+ position: {
1154
+ x: 0,
1155
+ y: 0,
1156
+ z: 0
1157
+ },
1158
+ orientation: {
1159
+ x: 0,
1160
+ y: 0,
1161
+ z: 0,
1162
+ w: 1
1163
+ }
1164
+ },
1165
+ id: "Cell workzone"
1166
+ },
1167
+ motion_group_uid: 1
1168
+ },
1169
+ {
1170
+ id: 2,
1171
+ priority: 0,
1172
+ geometry: {
1173
+ convex_hull: { vertices: [
1174
+ {
1175
+ x: 1650,
1176
+ y: 1330,
1177
+ z: -1850
1178
+ },
1179
+ {
1180
+ x: 865,
1181
+ y: 1330,
1182
+ z: -1850
1183
+ },
1184
+ {
1185
+ x: 865,
1186
+ y: -720,
1187
+ z: -1850
1188
+ },
1189
+ {
1190
+ x: 1650,
1191
+ y: -720,
1192
+ z: -1850
1193
+ },
1194
+ {
1195
+ x: 1650,
1196
+ y: 1330,
1197
+ z: -920
1198
+ },
1199
+ {
1200
+ x: 865,
1201
+ y: 1330,
1202
+ z: -920
1203
+ },
1204
+ {
1205
+ x: 865,
1206
+ y: -720,
1207
+ z: -920
1208
+ },
1209
+ {
1210
+ x: 1650,
1211
+ y: -720,
1212
+ z: -920
1213
+ }
1214
+ ] },
1215
+ init_pose: {
1216
+ position: {
1217
+ x: 0,
1218
+ y: 0,
1219
+ z: 0
1220
+ },
1221
+ orientation: {
1222
+ x: 0,
1223
+ y: 0,
1224
+ z: 0,
1225
+ w: 1
1226
+ }
1227
+ },
1228
+ id: "Transport"
1229
+ },
1230
+ motion_group_uid: 1
1231
+ },
1232
+ {
1233
+ id: 3,
1234
+ priority: 0,
1235
+ geometry: {
1236
+ convex_hull: { vertices: [
1237
+ {
1238
+ x: 1650,
1239
+ y: 1330,
1240
+ z: -600
1241
+ },
1242
+ {
1243
+ x: 865,
1244
+ y: 1330,
1245
+ z: -600
1246
+ },
1247
+ {
1248
+ x: 865,
1249
+ y: 430,
1250
+ z: -600
1251
+ },
1252
+ {
1253
+ x: 1650,
1254
+ y: 430,
1255
+ z: -600
1256
+ },
1257
+ {
1258
+ x: 1650,
1259
+ y: 1330,
1260
+ z: -1250
1261
+ },
1262
+ {
1263
+ x: 865,
1264
+ y: 1330,
1265
+ z: -1250
1266
+ },
1267
+ {
1268
+ x: 865,
1269
+ y: 430,
1270
+ z: -1250
1271
+ },
1272
+ {
1273
+ x: 1650,
1274
+ y: 430,
1275
+ z: -1250
1276
+ }
1277
+ ] },
1278
+ init_pose: {
1279
+ position: {
1280
+ x: 0,
1281
+ y: 0,
1282
+ z: 0
1283
+ },
1284
+ orientation: {
1285
+ x: 0,
1286
+ y: 0,
1287
+ z: 0,
1288
+ w: 1
1289
+ }
1290
+ },
1291
+ id: "Tunel"
1292
+ },
1293
+ motion_group_uid: 1
1294
+ },
1295
+ {
1296
+ id: 4,
1297
+ priority: 0,
1298
+ geometry: {
1299
+ convex_hull: { vertices: [
1300
+ {
1301
+ x: 1650,
1302
+ y: -760,
1303
+ z: -440
1304
+ },
1305
+ {
1306
+ x: 900,
1307
+ y: -760,
1308
+ z: -440
1309
+ },
1310
+ {
1311
+ x: 900,
1312
+ y: -1330,
1313
+ z: -440
1314
+ },
1315
+ {
1316
+ x: 1650,
1317
+ y: -1330,
1318
+ z: -440
1319
+ },
1320
+ {
1321
+ x: 1650,
1322
+ y: -760,
1323
+ z: -1800
1324
+ },
1325
+ {
1326
+ x: 900,
1327
+ y: -760,
1328
+ z: -1800
1329
+ },
1330
+ {
1331
+ x: 900,
1332
+ y: -1330,
1333
+ z: -1800
1334
+ },
1335
+ {
1336
+ x: 1650,
1337
+ y: -1330,
1338
+ z: -1800
1339
+ }
1340
+ ] },
1341
+ init_pose: {
1342
+ position: {
1343
+ x: 0,
1344
+ y: 0,
1345
+ z: 0
1346
+ },
1347
+ orientation: {
1348
+ x: 0,
1349
+ y: 0,
1350
+ z: 0,
1351
+ w: 1
1352
+ }
1353
+ },
1354
+ id: "Fanuc controller"
1355
+ },
1356
+ motion_group_uid: 1
1357
+ },
1358
+ {
1359
+ id: 6,
1360
+ priority: 0,
1361
+ geometry: {
1362
+ convex_hull: { vertices: [
1363
+ {
1364
+ x: -200,
1365
+ y: -200,
1366
+ z: -1900
1367
+ },
1368
+ {
1369
+ x: 200,
1370
+ y: -200,
1371
+ z: -1900
1372
+ },
1373
+ {
1374
+ x: 200,
1375
+ y: 200,
1376
+ z: -1900
1377
+ },
1378
+ {
1379
+ x: -200,
1380
+ y: 200,
1381
+ z: -1900
1382
+ },
1383
+ {
1384
+ x: -200,
1385
+ y: -200,
1386
+ z: -350
1387
+ },
1388
+ {
1389
+ x: 200,
1390
+ y: -200,
1391
+ z: -350
1392
+ },
1393
+ {
1394
+ x: 200,
1395
+ y: 200,
1396
+ z: -350
1397
+ },
1398
+ {
1399
+ x: -200,
1400
+ y: 200,
1401
+ z: -350
1402
+ }
1403
+ ] },
1404
+ init_pose: {
1405
+ position: {
1406
+ x: 0,
1407
+ y: 0,
1408
+ z: 0
1409
+ },
1410
+ orientation: {
1411
+ x: 0,
1412
+ y: 0,
1413
+ z: 0,
1414
+ w: 1
1415
+ }
1416
+ },
1417
+ id: "Robot base"
1418
+ },
1419
+ motion_group_uid: 1
1420
+ }
1421
+ ],
1422
+ robot_model_geometries: [
1423
+ {
1424
+ link_index: 1,
1425
+ geometry: {
1426
+ sphere: { radius: 270 },
1427
+ init_pose: {
1428
+ position: {
1429
+ x: -70,
1430
+ y: -70,
1431
+ z: -50
1432
+ },
1433
+ orientation: {
1434
+ x: 0,
1435
+ y: 0,
1436
+ z: 0,
1437
+ w: 1
1438
+ }
1439
+ },
1440
+ id: "link1_sphere"
1441
+ }
1442
+ },
1443
+ {
1444
+ link_index: 2,
1445
+ geometry: {
1446
+ capsule: {
1447
+ radius: 160,
1448
+ cylinder_height: 800
1449
+ },
1450
+ init_pose: {
1451
+ position: {
1452
+ x: -450,
1453
+ y: 40,
1454
+ z: 170
1455
+ },
1456
+ orientation: {
1457
+ x: 0,
1458
+ y: -Math.SQRT1_2,
1459
+ z: 0,
1460
+ w: Math.SQRT1_2
1461
+ }
1462
+ },
1463
+ id: "link2_capsule"
1464
+ }
1465
+ },
1466
+ {
1467
+ link_index: 3,
1468
+ geometry: {
1469
+ sphere: { radius: 270 },
1470
+ init_pose: {
1471
+ position: {
1472
+ x: -110,
1473
+ y: 10,
1474
+ z: -100
1475
+ },
1476
+ orientation: {
1477
+ x: 0,
1478
+ y: 0,
1479
+ z: 0,
1480
+ w: 1
1481
+ }
1482
+ },
1483
+ id: "link3_sphere"
1484
+ }
1485
+ },
1486
+ {
1487
+ link_index: 4,
1488
+ geometry: {
1489
+ capsule: {
1490
+ radius: 110,
1491
+ cylinder_height: 600
1492
+ },
1493
+ init_pose: {
1494
+ position: {
1495
+ x: 0,
1496
+ y: 300,
1497
+ z: 40
1498
+ },
1499
+ orientation: {
1500
+ x: -Math.SQRT1_2,
1501
+ y: 0,
1502
+ z: 0,
1503
+ w: Math.SQRT1_2
1504
+ }
1505
+ },
1506
+ id: "link4_capsule"
1507
+ }
1508
+ },
1509
+ {
1510
+ link_index: 5,
1511
+ geometry: {
1512
+ sphere: { radius: 75 },
1513
+ init_pose: {
1514
+ position: {
1515
+ x: 0,
1516
+ y: 0,
1517
+ z: -50
1518
+ },
1519
+ orientation: {
1520
+ x: 0,
1521
+ y: 0,
1522
+ z: 0,
1523
+ w: 1
1524
+ }
1525
+ },
1526
+ id: "link5_sphere"
1527
+ }
1528
+ }
1529
+ ],
1530
+ tool_geometries: []
1531
+ };
1532
+ }
1533
+ },
1534
+ {
1535
+ method: "GET",
1536
+ path: "/cells/:cellId/coordinate-systems",
1537
+ handle() {
1538
+ return { coordinatesystems: [{
1539
+ coordinate_system: "",
1540
+ name: "world",
1541
+ reference_uid: "",
1542
+ position: {
1543
+ x: 0,
1544
+ y: 0,
1545
+ z: 0
1546
+ },
1547
+ rotation: {
1548
+ angles: [
1549
+ 0,
1550
+ 0,
1551
+ 0
1552
+ ],
1553
+ type: "ROTATION_VECTOR"
1554
+ }
1555
+ }] };
1556
+ }
1557
+ },
1558
+ {
1559
+ method: "GET",
1560
+ path: "/cells/:cellId/motion-groups/:motionGroupId/tcps",
1561
+ handle() {
1562
+ return { tcps: [{
1563
+ id: "Flange",
1564
+ readable_name: "Default-Flange",
1565
+ position: {
1566
+ x: 0,
1567
+ y: 0,
1568
+ z: 0
1569
+ },
1570
+ rotation: {
1571
+ angles: [
1572
+ 0,
1573
+ 0,
1574
+ 0,
1575
+ 0
1576
+ ],
1577
+ type: "ROTATION_VECTOR"
1578
+ }
1579
+ }, {
1580
+ id: "complex-tcp-position",
1581
+ readable_name: "Complex TCP Position",
1582
+ position: {
1583
+ x: -200,
1584
+ y: 300,
1585
+ z: 150
1586
+ },
1587
+ rotation: {
1588
+ angles: [
1589
+ -.12139440409113832,
1590
+ -.06356210998212003,
1591
+ -.2023240068185639,
1592
+ 0
1593
+ ],
1594
+ type: "ROTATION_VECTOR"
1595
+ }
1596
+ }] };
1597
+ }
1598
+ }
1599
+ ];
1600
+ const method = config.method?.toUpperCase() || "GET";
1601
+ const path = `/cells${config.url?.split("/cells")[1]?.split("?")[0]}`;
1602
+ for (const handler of apiHandlers) {
1603
+ const match = path_to_regexp.match(handler.path)(path || "");
1604
+ if (method === handler.method && match) {
1605
+ const json = handler.handle();
1606
+ return {
1607
+ status: 200,
1608
+ statusText: "Success",
1609
+ data: JSON.stringify(json),
1610
+ headers: {},
1611
+ config,
1612
+ request: { responseURL: config.url }
1613
+ };
1614
+ }
1615
+ }
1616
+ throw new axios.AxiosError(`No mock handler matched this request: ${method} ${path}`, "404", config);
1617
+ }
1618
+ handleWebsocketConnection(socket) {
1619
+ this.connections.push(socket);
1620
+ setTimeout(() => {
1621
+ socket.dispatchEvent(new Event("open"));
1622
+ console.log("Websocket connection opened from", socket.url);
1623
+ if (socket.url.includes("/state-stream")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify(defaultMotionState) }));
1624
+ if (socket.url.includes("/move-joint")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify({ result: {
1625
+ motion_group: "0@ur",
1626
+ state: {
1627
+ controller: "ur",
1628
+ operation_mode: "OPERATION_MODE_AUTO",
1629
+ safety_state: "SAFETY_STATE_NORMAL",
1630
+ timestamp: "2024-09-18T12:48:26.096266444Z",
1631
+ velocity_override: 100,
1632
+ motion_groups: [{
1633
+ motion_group: "0@ur",
1634
+ controller: "ur",
1635
+ joint_position: { joints: [
1636
+ 1.3492152690887451,
1637
+ -1.5659207105636597,
1638
+ 1.6653711795806885,
1639
+ -1.0991662740707397,
1640
+ -1.829018235206604,
1641
+ 1.264623761177063
1642
+ ] },
1643
+ joint_velocity: { joints: [
1644
+ 0,
1645
+ 0,
1646
+ 0,
1647
+ 0,
1648
+ 0,
1649
+ 0
1650
+ ] },
1651
+ flange_pose: {
1652
+ position: {
1653
+ x: 6.437331889439328,
1654
+ y: -628.4123774830913,
1655
+ z: 577.0569957147832
1656
+ },
1657
+ orientation: {
1658
+ x: -1.683333649797158,
1659
+ y: -1.9783363827298732,
1660
+ z: -.4928031860165713
1661
+ },
1662
+ coordinate_system: ""
1663
+ },
1664
+ tcp_pose: {
1665
+ position: {
1666
+ x: 6.437331889439328,
1667
+ y: -628.4123774830913,
1668
+ z: 577.0569957147832
1669
+ },
1670
+ orientation: {
1671
+ x: -1.683333649797158,
1672
+ y: -1.9783363827298732,
1673
+ z: -.4928031860165713
1674
+ },
1675
+ coordinate_system: "",
1676
+ tcp: "Flange"
1677
+ },
1678
+ velocity: {
1679
+ linear: {
1680
+ x: 0,
1681
+ y: 0,
1682
+ z: 0
1683
+ },
1684
+ angular: {
1685
+ x: -0,
1686
+ y: 0,
1687
+ z: 0
1688
+ },
1689
+ coordinate_system: ""
1690
+ },
1691
+ force: {
1692
+ force: {
1693
+ x: 0,
1694
+ y: 0,
1695
+ z: 0
1696
+ },
1697
+ moment: {
1698
+ x: 0,
1699
+ y: 0,
1700
+ z: 0
1701
+ },
1702
+ coordinate_system: ""
1703
+ },
1704
+ joint_limit_reached: { limit_reached: [
1705
+ false,
1706
+ false,
1707
+ false,
1708
+ false,
1709
+ false,
1710
+ false
1711
+ ] },
1712
+ joint_current: { joints: [
1713
+ 0,
1714
+ 0,
1715
+ 0,
1716
+ 0,
1717
+ 0,
1718
+ 0
1719
+ ] },
1720
+ sequence_number: "671259"
1721
+ }],
1722
+ sequence_number: "671259"
1723
+ },
1724
+ movement_state: "MOVEMENT_STATE_MOVING"
1725
+ } }) }));
1726
+ if (socket.url.includes("/move-tcp")) socket.dispatchEvent(new MessageEvent("message", { data: JSON.stringify({ result: {
1727
+ motion_group: "0@ur",
1728
+ state: {
1729
+ controller: "ur",
1730
+ operation_mode: "OPERATION_MODE_AUTO",
1731
+ safety_state: "SAFETY_STATE_NORMAL",
1732
+ timestamp: "2024-09-18T12:43:12.188335774Z",
1733
+ velocity_override: 100,
1734
+ motion_groups: [{
1735
+ motion_group: "0@ur",
1736
+ controller: "ur",
1737
+ joint_position: { joints: [
1738
+ 1.3352527618408203,
1739
+ -1.5659207105636597,
1740
+ 1.6653711795806885,
1741
+ -1.110615611076355,
1742
+ -1.829018235206604,
1743
+ 1.264623761177063
1744
+ ] },
1745
+ joint_velocity: { joints: [
1746
+ 0,
1747
+ 0,
1748
+ 0,
1749
+ 0,
1750
+ 0,
1751
+ 0
1752
+ ] },
1753
+ flange_pose: {
1754
+ position: {
1755
+ x: -2.763015284002938,
1756
+ y: -630.2151479701106,
1757
+ z: 577.524509114342
1758
+ },
1759
+ orientation: {
1760
+ x: -1.704794877102097,
1761
+ y: -1.9722372952861567,
1762
+ z: -.4852079204210754
1763
+ },
1764
+ coordinate_system: ""
1765
+ },
1766
+ tcp_pose: {
1767
+ position: {
1768
+ x: -2.763015284002938,
1769
+ y: -630.2151479701106,
1770
+ z: 577.524509114342
1771
+ },
1772
+ orientation: {
1773
+ x: -1.704794877102097,
1774
+ y: -1.9722372952861567,
1775
+ z: -.4852079204210754
1776
+ },
1777
+ coordinate_system: "",
1778
+ tcp: "Flange"
1779
+ },
1780
+ velocity: {
1781
+ linear: {
1782
+ x: 0,
1783
+ y: 0,
1784
+ z: 0
1785
+ },
1786
+ angular: {
1787
+ x: -0,
1788
+ y: 0,
1789
+ z: 0
1790
+ },
1791
+ coordinate_system: ""
1792
+ },
1793
+ force: {
1794
+ force: {
1795
+ x: 0,
1796
+ y: 0,
1797
+ z: 0
1798
+ },
1799
+ moment: {
1800
+ x: 0,
1801
+ y: 0,
1802
+ z: 0
1803
+ },
1804
+ coordinate_system: ""
1805
+ },
1806
+ joint_limit_reached: { limit_reached: [
1807
+ false,
1808
+ false,
1809
+ false,
1810
+ false,
1811
+ false,
1812
+ false
1813
+ ] },
1814
+ joint_current: { joints: [
1815
+ 0,
1816
+ 0,
1817
+ 0,
1818
+ 0,
1819
+ 0,
1820
+ 0
1821
+ ] },
1822
+ sequence_number: "627897"
1823
+ }],
1824
+ sequence_number: "627897"
1825
+ },
1826
+ movement_state: "MOVEMENT_STATE_MOVING"
1827
+ } }) }));
1828
+ }, 10);
1829
+ }
1830
+ handleWebsocketMessage(socket, message) {
1831
+ console.log(`Received message on ${socket.url}`, message);
1832
+ }
1833
+ };
1834
+ const defaultMotionState = { result: {
1835
+ state: {
1836
+ motion_group: "0@universalrobots-ur5e",
1837
+ controller: "universalrobots-ur5e",
1838
+ joint_position: { joints: [
1839
+ 1.1699999570846558,
1840
+ -1.5700000524520874,
1841
+ 1.3600000143051147,
1842
+ 1.0299999713897705,
1843
+ 1.2899999618530273,
1844
+ 1.2799999713897705
1845
+ ] },
1846
+ joint_velocity: { joints: [
1847
+ 0,
1848
+ 0,
1849
+ 0,
1850
+ 0,
1851
+ 0,
1852
+ 0
1853
+ ] },
1854
+ flange_pose: {
1855
+ position: {
1856
+ x: 1.3300010259703043,
1857
+ y: -409.2680714682808,
1858
+ z: 531.0203477065281
1859
+ },
1860
+ orientation: {
1861
+ x: 1.7564919306270736,
1862
+ y: -1.7542521568325058,
1863
+ z: .7326972590614671
1864
+ },
1865
+ coordinate_system: ""
1866
+ },
1867
+ tcp_pose: {
1868
+ position: {
1869
+ x: 1.3300010259703043,
1870
+ y: -409.2680714682808,
1871
+ z: 531.0203477065281
1872
+ },
1873
+ orientation: {
1874
+ x: 1.7564919306270736,
1875
+ y: -1.7542521568325058,
1876
+ z: .7326972590614671
1877
+ },
1878
+ coordinate_system: "",
1879
+ tcp: "Flange"
1880
+ },
1881
+ velocity: {
1882
+ linear: {
1883
+ x: 0,
1884
+ y: 0,
1885
+ z: 0
1886
+ },
1887
+ angular: {
1888
+ x: 0,
1889
+ y: 0,
1890
+ z: 0
1891
+ },
1892
+ coordinate_system: ""
1893
+ },
1894
+ force: {
1895
+ force: {
1896
+ x: 0,
1897
+ y: 0,
1898
+ z: 0
1899
+ },
1900
+ moment: {
1901
+ x: 0,
1902
+ y: 0,
1903
+ z: 0
1904
+ },
1905
+ coordinate_system: ""
1906
+ },
1907
+ joint_limit_reached: { limit_reached: [
1908
+ false,
1909
+ false,
1910
+ false,
1911
+ false,
1912
+ false,
1913
+ false
1914
+ ] },
1915
+ joint_current: { joints: [
1916
+ 0,
1917
+ 0,
1918
+ 0,
1919
+ 0,
1920
+ 0,
1921
+ 0
1922
+ ] },
1923
+ sequence_number: "1"
1924
+ },
1925
+ tcp_pose: {
1926
+ position: {
1927
+ x: 302.90748476115556,
1928
+ y: -152.87065869452337,
1929
+ z: 424.0454619321661
1930
+ },
1931
+ orientation: {
1932
+ x: 2.3403056115045353,
1933
+ y: -1.1706836379431356,
1934
+ z: .9772511964246311
1935
+ },
1936
+ coordinate_system: "",
1937
+ tcp: "Flange"
1938
+ }
1939
+ } };
1940
+
1941
+ //#endregion
1942
+ //#region src/lib/v1/NovaClient.ts
1943
+ function permissiveInstanceUrlParse(url) {
1944
+ if (!url.startsWith("http")) url = `http://${url}`;
1945
+ return new URL(url).toString();
1946
+ }
1947
+ /**
1948
+ * Client for connecting to a Nova instance and controlling robots.
1949
+ * @deprecated The nova v1 client is deprecated. Please use the v2 client from `@wandelbots/nova-js/v2` instead.
1950
+ */
1951
+ var NovaClient = class {
1952
+ constructor(config) {
1953
+ this.authPromise = null;
1954
+ this.accessToken = null;
1955
+ const cellId = config.cellId ?? "cell";
1956
+ this.config = {
1957
+ cellId,
1958
+ ...config
1959
+ };
1960
+ this.accessToken = config.accessToken || require_LoginWithAuth0.availableStorage.getString("wbjs.access_token") || null;
1961
+ if (this.config.instanceUrl === "https://mock.example.com") this.mock = new MockNovaInstance();
1962
+ else this.config.instanceUrl = permissiveInstanceUrlParse(this.config.instanceUrl);
1963
+ const axiosInstance = axios.default.create({
1964
+ baseURL: (0, url_join.default)(this.config.instanceUrl, "/api/v1"),
1965
+ headers: typeof window !== "undefined" && window.location.origin.includes("localhost") ? {} : { "X-Wandelbots-Client": "Wandelbots-Nova-JS-SDK" }
1966
+ });
1967
+ axiosInstance.interceptors.request.use(async (request) => {
1968
+ if (!request.headers.Authorization) {
1969
+ if (this.accessToken) request.headers.Authorization = `Bearer ${this.accessToken}`;
1970
+ else if (this.config.username && this.config.password) request.headers.Authorization = `Basic ${btoa(`${config.username}:${config.password}`)}`;
1971
+ }
1972
+ return request;
1973
+ });
1974
+ if (typeof window !== "undefined") axiosInstance.interceptors.response.use((r) => r, async (error) => {
1975
+ if ((0, axios.isAxiosError)(error)) {
1976
+ if (error.response?.status === 401) try {
1977
+ await this.renewAuthentication();
1978
+ if (error.config) {
1979
+ if (this.accessToken) error.config.headers.Authorization = `Bearer ${this.accessToken}`;
1980
+ else delete error.config.headers.Authorization;
1981
+ return axiosInstance.request(error.config);
1982
+ }
1983
+ } catch (err) {
1984
+ return Promise.reject(err);
1985
+ }
1986
+ else if (error.response?.status === 503) {
1987
+ if ((await fetch(window.location.href)).status === 503) window.location.reload();
1988
+ }
1989
+ }
1990
+ return Promise.reject(error);
1991
+ });
1992
+ this.api = new NovaCellAPIClient(cellId, {
1993
+ ...config,
1994
+ basePath: (0, url_join.default)(this.config.instanceUrl, "/api/v1"),
1995
+ isJsonMime: (mime) => {
1996
+ return mime === "application/json";
1997
+ },
1998
+ baseOptions: {
1999
+ ...this.mock ? { adapter: (config$1) => {
2000
+ return this.mock.handleAPIRequest(config$1);
2001
+ } } : {},
2002
+ ...config.baseOptions
2003
+ },
2004
+ axiosInstance
2005
+ });
2006
+ }
2007
+ async renewAuthentication() {
2008
+ if (this.authPromise) return;
2009
+ this.authPromise = require_LoginWithAuth0.loginWithAuth0(this.config.instanceUrl);
2010
+ try {
2011
+ this.accessToken = await this.authPromise;
2012
+ if (this.accessToken) require_LoginWithAuth0.availableStorage.setString("wbjs.access_token", this.accessToken);
2013
+ else require_LoginWithAuth0.availableStorage.delete("wbjs.access_token");
2014
+ } finally {
2015
+ this.authPromise = null;
2016
+ }
2017
+ }
2018
+ makeWebsocketURL(path) {
2019
+ const url = new URL((0, url_join.default)(this.config.instanceUrl, `/api/v1/cells/${this.config.cellId}`, path));
2020
+ url.protocol = url.protocol.replace("http", "ws");
2021
+ url.protocol = url.protocol.replace("https", "wss");
2022
+ if (this.accessToken) url.searchParams.append("token", this.accessToken);
2023
+ else if (this.config.username && this.config.password) {
2024
+ url.username = this.config.username;
2025
+ url.password = this.config.password;
2026
+ }
2027
+ return url.toString();
2028
+ }
2029
+ /**
2030
+ * Retrieve an AutoReconnectingWebsocket to the given path on the Nova instance.
2031
+ * If you explicitly want to reconnect an existing websocket, call `reconnect`
2032
+ * on the returned object.
2033
+ */
2034
+ openReconnectingWebsocket(path) {
2035
+ return new require_LoginWithAuth0.AutoReconnectingWebsocket(this.makeWebsocketURL(path), { mock: this.mock });
2036
+ }
2037
+ /**
2038
+ * Connect to the motion state websocket(s) for a given motion group
2039
+ */
2040
+ async connectMotionStream(motionGroupId) {
2041
+ return await MotionStreamConnection.open(this, motionGroupId);
2042
+ }
2043
+ /**
2044
+ * Connect to the jogging websocket(s) for a given motion group
2045
+ */
2046
+ async connectJogger(motionGroupId) {
2047
+ return await JoggerConnection.open(this, motionGroupId);
2048
+ }
2049
+ async connectMotionGroups(motionGroupIds) {
2050
+ const { instances } = await this.api.controller.listControllers();
2051
+ return Promise.all(motionGroupIds.map((motionGroupId) => ConnectedMotionGroup.connect(this, motionGroupId, instances)));
2052
+ }
2053
+ async connectMotionGroup(motionGroupId) {
2054
+ return (await this.connectMotionGroups([motionGroupId]))[0];
2055
+ }
2056
+ };
2057
+
2058
+ //#endregion
2059
+ Object.defineProperty(exports, 'ConnectedMotionGroup', {
2060
+ enumerable: true,
2061
+ get: function () {
2062
+ return ConnectedMotionGroup;
2063
+ }
2064
+ });
2065
+ Object.defineProperty(exports, 'JoggerConnection', {
2066
+ enumerable: true,
2067
+ get: function () {
2068
+ return JoggerConnection;
2069
+ }
2070
+ });
2071
+ Object.defineProperty(exports, 'MotionStreamConnection', {
2072
+ enumerable: true,
2073
+ get: function () {
2074
+ return MotionStreamConnection;
2075
+ }
2076
+ });
2077
+ Object.defineProperty(exports, 'NovaCellAPIClient', {
2078
+ enumerable: true,
2079
+ get: function () {
2080
+ return NovaCellAPIClient;
2081
+ }
2082
+ });
2083
+ Object.defineProperty(exports, 'NovaClient', {
2084
+ enumerable: true,
2085
+ get: function () {
2086
+ return NovaClient;
2087
+ }
2088
+ });
2089
+ Object.defineProperty(exports, 'XYZ_TO_VECTOR', {
2090
+ enumerable: true,
2091
+ get: function () {
2092
+ return XYZ_TO_VECTOR;
2093
+ }
2094
+ });
2095
+ Object.defineProperty(exports, 'degreesToRadians', {
2096
+ enumerable: true,
2097
+ get: function () {
2098
+ return degreesToRadians;
2099
+ }
2100
+ });
2101
+ Object.defineProperty(exports, 'isSameCoordinateSystem', {
2102
+ enumerable: true,
2103
+ get: function () {
2104
+ return isSameCoordinateSystem;
2105
+ }
2106
+ });
2107
+ Object.defineProperty(exports, 'makeUrlQueryString', {
2108
+ enumerable: true,
2109
+ get: function () {
2110
+ return makeUrlQueryString;
2111
+ }
2112
+ });
2113
+ Object.defineProperty(exports, 'poseToWandelscriptString', {
2114
+ enumerable: true,
2115
+ get: function () {
2116
+ return poseToWandelscriptString;
2117
+ }
2118
+ });
2119
+ Object.defineProperty(exports, 'radiansToDegrees', {
2120
+ enumerable: true,
2121
+ get: function () {
2122
+ return radiansToDegrees;
2123
+ }
2124
+ });
2125
+ Object.defineProperty(exports, 'tryParseJson', {
2126
+ enumerable: true,
2127
+ get: function () {
2128
+ return tryParseJson;
2129
+ }
2130
+ });
2131
+ Object.defineProperty(exports, 'tryStringifyJson', {
2132
+ enumerable: true,
2133
+ get: function () {
2134
+ return tryStringifyJson;
2135
+ }
2136
+ });
2137
+ //# sourceMappingURL=NovaClient-D2EItmiH.cjs.map