@wandelbots/wandelbots-js-react-components 3.4.0-pr.feat-add-yaskawa-gp200s.438.0503e4b → 3.4.0-pr.feat-yaskawa-gp200s.437.1b5737e

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 (165) hide show
  1. package/README.md +61 -10
  2. package/dist/3d.cjs.js +2 -0
  3. package/dist/3d.cjs.js.map +1 -0
  4. package/dist/3d.d.ts +11 -0
  5. package/dist/3d.d.ts.map +1 -0
  6. package/dist/3d.es.js +16 -0
  7. package/dist/3d.es.js.map +1 -0
  8. package/dist/LoadingCover-Dr9hDTku.js +87 -0
  9. package/dist/LoadingCover-Dr9hDTku.js.map +1 -0
  10. package/dist/LoadingCover-r2yhJZF9.cjs +2 -0
  11. package/dist/LoadingCover-r2yhJZF9.cjs.map +1 -0
  12. package/dist/WandelscriptEditor-Dj7TBCkF.cjs +2 -0
  13. package/dist/WandelscriptEditor-Dj7TBCkF.cjs.map +1 -0
  14. package/dist/WandelscriptEditor-DnJvITTA.js +140 -0
  15. package/dist/WandelscriptEditor-DnJvITTA.js.map +1 -0
  16. package/dist/auth0-spa-js.production.esm-9WdmjTxR.js +1429 -0
  17. package/dist/auth0-spa-js.production.esm-9WdmjTxR.js.map +1 -0
  18. package/dist/auth0-spa-js.production.esm-BcLLh1tx.cjs +5 -0
  19. package/dist/auth0-spa-js.production.esm-BcLLh1tx.cjs.map +1 -0
  20. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts +1 -1
  21. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts.map +1 -1
  22. package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts.map +1 -1
  23. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts +1 -1
  24. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts.map +1 -1
  25. package/dist/components/3d-viewport/collider/ColliderElement.d.ts +1 -1
  26. package/dist/components/3d-viewport/collider/ColliderElement.d.ts.map +1 -1
  27. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts +1 -1
  28. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts.map +1 -1
  29. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts +1 -1
  30. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts.map +1 -1
  31. package/dist/components/ProgramStateIndicator.d.ts +3 -3
  32. package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
  33. package/dist/components/RobotCard.d.ts +4 -3
  34. package/dist/components/RobotCard.d.ts.map +1 -1
  35. package/dist/components/jogging/JoggingBlocked.d.ts +7 -0
  36. package/dist/components/jogging/JoggingBlocked.d.ts.map +1 -0
  37. package/dist/components/jogging/JoggingCartesianTab.d.ts.map +1 -1
  38. package/dist/components/jogging/JoggingOptions.d.ts.map +1 -1
  39. package/dist/components/jogging/JoggingPanel.d.ts +1 -1
  40. package/dist/components/jogging/JoggingPanel.d.ts.map +1 -1
  41. package/dist/components/jogging/JoggingStore.d.ts +10 -5
  42. package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
  43. package/dist/components/jogging/PoseCartesianValues.d.ts +2 -2
  44. package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
  45. package/dist/components/jogging/PoseJointValues.d.ts +1 -2
  46. package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
  47. package/dist/components/robots/DHRobot.d.ts.map +1 -1
  48. package/dist/components/robots/Robot.d.ts +1 -1
  49. package/dist/components/robots/Robot.d.ts.map +1 -1
  50. package/dist/components/robots/RobotAnimator.d.ts +2 -2
  51. package/dist/components/robots/RobotAnimator.d.ts.map +1 -1
  52. package/dist/components/robots/SupportedRobot.d.ts +3 -3
  53. package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
  54. package/dist/components/robots/manufacturerHomePositions.d.ts +1 -1
  55. package/dist/components/robots/manufacturerHomePositions.d.ts.map +1 -1
  56. package/dist/components/safetyBar/ControllerTypeIndicator.d.ts.map +1 -1
  57. package/dist/components/safetyBar/OperationModeIndicator.d.ts +2 -2
  58. package/dist/components/safetyBar/OperationModeIndicator.d.ts.map +1 -1
  59. package/dist/components/safetyBar/SafetyBar.d.ts +3 -3
  60. package/dist/components/safetyBar/SafetyBar.d.ts.map +1 -1
  61. package/dist/components/safetyBar/SafetyStateIndicator.d.ts +2 -2
  62. package/dist/components/safetyBar/SafetyStateIndicator.d.ts.map +1 -1
  63. package/dist/components/utils/errorHandling.d.ts.map +1 -1
  64. package/dist/components/utils/errorHandling.test.d.ts +2 -0
  65. package/dist/components/utils/errorHandling.test.d.ts.map +1 -0
  66. package/dist/core.cjs.js +2 -0
  67. package/dist/core.cjs.js.map +1 -0
  68. package/dist/core.d.ts +33 -0
  69. package/dist/core.d.ts.map +1 -0
  70. package/dist/core.es.js +54 -0
  71. package/dist/core.es.js.map +1 -0
  72. package/dist/index-CAib4NKw.js +2261 -0
  73. package/dist/index-CAib4NKw.js.map +1 -0
  74. package/dist/index-CqMZL0FV.cjs +2 -0
  75. package/dist/index-CqMZL0FV.cjs.map +1 -0
  76. package/dist/index-CxasuX80.js +5212 -0
  77. package/dist/index-CxasuX80.js.map +1 -0
  78. package/dist/index-DxwppshT.cjs +29 -0
  79. package/dist/index-DxwppshT.cjs.map +1 -0
  80. package/dist/index.cjs.js +2 -0
  81. package/dist/index.cjs.js.map +1 -0
  82. package/dist/index.d.ts +3 -39
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.es.js +69 -0
  85. package/dist/index.es.js.map +1 -0
  86. package/dist/lib/ConnectedMotionGroup.d.ts +90 -0
  87. package/dist/lib/ConnectedMotionGroup.d.ts.map +1 -0
  88. package/dist/lib/JoggerConnection.d.ts +113 -0
  89. package/dist/lib/JoggerConnection.d.ts.map +1 -0
  90. package/dist/lib/JoggerConnection.test.d.ts +2 -0
  91. package/dist/lib/JoggerConnection.test.d.ts.map +1 -0
  92. package/dist/lib/MotionStreamConnection.d.ts +24 -0
  93. package/dist/lib/MotionStreamConnection.d.ts.map +1 -0
  94. package/dist/lib/MotionStreamConnection.test.d.ts +2 -0
  95. package/dist/lib/MotionStreamConnection.test.d.ts.map +1 -0
  96. package/dist/lib/motionStateUpdate.d.ts +7 -0
  97. package/dist/lib/motionStateUpdate.d.ts.map +1 -0
  98. package/dist/lib/motionStateUpdate.test.d.ts +2 -0
  99. package/dist/lib/motionStateUpdate.test.d.ts.map +1 -0
  100. package/dist/manufacturerHomePositions-Ca80ycLi.cjs +2 -0
  101. package/dist/manufacturerHomePositions-Ca80ycLi.cjs.map +1 -0
  102. package/dist/manufacturerHomePositions-CgaG5vaK.js +976 -0
  103. package/dist/manufacturerHomePositions-CgaG5vaK.js.map +1 -0
  104. package/dist/theming-BQcKj8Gp.cjs +133 -0
  105. package/dist/theming-BQcKj8Gp.cjs.map +1 -0
  106. package/dist/theming-Bafjg0Wg.js +23460 -0
  107. package/dist/theming-Bafjg0Wg.js.map +1 -0
  108. package/dist/wandelscript.cjs.js +2 -0
  109. package/dist/wandelscript.cjs.js.map +1 -0
  110. package/dist/wandelscript.d.ts +2 -0
  111. package/dist/wandelscript.d.ts.map +1 -0
  112. package/dist/wandelscript.es.js +5 -0
  113. package/dist/wandelscript.es.js.map +1 -0
  114. package/package.json +49 -21
  115. package/src/3d.ts +15 -0
  116. package/src/components/3d-viewport/CoordinateSystemTransform.tsx +1 -1
  117. package/src/components/3d-viewport/SafetyZonesRenderer.tsx +1 -2
  118. package/src/components/3d-viewport/collider/ColliderCollection.tsx +1 -1
  119. package/src/components/3d-viewport/collider/ColliderElement.tsx +1 -1
  120. package/src/components/3d-viewport/collider/CollisionSceneRenderer.tsx +1 -1
  121. package/src/components/3d-viewport/collider/colliderShapeToBufferGeometry.ts +1 -1
  122. package/src/components/AppHeader.md +1 -1
  123. package/src/components/ProgramStateIndicator.tsx +3 -6
  124. package/src/components/RobotCard.tsx +4 -7
  125. package/src/components/jogging/JoggingBlocked.tsx +37 -0
  126. package/src/components/jogging/JoggingCartesianTab.tsx +13 -11
  127. package/src/components/jogging/JoggingJointLimitDetector.tsx +2 -2
  128. package/src/components/jogging/JoggingJointTab.tsx +4 -4
  129. package/src/components/jogging/JoggingOptions.tsx +6 -5
  130. package/src/components/jogging/JoggingPanel.tsx +6 -3
  131. package/src/components/jogging/JoggingStore.ts +66 -39
  132. package/src/components/jogging/PoseCartesianValues.tsx +3 -4
  133. package/src/components/jogging/PoseJointValues.tsx +3 -4
  134. package/src/components/robots/DHRobot.tsx +2 -3
  135. package/src/components/robots/Robot.tsx +1 -1
  136. package/src/components/robots/RobotAnimator.test.tsx +7 -22
  137. package/src/components/robots/RobotAnimator.tsx +8 -13
  138. package/src/components/robots/SupportedRobot.tsx +3 -6
  139. package/src/components/robots/manufacturerHomePositions.ts +1 -1
  140. package/src/components/safetyBar/ControllerTypeIndicator.tsx +4 -2
  141. package/src/components/safetyBar/OperationModeIndicator.tsx +7 -5
  142. package/src/components/safetyBar/SafetyBar.tsx +3 -6
  143. package/src/components/safetyBar/SafetyStateIndicator.tsx +9 -7
  144. package/src/components/utils/errorHandling.test.ts +41 -0
  145. package/src/components/utils/errorHandling.ts +4 -0
  146. package/src/core.ts +33 -0
  147. package/src/i18n/locales/de/translations.json +3 -0
  148. package/src/i18n/locales/en/translations.json +3 -0
  149. package/src/index.ts +4 -43
  150. package/src/lib/ConnectedMotionGroup.ts +444 -0
  151. package/src/lib/JoggerConnection.test.ts +120 -0
  152. package/src/lib/JoggerConnection.ts +674 -0
  153. package/src/lib/MotionStreamConnection.test.ts +23 -0
  154. package/src/lib/MotionStreamConnection.ts +189 -0
  155. package/src/lib/motionStateUpdate.test.ts +28 -0
  156. package/src/lib/motionStateUpdate.ts +117 -0
  157. package/src/wandelscript.ts +2 -0
  158. package/dist/auth0-spa-js.production.esm-1QXzndwB.js +0 -950
  159. package/dist/auth0-spa-js.production.esm-1QXzndwB.js.map +0 -1
  160. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs +0 -5
  161. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs.map +0 -1
  162. package/dist/index.cjs +0 -155
  163. package/dist/index.cjs.map +0 -1
  164. package/dist/index.js +0 -34927
  165. package/dist/index.js.map +0 -1
@@ -1,14 +1,18 @@
1
1
  import { tryParseJson } from "@wandelbots/nova-js"
2
2
  import type {
3
3
  CoordinateSystem,
4
- JoggerConnection,
5
- MotionGroupSpecification,
4
+ MotionGroupDescription,
6
5
  RobotTcp,
7
- } from "@wandelbots/nova-js/v1"
6
+ } from "@wandelbots/nova-js/v2"
8
7
  import { countBy } from "lodash-es"
9
8
  import keyBy from "lodash-es/keyBy"
10
9
  import uniqueId from "lodash-es/uniqueId"
11
10
  import { autorun, makeAutoObservable, type IReactionDisposer } from "mobx"
11
+ import type {
12
+ JoggerConnection,
13
+ JoggerOrientation,
14
+ Vector3Simple,
15
+ } from "../../lib/JoggerConnection"
12
16
 
13
17
  const discreteIncrementOptions = [
14
18
  { id: "0.1", mm: 0.1, degrees: 0.05 },
@@ -55,6 +59,9 @@ export class JoggingStore {
55
59
  /** Locks to prevent UI interactions during certain operations */
56
60
  locks = new Set<string>()
57
61
 
62
+ /** Block jogging UI interactions when connection is taken by another jogger */
63
+ blocked: boolean = false
64
+
58
65
  /**
59
66
  * Id of selected coordinate system from among those defined on the API side
60
67
  */
@@ -105,7 +112,7 @@ export class JoggingStore {
105
112
  maxRotationVelocityDegPerSec: number = 60
106
113
 
107
114
  /** Whether to show the coordinate system select dropdown in the UI */
108
- showCoordSystemSelect: boolean = true
115
+ showCoordSystemSelect: boolean = false
109
116
 
110
117
  /** Whether to show the TCP select dropdown in the UI */
111
118
  showTcpSelect: boolean = true
@@ -138,34 +145,34 @@ export class JoggingStore {
138
145
  const { nova } = jogger
139
146
 
140
147
  // Find out what TCPs this motion group has (we need it for jogging)
141
- const [motionGroupSpec, { coordinatesystems }, { tcps }] =
142
- await Promise.all([
143
- nova.api.motionGroupInfos.getMotionGroupSpecification(
144
- jogger.motionGroupId,
145
- ),
146
-
147
- // Fetch coord systems so user can select between them
148
- nova.api.coordinateSystems.listCoordinateSystems("ROTATION_VECTOR"),
149
-
150
- // Same for TCPs
151
- nova.api.motionGroupInfos.listTcps(
152
- jogger.motionGroupId,
153
- "ROTATION_VECTOR",
154
- ),
155
- ])
156
-
157
- return new JoggingStore(
158
- jogger,
159
- motionGroupSpec,
160
- coordinatesystems || [],
161
- tcps || [],
162
- )
148
+ const [coordinatesystems, description] = await Promise.all([
149
+ // Fetch coord systems so user can select between them
150
+ nova.api.controller.listCoordinateSystems(
151
+ jogger.motionStream.controllerId,
152
+ "ROTATION_VECTOR",
153
+ ),
154
+
155
+ // Same for TCPs and other info from description
156
+ nova.api.motionGroup.getMotionGroupDescription(
157
+ jogger.motionStream.controllerId,
158
+ jogger.motionGroupId,
159
+ ),
160
+ ])
161
+
162
+ const tcps = Object.entries(description.tcps || {}).map(([id, tcp]) => ({
163
+ id,
164
+ readable_name: tcp.name,
165
+ position: tcp.pose.position as Vector3Simple,
166
+ orientation: tcp.pose.orientation as Vector3Simple,
167
+ }))
168
+
169
+ return new JoggingStore(jogger, coordinatesystems || [], description, tcps)
163
170
  }
164
171
 
165
172
  constructor(
166
173
  readonly jogger: JoggerConnection,
167
- readonly motionGroupSpec: MotionGroupSpecification,
168
174
  readonly coordSystems: CoordinateSystem[],
175
+ readonly motionGroupDescription: MotionGroupDescription,
169
176
  readonly tcps: RobotTcp[],
170
177
  ) {
171
178
  // TODO workaround for default coord system on backend having a canonical id
@@ -179,13 +186,21 @@ export class JoggingStore {
179
186
  this.selectedCoordSystemId = coordSystems[0]?.coordinate_system || "world"
180
187
  this.selectedTcpId = tcps[0]?.id || ""
181
188
 
189
+ // Make all properties observable and actions auto-bound
182
190
  makeAutoObservable(this, {}, { autoBind: true })
183
191
 
192
+ // Register blocked watching
193
+ this.jogger.onBlocked = () => {
194
+ this.block()
195
+ }
196
+
184
197
  // Load user settings from local storage if available
185
198
  this.loadFromLocalStorage()
186
199
 
187
200
  // Automatically save user settings to local storage when save changes
188
201
  this.disposers.push(autorun(() => this.saveToLocalStorage()))
202
+
203
+ // Assign joggingStore to window
189
204
  ;(window as any).joggingStore = this
190
205
  }
191
206
 
@@ -201,30 +216,31 @@ export class JoggingStore {
201
216
  }
202
217
 
203
218
  async deactivate() {
204
- const websocket = this.jogger.activeWebsocket
205
-
206
- this.jogger.setJoggingMode("increment")
207
-
208
- if (websocket) {
209
- await websocket.closed()
219
+ if (this.jogger.mode === "jogging") {
220
+ return this.jogger.stop()
210
221
  }
211
222
  }
212
223
 
213
224
  /** Activate the jogger with current settings */
214
225
  async activate() {
215
226
  if (this.currentTab.id === "cartesian") {
216
- const cartesianJoggingOpts = {
217
- tcpId: this.selectedTcpId,
218
- coordSystemId: this.activeCoordSystemId,
227
+ if (
228
+ this.jogger.tcp !== this.selectedTcpId ||
229
+ this.jogger.orientation !== this.selectedOrientation
230
+ ) {
231
+ this.jogger.setOptions({
232
+ tcp: this.selectedTcpId,
233
+ orientation: this.selectedOrientation as JoggerOrientation,
234
+ })
219
235
  }
220
236
 
221
237
  if (this.activeDiscreteIncrement) {
222
- this.jogger.setJoggingMode("increment", cartesianJoggingOpts)
238
+ this.jogger.setJoggingMode("trajectory")
223
239
  } else {
224
- this.jogger.setJoggingMode("cartesian", cartesianJoggingOpts)
240
+ this.jogger.setJoggingMode("jogging")
225
241
  }
226
242
  } else {
227
- this.jogger.setJoggingMode("joint")
243
+ this.jogger.setJoggingMode("jogging")
228
244
  }
229
245
 
230
246
  return this.jogger
@@ -433,6 +449,17 @@ export class JoggingStore {
433
449
  this.locks.delete(id)
434
450
  }
435
451
 
452
+ block() {
453
+ this.blocked = true
454
+ }
455
+
456
+ unblock() {
457
+ this.blocked = false
458
+ if (this.jogger.mode === "jogging") {
459
+ this.jogger.initializeJoggingWebsocket()
460
+ }
461
+ }
462
+
436
463
  /** Lock the UI until the given async callback resolves */
437
464
  async withMotionLock(fn: () => Promise<void>) {
438
465
  const lockId = uniqueId()
@@ -1,13 +1,12 @@
1
1
  import { Button, Stack } from "@mui/material"
2
- import { poseToWandelscriptString } from "@wandelbots/nova-js"
3
- import type { TcpPose } from "@wandelbots/nova-js/v1"
2
+ import { poseToWandelscriptString, type Pose } from "@wandelbots/nova-js/v2"
4
3
  import { observer } from "mobx-react-lite"
5
4
  import { useState } from "react"
6
5
  import { externalizeComponent } from "../../externalizeComponent"
7
6
  import { CopyableText } from "../CopyableText"
8
7
 
9
8
  export type PoseCartesianValuesProps = {
10
- tcpPose: TcpPose
9
+ tcpPose: Pose
11
10
  showCopyButton?: boolean
12
11
  }
13
12
 
@@ -44,7 +43,7 @@ export const PoseCartesianValues = externalizeComponent(
44
43
  onClick={handleCopy}
45
44
  sx={{ flexShrink: 0 }}
46
45
  >
47
- { copyMessage ? copyMessage : "Copy"}
46
+ {copyMessage ? copyMessage : "Copy"}
48
47
  </Button>
49
48
  )}
50
49
  </Stack>
@@ -1,19 +1,18 @@
1
1
  import { Button, Stack } from "@mui/material"
2
- import type { Joints } from "@wandelbots/nova-api/v1"
3
2
  import { observer } from "mobx-react-lite"
4
3
  import { useState } from "react"
5
4
  import { externalizeComponent } from "../../externalizeComponent"
6
5
  import { CopyableText } from "../CopyableText"
7
6
 
8
7
  export type PoseJointValuesProps = {
9
- joints: Joints
8
+ joints: Array<number>
10
9
  showCopyButton?: boolean
11
10
  }
12
11
 
13
12
  export const PoseJointValues = externalizeComponent(
14
13
  observer(({ joints, showCopyButton = false }: PoseJointValuesProps) => {
15
14
  const [copyMessage, setCopyMessage] = useState<string | null>(null)
16
- const poseString = `[${joints.joints.map((j: number) => parseFloat(j.toFixed(4))).join(", ")}]`
15
+ const poseString = `[${joints.map((j: number) => parseFloat(j.toFixed(4))).join(", ")}]`
17
16
 
18
17
  const handleCopy = async () => {
19
18
  try {
@@ -43,7 +42,7 @@ export const PoseJointValues = externalizeComponent(
43
42
  onClick={handleCopy}
44
43
  sx={{ flexShrink: 0 }}
45
44
  >
46
- { copyMessage ? copyMessage : "Copy"}
45
+ {copyMessage ? copyMessage : "Copy"}
47
46
  </Button>
48
47
  )}
49
48
  </Stack>
@@ -1,5 +1,5 @@
1
1
  import { Line } from "@react-three/drei"
2
- import type { DHParameter } from "@wandelbots/nova-api/v1"
2
+ import type { DHParameter } from "@wandelbots/nova-js/v2"
3
3
  import React, { useRef } from "react"
4
4
  import type * as THREE from "three"
5
5
  import { Matrix4, Quaternion, Vector3 } from "three"
@@ -113,8 +113,7 @@ export function DHRobot({
113
113
  {dhParameters!.map((param, index) => {
114
114
  const { a, b } = getLinePoints(
115
115
  param,
116
- rapidlyChangingMotionState.state.joint_position.joints[index] ??
117
- 0,
116
+ rapidlyChangingMotionState.joint_position[index] ?? 0,
118
117
  )
119
118
  const jointName = `dhrobot_J0${index}`
120
119
  return (
@@ -1,7 +1,7 @@
1
1
  import type { ThreeElements } from "@react-three/fiber"
2
2
 
3
- import type { ConnectedMotionGroup } from "@wandelbots/nova-js/v1"
4
3
  import type { Group } from "three"
4
+ import type { ConnectedMotionGroup } from "../../lib/ConnectedMotionGroup"
5
5
  import { defaultGetModel } from "./robotModelLogic"
6
6
  import { SupportedRobot } from "./SupportedRobot"
7
7
 
@@ -1,7 +1,4 @@
1
- import type {
2
- DHParameter,
3
- MotionGroupStateResponse,
4
- } from "@wandelbots/nova-api/v1"
1
+ import type { DHParameter, MotionGroupState } from "@wandelbots/nova-api/v2"
5
2
  import { describe, expect, it, vi } from "vitest"
6
3
  import RobotAnimator from "./RobotAnimator"
7
4
 
@@ -26,12 +23,8 @@ describe("RobotAnimator", () => {
26
23
 
27
24
  it("should handle props with different numbers of joints", () => {
28
25
  // Test that the component accepts different numbers of DH parameters
29
- const mockMotionState4Joints: MotionGroupStateResponse = {
30
- state: {
31
- joint_position: {
32
- joints: [0.1, 0.2, 0.3, 0.4],
33
- },
34
- },
26
+ const mockMotionState4Joints: MotionGroupState = {
27
+ joint_position: [0.1, 0.2, 0.3, 0.4],
35
28
  } as any
36
29
 
37
30
  const mockDHParameters4Joints: DHParameter[] = [
@@ -41,12 +34,8 @@ describe("RobotAnimator", () => {
41
34
  { theta: 0, reverse_rotation_direction: false },
42
35
  ]
43
36
 
44
- const mockMotionState7Joints: MotionGroupStateResponse = {
45
- state: {
46
- joint_position: {
47
- joints: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7],
48
- },
49
- },
37
+ const mockMotionState7Joints: MotionGroupState = {
38
+ joint_position: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7],
50
39
  } as any
51
40
 
52
41
  const mockDHParameters7Joints: DHParameter[] = Array(7).fill({
@@ -63,9 +52,7 @@ describe("RobotAnimator", () => {
63
52
  }
64
53
  // Verify props are correctly typed
65
54
  expect(props4.dhParameters).toHaveLength(4)
66
- expect(
67
- props4.rapidlyChangingMotionState.state.joint_position.joints,
68
- ).toHaveLength(4)
55
+ expect(props4.rapidlyChangingMotionState.joint_position).toHaveLength(4)
69
56
  }).not.toThrow()
70
57
 
71
58
  expect(() => {
@@ -75,9 +62,7 @@ describe("RobotAnimator", () => {
75
62
  children: null,
76
63
  }
77
64
  expect(props7.dhParameters).toHaveLength(7)
78
- expect(
79
- props7.rapidlyChangingMotionState.state.joint_position.joints,
80
- ).toHaveLength(7)
65
+ expect(props7.rapidlyChangingMotionState.joint_position).toHaveLength(7)
81
66
  }).not.toThrow()
82
67
  })
83
68
 
@@ -1,8 +1,5 @@
1
1
  import { useFrame, useThree } from "@react-three/fiber"
2
- import type {
3
- DHParameter,
4
- MotionGroupStateResponse,
5
- } from "@wandelbots/nova-api/v1"
2
+ import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
6
3
  import React, { useEffect, useRef } from "react"
7
4
  import type { Group, Object3D } from "three"
8
5
  import { useAutorun } from "../utils/hooks"
@@ -10,7 +7,7 @@ import { ValueInterpolator } from "../utils/interpolation"
10
7
  import { collectJoints } from "./robotModelLogic"
11
8
 
12
9
  type RobotAnimatorProps = {
13
- rapidlyChangingMotionState: MotionGroupStateResponse
10
+ rapidlyChangingMotionState: MotionGroupState
14
11
  dhParameters: DHParameter[]
15
12
  onRotationChanged?: (joints: Object3D[], jointValues: number[]) => void
16
13
  children: React.ReactNode
@@ -29,10 +26,9 @@ export default function RobotAnimator({
29
26
 
30
27
  // Initialize interpolator
31
28
  useEffect(() => {
32
- const initialJointValues =
33
- rapidlyChangingMotionState.state.joint_position.joints.filter(
34
- (item) => item !== undefined,
35
- )
29
+ const initialJointValues = rapidlyChangingMotionState.joint_position.filter(
30
+ (item) => item !== undefined,
31
+ )
36
32
 
37
33
  interpolatorRef.current = new ValueInterpolator(initialJointValues, {
38
34
  tension: 120, // Controls spring stiffness - higher values create faster, more responsive motion
@@ -91,10 +87,9 @@ export default function RobotAnimator({
91
87
  }
92
88
 
93
89
  useAutorun(() => {
94
- const newJointValues =
95
- rapidlyChangingMotionState.state.joint_position.joints.filter(
96
- (item) => item !== undefined,
97
- )
90
+ const newJointValues = rapidlyChangingMotionState.joint_position.filter(
91
+ (item) => item !== undefined,
92
+ )
98
93
 
99
94
  requestAnimationFrame(() => updateJoints(newJointValues))
100
95
  })
@@ -1,8 +1,5 @@
1
1
  import type { ThreeElements } from "@react-three/fiber"
2
- import type {
3
- DHParameter,
4
- MotionGroupStateResponse,
5
- } from "@wandelbots/nova-api/v1"
2
+ import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
6
3
  import { Suspense, useCallback, useEffect, useState } from "react"
7
4
  import { DHRobot } from "./DHRobot"
8
5
 
@@ -16,12 +13,12 @@ import { applyGhostStyle, removeGhostStyle } from "./ghostStyle"
16
13
  import { defaultGetModel } from "./robotModelLogic"
17
14
 
18
15
  export type DHRobotProps = {
19
- rapidlyChangingMotionState: MotionGroupStateResponse
16
+ rapidlyChangingMotionState: MotionGroupState
20
17
  dhParameters: Array<DHParameter>
21
18
  } & ThreeElements["group"]
22
19
 
23
20
  export type SupportedRobotProps = {
24
- rapidlyChangingMotionState: MotionGroupStateResponse
21
+ rapidlyChangingMotionState: MotionGroupState
25
22
  modelFromController: string
26
23
  dhParameters: DHParameter[]
27
24
  flangeRef?: React.Ref<THREE.Group>
@@ -1,4 +1,4 @@
1
- import { Manufacturer } from "@wandelbots/nova-api/v1"
1
+ import { Manufacturer } from "@wandelbots/nova-js/v2"
2
2
 
3
3
  /**
4
4
  * Default home configs for different robot manufacturers.
@@ -1,5 +1,6 @@
1
1
  import { useTheme, type PopoverOrigin } from "@mui/material"
2
2
  import { observer } from "mobx-react-lite"
3
+ import { useId } from "react"
3
4
  import { Trans, useTranslation } from "react-i18next"
4
5
  import ControllerTypePhysicalIcon from "./icons/controller-type-physical.svg"
5
6
  import ControllerTypeVirtualIcon from "./icons/controller-type-virtual.svg"
@@ -22,12 +23,13 @@ export const ControllerTypeIndicator = observer(
22
23
  compact,
23
24
  }: ControllerTypeIndicatorProps) => {
24
25
  const theme = useTheme()
26
+ const componentId = useId()
25
27
  const { t } = useTranslation()
26
28
 
27
29
  if (isVirtual) {
28
30
  return (
29
31
  <IndicatorWithExplanation
30
- id="motion-group-virtual"
32
+ id={`motion-group-virtual-${componentId}`}
31
33
  icon={ControllerTypeVirtualIcon}
32
34
  color={theme.palette.tertiary.main}
33
35
  name={t("SafetyBar.ControllerType.Virtual.lb")}
@@ -52,7 +54,7 @@ export const ControllerTypeIndicator = observer(
52
54
 
53
55
  return (
54
56
  <IndicatorWithExplanation
55
- id="motion-group-physical"
57
+ id={`motion-group-physical-${componentId}`}
56
58
  icon={ControllerTypePhysicalIcon}
57
59
  color={theme.palette.primary.main}
58
60
  name={t("SafetyBar.ControllerType.Physical.lb")}
@@ -1,6 +1,7 @@
1
1
  import { useTheme, type PopoverOrigin } from "@mui/material"
2
- import type { RobotControllerStateOperationModeEnum } from "@wandelbots/nova-js/v1"
2
+ import type { OperationMode } from "@wandelbots/nova-js/v2"
3
3
  import { observer } from "mobx-react-lite"
4
+ import { useId } from "react"
4
5
  import { Trans, useTranslation } from "react-i18next"
5
6
  import OperationModeAutomaticIcon from "./icons/operation-mode-automatic.svg"
6
7
  import OperationModeErrorIcon from "./icons/operation-mode-error.svg"
@@ -8,7 +9,7 @@ import OperationModeManualIcon from "./icons/operation-mode-manual.svg"
8
9
  import { IndicatorWithExplanation } from "./IndicatorWithExplanation"
9
10
 
10
11
  interface OperationModeIndicatorProps {
11
- operationMode: RobotControllerStateOperationModeEnum
12
+ operationMode: OperationMode
12
13
  anchorOrigin?: PopoverOrigin
13
14
  transformOrigin?: PopoverOrigin
14
15
  compact: boolean
@@ -23,12 +24,13 @@ export const OperationModeIndicator = observer(
23
24
  }: OperationModeIndicatorProps) => {
24
25
  const { t } = useTranslation()
25
26
  const theme = useTheme()
27
+ const componentId = useId()
26
28
 
27
29
  switch (operationMode) {
28
30
  case "OPERATION_MODE_AUTO":
29
31
  return (
30
32
  <IndicatorWithExplanation
31
- id="operation-mode-auto"
33
+ id={`operation-mode-auto-${componentId}`}
32
34
  icon={OperationModeAutomaticIcon}
33
35
  title={t("SafetyBar.OperationMode.ti")}
34
36
  name={t("SafetyBar.OperationMode.Automatic.ti")}
@@ -49,7 +51,7 @@ export const OperationModeIndicator = observer(
49
51
  case "OPERATION_MODE_MANUAL_T2": {
50
52
  return (
51
53
  <IndicatorWithExplanation
52
- id="operation-mode-manual"
54
+ id={`operation-mode-manual-${componentId}`}
53
55
  icon={OperationModeManualIcon}
54
56
  color={theme.palette.warning.main}
55
57
  title={t("SafetyBar.OperationMode.ti")}
@@ -71,7 +73,7 @@ export const OperationModeIndicator = observer(
71
73
  default:
72
74
  return (
73
75
  <IndicatorWithExplanation
74
- id="operation-mode-error"
76
+ id={`operation-mode-error-${componentId}`}
75
77
  icon={OperationModeErrorIcon}
76
78
  color={theme.palette.warning.main}
77
79
  title={t("SafetyBar.OperationMode.ti")}
@@ -1,8 +1,5 @@
1
1
  import { Divider, Stack, type PopoverOrigin } from "@mui/material"
2
- import type {
3
- RobotControllerStateOperationModeEnum,
4
- RobotControllerStateSafetyStateEnum,
5
- } from "@wandelbots/nova-js/v1"
2
+ import type { OperationMode, SafetyStateType } from "@wandelbots/nova-js/v2"
6
3
  import { observer } from "mobx-react-lite"
7
4
  import { externalizeComponent } from "../../externalizeComponent"
8
5
  import { ControllerTypeIndicator } from "./ControllerTypeIndicator"
@@ -12,8 +9,8 @@ import { SafetyStateIndicator } from "./SafetyStateIndicator"
12
9
  export interface SafetyBarProps {
13
10
  isVirtual: boolean
14
11
  motionGroupId: string
15
- operationMode: RobotControllerStateOperationModeEnum
16
- safetyState: RobotControllerStateSafetyStateEnum
12
+ operationMode: OperationMode
13
+ safetyState: SafetyStateType
17
14
  anchorOrigin?: PopoverOrigin
18
15
  transformOrigin?: PopoverOrigin
19
16
  compact?: boolean
@@ -1,6 +1,7 @@
1
1
  import { useTheme, type PopoverOrigin } from "@mui/material"
2
- import type { RobotControllerStateSafetyStateEnum } from "@wandelbots/nova-js/v1"
2
+ import type { SafetyStateType } from "@wandelbots/nova-js/v2"
3
3
  import { observer } from "mobx-react-lite"
4
+ import { useId } from "react"
4
5
  import { Trans, useTranslation } from "react-i18next"
5
6
  import { assertUnreachable } from "../utils/errorHandling"
6
7
  import SafetyStateErrorIcon from "./icons/safety-state-error.svg"
@@ -11,7 +12,7 @@ import SafetyStateStopIcon from "./icons/safety-state-stop.svg"
11
12
  import { IndicatorWithExplanation } from "./IndicatorWithExplanation"
12
13
 
13
14
  interface SafetyStateIndicatorProps {
14
- safetyState: RobotControllerStateSafetyStateEnum
15
+ safetyState: SafetyStateType
15
16
  anchorOrigin?: PopoverOrigin
16
17
  transformOrigin?: PopoverOrigin
17
18
  compact: boolean
@@ -26,13 +27,14 @@ export const SafetyStateIndicator = observer(
26
27
  }: SafetyStateIndicatorProps) => {
27
28
  const { t } = useTranslation()
28
29
  const theme = useTheme()
30
+ const componentId = useId()
29
31
 
30
32
  switch (safetyState) {
31
33
  // Normal state, robot can move
32
34
  case "SAFETY_STATE_NORMAL":
33
35
  return (
34
36
  <IndicatorWithExplanation
35
- id="safety-state-normal"
37
+ id={`safety-state-normal-${componentId}`}
36
38
  title={t("SafetyBar.SafetyState.ti")}
37
39
  name={t("SafetyBar.SafetyState.Normal.lb")}
38
40
  label={compact ? null : t("SafetyBar.SafetyState.Normal.lb")}
@@ -54,7 +56,7 @@ export const SafetyStateIndicator = observer(
54
56
  case "SAFETY_STATE_ROBOT_EMERGENCY_STOP":
55
57
  return (
56
58
  <IndicatorWithExplanation
57
- id="safety-state-estop"
59
+ id={`safety-state-estop-${componentId}`}
58
60
  title={t("SafetyBar.SafetyState.ti")}
59
61
  name={t("SafetyBar.SafetyState.Estop.lb")}
60
62
  label={compact ? null : t("SafetyBar.SafetyState.Estop.lb")}
@@ -81,7 +83,7 @@ export const SafetyStateIndicator = observer(
81
83
  case "SAFETY_STATE_STOP":
82
84
  return (
83
85
  <IndicatorWithExplanation
84
- id="safety-state-stop"
86
+ id={`safety-state-stop-${componentId}`}
85
87
  icon={SafetyStateStopIcon}
86
88
  title={t("SafetyBar.SafetyState.ti")}
87
89
  name={t("SafetyBar.SafetyState.Stop.lb")}
@@ -108,7 +110,7 @@ export const SafetyStateIndicator = observer(
108
110
  case "SAFETY_STATE_VIOLATION":
109
111
  return (
110
112
  <IndicatorWithExplanation
111
- id="safety-state-manual-action-required"
113
+ id={`safety-state-manual-action-required-${componentId}`}
112
114
  icon={SafetyStateManualActionRequiredIcon}
113
115
  color={theme.palette.warning.main}
114
116
  title={t("SafetyBar.SafetyState.ti")}
@@ -135,7 +137,7 @@ export const SafetyStateIndicator = observer(
135
137
  case "SAFETY_STATE_FAULT":
136
138
  return (
137
139
  <IndicatorWithExplanation
138
- id="safety-state-error"
140
+ id={`safety-state-error-${componentId}`}
139
141
  icon={SafetyStateErrorIcon}
140
142
  color={theme.palette.error.main}
141
143
  title={t("SafetyBar.SafetyState.ti")}
@@ -0,0 +1,41 @@
1
+ import axios, { AxiosError, AxiosHeaders } from "axios"
2
+ import { expect, test } from "vitest"
3
+ import { makeErrorMessage } from "./errorHandling"
4
+
5
+ test("making useful error messages", async () => {
6
+ // Error objects take the message
7
+ const someCustomError = new Error("some custom error")
8
+ expect(makeErrorMessage(someCustomError)).toEqual("some custom error")
9
+
10
+ // Strings go through prefixed
11
+ expect(makeErrorMessage("some string")).toEqual(
12
+ 'Unexpected error: "some string"',
13
+ )
14
+
15
+ // Random objects get serialized
16
+ expect(makeErrorMessage({ some: "object" })).toEqual(
17
+ 'Unexpected error: {"some":"object"}',
18
+ )
19
+
20
+ // Axios errors with a response should include the response code
21
+ // and url - but not for 404, we use a friendly message for that
22
+ try {
23
+ await axios.get("http://example.com/doesnt-exist")
24
+ expect(true).toBe(false)
25
+ } catch (err) {
26
+ expect(makeErrorMessage(err)).toMatch(
27
+ "Failed to connect to the server. Please check your internet connection.",
28
+ )
29
+ }
30
+
31
+ // Not sure how to reproduce CORS errors naturally in vitest environment
32
+ // so let's create it manually
33
+ const networkError = new AxiosError("Network Error", "ERR_NETWORK", {
34
+ url: "http://example.com/some-cors-thing",
35
+ method: "post",
36
+ headers: new AxiosHeaders(),
37
+ })
38
+ expect(makeErrorMessage(networkError)).toEqual(
39
+ "Failed to connect to the server. Please check your internet connection.",
40
+ )
41
+ })
@@ -1,6 +1,10 @@
1
1
  import { AxiosError } from "axios"
2
2
  import { tryStringifyJson } from "./converters"
3
3
 
4
+ // Please note: These helper functions also exist in nova.js
5
+ // (with slightly different formatting), and will be unified
6
+ // at some point in the future.
7
+
4
8
  export function delay(ms: number) {
5
9
  return new Promise((resolve) => setTimeout(resolve, ms))
6
10
  }
package/src/core.ts ADDED
@@ -0,0 +1,33 @@
1
+ // Core components without heavy dependencies (Three.js, Monaco, MUI X)
2
+ export * from "./components/AppHeader"
3
+ export * from "./components/CycleTimer"
4
+ export * from "./components/DataGrid"
5
+ export * from "./components/jogging/JoggingCartesianAxisControl"
6
+ export * from "./components/jogging/JoggingJointRotationControl"
7
+ export * from "./components/jogging/JoggingPanel"
8
+ export { JoggingStore } from "./components/jogging/JoggingStore"
9
+ export * from "./components/jogging/PoseCartesianValues"
10
+ export * from "./components/jogging/PoseJointValues"
11
+ export * from "./components/LoadingCover"
12
+ export * from "./components/LogPanel"
13
+ export { LogStore } from "./components/LogStore"
14
+ export * from "./components/LogViewer"
15
+ export * from "./components/modal/NoMotionGroupModal"
16
+ export * from "./components/ProgramControl"
17
+ export * from "./components/ProgramStateIndicator"
18
+ export * from "./components/RobotListItem"
19
+ export * from "./components/RobotSetupReadinessIndicator"
20
+ export * from "./components/safetyBar/SafetyBar"
21
+ export * from "./components/SelectableFab"
22
+ export * from "./components/TabBar"
23
+ export * from "./components/Timer"
24
+ export * from "./components/utils/hooks"
25
+ export * from "./components/utils/interpolation"
26
+ export * from "./components/VelocitySlider"
27
+ export * from "./i18n/config"
28
+ export * from "./lib/ConnectedMotionGroup"
29
+ export * from "./lib/JoggerConnection"
30
+ export * from "./lib/motionStateUpdate"
31
+ export * from "./lib/MotionStreamConnection"
32
+ export * from "./themes/themeTypes"
33
+ export { createNovaMuiTheme } from "./themes/theming"