@wandelbots/wandelbots-js-react-components 2.59.0-pr.dev-fix-flaky-task.488.1957fef → 2.59.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 (172) hide show
  1. package/README.md +10 -107
  2. package/dist/auth0-spa-js.production.esm-1QXzndwB.js +950 -0
  3. package/dist/auth0-spa-js.production.esm-1QXzndwB.js.map +1 -0
  4. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs +5 -0
  5. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs.map +1 -0
  6. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts +1 -1
  7. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts.map +1 -1
  8. package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts.map +1 -1
  9. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts +1 -1
  10. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts.map +1 -1
  11. package/dist/components/3d-viewport/collider/ColliderElement.d.ts +1 -1
  12. package/dist/components/3d-viewport/collider/ColliderElement.d.ts.map +1 -1
  13. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts +1 -1
  14. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts.map +1 -1
  15. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts +1 -1
  16. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts.map +1 -1
  17. package/dist/components/ProgramStateIndicator.d.ts +3 -3
  18. package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
  19. package/dist/components/RobotCard.d.ts +4 -5
  20. package/dist/components/RobotCard.d.ts.map +1 -1
  21. package/dist/components/jogging/JoggingCartesianTab.d.ts.map +1 -1
  22. package/dist/components/jogging/JoggingOptions.d.ts.map +1 -1
  23. package/dist/components/jogging/JoggingPanel.d.ts +1 -1
  24. package/dist/components/jogging/JoggingPanel.d.ts.map +1 -1
  25. package/dist/components/jogging/JoggingStore.d.ts +5 -10
  26. package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
  27. package/dist/components/jogging/PoseCartesianValues.d.ts +2 -2
  28. package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
  29. package/dist/components/jogging/PoseJointValues.d.ts +2 -1
  30. package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
  31. package/dist/components/robots/DHRobot.d.ts.map +1 -1
  32. package/dist/components/robots/GenericRobot.d.ts +2 -2
  33. package/dist/components/robots/GenericRobot.d.ts.map +1 -1
  34. package/dist/components/robots/Robot.d.ts +2 -4
  35. package/dist/components/robots/Robot.d.ts.map +1 -1
  36. package/dist/components/robots/RobotAnimator.d.ts +2 -2
  37. package/dist/components/robots/RobotAnimator.d.ts.map +1 -1
  38. package/dist/components/robots/SupportedRobot.d.ts +4 -4
  39. package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
  40. package/dist/components/robots/manufacturerHomePositions.d.ts +1 -1
  41. package/dist/components/robots/manufacturerHomePositions.d.ts.map +1 -1
  42. package/dist/components/robots/robotModelLogic.d.ts +1 -11
  43. package/dist/components/robots/robotModelLogic.d.ts.map +1 -1
  44. package/dist/components/safetyBar/ControllerTypeIndicator.d.ts.map +1 -1
  45. package/dist/components/safetyBar/OperationModeIndicator.d.ts +2 -2
  46. package/dist/components/safetyBar/OperationModeIndicator.d.ts.map +1 -1
  47. package/dist/components/safetyBar/SafetyBar.d.ts +3 -3
  48. package/dist/components/safetyBar/SafetyBar.d.ts.map +1 -1
  49. package/dist/components/safetyBar/SafetyStateIndicator.d.ts +2 -2
  50. package/dist/components/safetyBar/SafetyStateIndicator.d.ts.map +1 -1
  51. package/dist/components/utils/errorHandling.d.ts.map +1 -1
  52. package/dist/index.cjs +160 -0
  53. package/dist/index.cjs.map +1 -0
  54. package/dist/index.d.ts +39 -3
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +36825 -0
  57. package/dist/index.js.map +1 -0
  58. package/package.json +32 -70
  59. package/src/components/3d-viewport/CoordinateSystemTransform.tsx +1 -1
  60. package/src/components/3d-viewport/SafetyZonesRenderer.tsx +2 -1
  61. package/src/components/3d-viewport/collider/ColliderCollection.tsx +1 -1
  62. package/src/components/3d-viewport/collider/ColliderElement.tsx +1 -1
  63. package/src/components/3d-viewport/collider/CollisionSceneRenderer.tsx +1 -1
  64. package/src/components/3d-viewport/collider/colliderShapeToBufferGeometry.ts +1 -1
  65. package/src/components/AppHeader.md +1 -1
  66. package/src/components/ProgramStateIndicator.tsx +6 -3
  67. package/src/components/RobotCard.tsx +8 -5
  68. package/src/components/jogging/JoggingCartesianTab.tsx +11 -13
  69. package/src/components/jogging/JoggingJointLimitDetector.tsx +2 -2
  70. package/src/components/jogging/JoggingJointTab.tsx +4 -4
  71. package/src/components/jogging/JoggingOptions.tsx +5 -6
  72. package/src/components/jogging/JoggingPanel.tsx +3 -6
  73. package/src/components/jogging/JoggingStore.ts +39 -66
  74. package/src/components/jogging/PoseCartesianValues.tsx +4 -3
  75. package/src/components/jogging/PoseJointValues.tsx +4 -3
  76. package/src/components/robots/DHRobot.tsx +3 -2
  77. package/src/components/robots/GenericRobot.tsx +36 -97
  78. package/src/components/robots/Robot.tsx +2 -4
  79. package/src/components/robots/RobotAnimator.test.tsx +22 -7
  80. package/src/components/robots/RobotAnimator.tsx +14 -9
  81. package/src/components/robots/SupportedRobot.tsx +9 -14
  82. package/src/components/robots/manufacturerHomePositions.ts +1 -1
  83. package/src/components/robots/robotModelLogic.ts +6 -75
  84. package/src/components/safetyBar/ControllerTypeIndicator.tsx +2 -4
  85. package/src/components/safetyBar/OperationModeIndicator.tsx +5 -7
  86. package/src/components/safetyBar/SafetyBar.tsx +6 -3
  87. package/src/components/safetyBar/SafetyStateIndicator.tsx +7 -9
  88. package/src/components/utils/errorHandling.ts +0 -4
  89. package/src/i18n/locales/de/translations.json +0 -3
  90. package/src/i18n/locales/en/translations.json +0 -3
  91. package/src/index.ts +43 -4
  92. package/dist/3d.cjs.js +0 -2
  93. package/dist/3d.cjs.js.map +0 -1
  94. package/dist/3d.d.ts +0 -11
  95. package/dist/3d.d.ts.map +0 -1
  96. package/dist/3d.es.js +0 -16
  97. package/dist/3d.es.js.map +0 -1
  98. package/dist/LoadingCover-6gWr11KP.js +0 -88
  99. package/dist/LoadingCover-6gWr11KP.js.map +0 -1
  100. package/dist/LoadingCover-CukpS_aj.cjs +0 -2
  101. package/dist/LoadingCover-CukpS_aj.cjs.map +0 -1
  102. package/dist/WandelscriptEditor-7eN-Yw7m.js +0 -140
  103. package/dist/WandelscriptEditor-7eN-Yw7m.js.map +0 -1
  104. package/dist/WandelscriptEditor-D6_vS5Uk.cjs +0 -2
  105. package/dist/WandelscriptEditor-D6_vS5Uk.cjs.map +0 -1
  106. package/dist/auth0-spa-js.production.esm-BMSlxZC5.js +0 -3877
  107. package/dist/auth0-spa-js.production.esm-BMSlxZC5.js.map +0 -1
  108. package/dist/auth0-spa-js.production.esm-DZ6lsBvD.cjs +0 -5
  109. package/dist/auth0-spa-js.production.esm-DZ6lsBvD.cjs.map +0 -1
  110. package/dist/components/jogging/JoggingBlocked.d.ts +0 -7
  111. package/dist/components/jogging/JoggingBlocked.d.ts.map +0 -1
  112. package/dist/components/utils/errorHandling.test.d.ts +0 -2
  113. package/dist/components/utils/errorHandling.test.d.ts.map +0 -1
  114. package/dist/core.cjs.js +0 -2
  115. package/dist/core.cjs.js.map +0 -1
  116. package/dist/core.d.ts +0 -33
  117. package/dist/core.d.ts.map +0 -1
  118. package/dist/core.es.js +0 -54
  119. package/dist/core.es.js.map +0 -1
  120. package/dist/externalizeComponent-CkVWk2F_.cjs +0 -24
  121. package/dist/externalizeComponent-CkVWk2F_.cjs.map +0 -1
  122. package/dist/externalizeComponent-Dc3fViZA.js +0 -489
  123. package/dist/externalizeComponent-Dc3fViZA.js.map +0 -1
  124. package/dist/index.cjs.js +0 -2
  125. package/dist/index.cjs.js.map +0 -1
  126. package/dist/index.es.js +0 -69
  127. package/dist/index.es.js.map +0 -1
  128. package/dist/interpolation-DAXKfoDS.cjs +0 -20
  129. package/dist/interpolation-DAXKfoDS.cjs.map +0 -1
  130. package/dist/interpolation-DcPbemBD.js +0 -6924
  131. package/dist/interpolation-DcPbemBD.js.map +0 -1
  132. package/dist/lib/ConnectedMotionGroup.d.ts +0 -90
  133. package/dist/lib/ConnectedMotionGroup.d.ts.map +0 -1
  134. package/dist/lib/JoggerConnection.d.ts +0 -113
  135. package/dist/lib/JoggerConnection.d.ts.map +0 -1
  136. package/dist/lib/JoggerConnection.test.d.ts +0 -2
  137. package/dist/lib/JoggerConnection.test.d.ts.map +0 -1
  138. package/dist/lib/MotionStreamConnection.d.ts +0 -24
  139. package/dist/lib/MotionStreamConnection.d.ts.map +0 -1
  140. package/dist/lib/MotionStreamConnection.test.d.ts +0 -2
  141. package/dist/lib/MotionStreamConnection.test.d.ts.map +0 -1
  142. package/dist/lib/motionStateUpdate.d.ts +0 -7
  143. package/dist/lib/motionStateUpdate.d.ts.map +0 -1
  144. package/dist/lib/motionStateUpdate.test.d.ts +0 -2
  145. package/dist/lib/motionStateUpdate.test.d.ts.map +0 -1
  146. package/dist/manufacturerHomePositions-BD6C5qZJ.js +0 -1040
  147. package/dist/manufacturerHomePositions-BD6C5qZJ.js.map +0 -1
  148. package/dist/manufacturerHomePositions-DRNjU1pU.cjs +0 -2
  149. package/dist/manufacturerHomePositions-DRNjU1pU.cjs.map +0 -1
  150. package/dist/theming-CPShzNuV.cjs +0 -115
  151. package/dist/theming-CPShzNuV.cjs.map +0 -1
  152. package/dist/theming-Hr605E6v.js +0 -22336
  153. package/dist/theming-Hr605E6v.js.map +0 -1
  154. package/dist/wandelscript.cjs.js +0 -2
  155. package/dist/wandelscript.cjs.js.map +0 -1
  156. package/dist/wandelscript.d.ts +0 -2
  157. package/dist/wandelscript.d.ts.map +0 -1
  158. package/dist/wandelscript.es.js +0 -5
  159. package/dist/wandelscript.es.js.map +0 -1
  160. package/src/3d.ts +0 -15
  161. package/src/components/jogging/JoggingBlocked.tsx +0 -37
  162. package/src/components/utils/errorHandling.test.ts +0 -41
  163. package/src/core.ts +0 -33
  164. package/src/env.d.ts +0 -3
  165. package/src/lib/ConnectedMotionGroup.ts +0 -444
  166. package/src/lib/JoggerConnection.test.ts +0 -120
  167. package/src/lib/JoggerConnection.ts +0 -674
  168. package/src/lib/MotionStreamConnection.test.ts +0 -23
  169. package/src/lib/MotionStreamConnection.ts +0 -189
  170. package/src/lib/motionStateUpdate.test.ts +0 -28
  171. package/src/lib/motionStateUpdate.ts +0 -117
  172. package/src/wandelscript.ts +0 -2
@@ -1,18 +1,14 @@
1
1
  import { tryParseJson } from "@wandelbots/nova-js"
2
2
  import type {
3
3
  CoordinateSystem,
4
- MotionGroupDescription,
4
+ JoggerConnection,
5
+ MotionGroupSpecification,
5
6
  RobotTcp,
6
- } from "@wandelbots/nova-js/v2"
7
+ } from "@wandelbots/nova-js/v1"
7
8
  import { countBy } from "lodash-es"
8
9
  import keyBy from "lodash-es/keyBy"
9
10
  import uniqueId from "lodash-es/uniqueId"
10
11
  import { autorun, makeAutoObservable, type IReactionDisposer } from "mobx"
11
- import type {
12
- JoggerConnection,
13
- JoggerOrientation,
14
- Vector3Simple,
15
- } from "../../lib/JoggerConnection"
16
12
 
17
13
  const discreteIncrementOptions = [
18
14
  { id: "0.1", mm: 0.1, degrees: 0.05 },
@@ -59,9 +55,6 @@ export class JoggingStore {
59
55
  /** Locks to prevent UI interactions during certain operations */
60
56
  locks = new Set<string>()
61
57
 
62
- /** Block jogging UI interactions when connection is taken by another jogger */
63
- blocked: boolean = false
64
-
65
58
  /**
66
59
  * Id of selected coordinate system from among those defined on the API side
67
60
  */
@@ -112,7 +105,7 @@ export class JoggingStore {
112
105
  maxRotationVelocityDegPerSec: number = 60
113
106
 
114
107
  /** Whether to show the coordinate system select dropdown in the UI */
115
- showCoordSystemSelect: boolean = false
108
+ showCoordSystemSelect: boolean = true
116
109
 
117
110
  /** Whether to show the TCP select dropdown in the UI */
118
111
  showTcpSelect: boolean = true
@@ -145,34 +138,34 @@ export class JoggingStore {
145
138
  const { nova } = jogger
146
139
 
147
140
  // Find out what TCPs this motion group has (we need it for jogging)
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)
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
+ )
170
163
  }
171
164
 
172
165
  constructor(
173
166
  readonly jogger: JoggerConnection,
167
+ readonly motionGroupSpec: MotionGroupSpecification,
174
168
  readonly coordSystems: CoordinateSystem[],
175
- readonly motionGroupDescription: MotionGroupDescription,
176
169
  readonly tcps: RobotTcp[],
177
170
  ) {
178
171
  // TODO workaround for default coord system on backend having a canonical id
@@ -186,21 +179,13 @@ export class JoggingStore {
186
179
  this.selectedCoordSystemId = coordSystems[0]?.coordinate_system || "world"
187
180
  this.selectedTcpId = tcps[0]?.id || ""
188
181
 
189
- // Make all properties observable and actions auto-bound
190
182
  makeAutoObservable(this, {}, { autoBind: true })
191
183
 
192
- // Register blocked watching
193
- this.jogger.onBlocked = () => {
194
- this.block()
195
- }
196
-
197
184
  // Load user settings from local storage if available
198
185
  this.loadFromLocalStorage()
199
186
 
200
187
  // Automatically save user settings to local storage when save changes
201
188
  this.disposers.push(autorun(() => this.saveToLocalStorage()))
202
-
203
- // Assign joggingStore to window
204
189
  ;(window as any).joggingStore = this
205
190
  }
206
191
 
@@ -216,31 +201,30 @@ export class JoggingStore {
216
201
  }
217
202
 
218
203
  async deactivate() {
219
- if (this.jogger.mode === "jogging") {
220
- return this.jogger.stop()
204
+ const websocket = this.jogger.activeWebsocket
205
+
206
+ this.jogger.setJoggingMode("increment")
207
+
208
+ if (websocket) {
209
+ await websocket.closed()
221
210
  }
222
211
  }
223
212
 
224
213
  /** Activate the jogger with current settings */
225
214
  async activate() {
226
215
  if (this.currentTab.id === "cartesian") {
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
- })
216
+ const cartesianJoggingOpts = {
217
+ tcpId: this.selectedTcpId,
218
+ coordSystemId: this.activeCoordSystemId,
235
219
  }
236
220
 
237
221
  if (this.activeDiscreteIncrement) {
238
- this.jogger.setJoggingMode("trajectory")
222
+ this.jogger.setJoggingMode("increment", cartesianJoggingOpts)
239
223
  } else {
240
- this.jogger.setJoggingMode("jogging")
224
+ this.jogger.setJoggingMode("cartesian", cartesianJoggingOpts)
241
225
  }
242
226
  } else {
243
- this.jogger.setJoggingMode("jogging")
227
+ this.jogger.setJoggingMode("joint")
244
228
  }
245
229
 
246
230
  return this.jogger
@@ -449,17 +433,6 @@ export class JoggingStore {
449
433
  this.locks.delete(id)
450
434
  }
451
435
 
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
-
463
436
  /** Lock the UI until the given async callback resolves */
464
437
  async withMotionLock(fn: () => Promise<void>) {
465
438
  const lockId = uniqueId()
@@ -1,12 +1,13 @@
1
1
  import { Button, Stack } from "@mui/material"
2
- import { poseToWandelscriptString, type Pose } from "@wandelbots/nova-js/v2"
2
+ import { poseToWandelscriptString } from "@wandelbots/nova-js"
3
+ import type { TcpPose } from "@wandelbots/nova-js/v1"
3
4
  import { observer } from "mobx-react-lite"
4
5
  import { useState } from "react"
5
6
  import { externalizeComponent } from "../../externalizeComponent"
6
7
  import { CopyableText } from "../CopyableText"
7
8
 
8
9
  export type PoseCartesianValuesProps = {
9
- tcpPose: Pose
10
+ tcpPose: TcpPose
10
11
  showCopyButton?: boolean
11
12
  }
12
13
 
@@ -43,7 +44,7 @@ export const PoseCartesianValues = externalizeComponent(
43
44
  onClick={handleCopy}
44
45
  sx={{ flexShrink: 0 }}
45
46
  >
46
- {copyMessage ? copyMessage : "Copy"}
47
+ { copyMessage ? copyMessage : "Copy"}
47
48
  </Button>
48
49
  )}
49
50
  </Stack>
@@ -1,18 +1,19 @@
1
1
  import { Button, Stack } from "@mui/material"
2
+ import type { Joints } from "@wandelbots/nova-api/v1"
2
3
  import { observer } from "mobx-react-lite"
3
4
  import { useState } from "react"
4
5
  import { externalizeComponent } from "../../externalizeComponent"
5
6
  import { CopyableText } from "../CopyableText"
6
7
 
7
8
  export type PoseJointValuesProps = {
8
- joints: Array<number>
9
+ joints: Joints
9
10
  showCopyButton?: boolean
10
11
  }
11
12
 
12
13
  export const PoseJointValues = externalizeComponent(
13
14
  observer(({ joints, showCopyButton = false }: PoseJointValuesProps) => {
14
15
  const [copyMessage, setCopyMessage] = useState<string | null>(null)
15
- const poseString = `[${joints.map((j: number) => parseFloat(j.toFixed(4))).join(", ")}]`
16
+ const poseString = `[${joints.joints.map((j: number) => parseFloat(j.toFixed(4))).join(", ")}]`
16
17
 
17
18
  const handleCopy = async () => {
18
19
  try {
@@ -42,7 +43,7 @@ export const PoseJointValues = externalizeComponent(
42
43
  onClick={handleCopy}
43
44
  sx={{ flexShrink: 0 }}
44
45
  >
45
- {copyMessage ? copyMessage : "Copy"}
46
+ { copyMessage ? copyMessage : "Copy"}
46
47
  </Button>
47
48
  )}
48
49
  </Stack>
@@ -1,5 +1,5 @@
1
1
  import { Line } from "@react-three/drei"
2
- import type { DHParameter } from "@wandelbots/nova-js/v2"
2
+ import type { DHParameter } from "@wandelbots/nova-api/v1"
3
3
  import React, { useRef } from "react"
4
4
  import type * as THREE from "three"
5
5
  import { Matrix4, Quaternion, Vector3 } from "three"
@@ -113,7 +113,8 @@ export function DHRobot({
113
113
  {dhParameters!.map((param, index) => {
114
114
  const { a, b } = getLinePoints(
115
115
  param,
116
- rapidlyChangingMotionState.joint_position[index] ?? 0,
116
+ rapidlyChangingMotionState.state.joint_position.joints[index] ??
117
+ 0,
117
118
  )
118
119
  const jointName = `dhrobot_J0${index}`
119
120
  return (
@@ -1,12 +1,12 @@
1
1
  import { useGLTF } from "@react-three/drei"
2
2
  import type { ThreeElements } from "@react-three/fiber"
3
- import React, { useCallback, useEffect, useState } from "react"
3
+ import React, { useCallback } from "react"
4
4
  import type { Group, Mesh } from "three"
5
5
  import { type Object3D } from "three"
6
6
  import { isFlange, parseRobotModel } from "./robotModelLogic"
7
7
 
8
8
  export type RobotModelProps = {
9
- modelURL: string | Promise<string>
9
+ modelURL: string
10
10
  /**
11
11
  * Called after a robot model has been loaded and
12
12
  * rendered into the threejs scene
@@ -19,25 +19,16 @@ function isMesh(node: Object3D): node is Mesh {
19
19
  return node.type === "Mesh"
20
20
  }
21
21
 
22
- // Separate component that only renders when we have a valid URL
23
- function LoadedRobotModel({
24
- url,
25
- flangeRef,
26
- postModelRender,
27
- ...props
28
- }: {
29
- url: string
30
- flangeRef?: React.Ref<Group>
31
- postModelRender?: () => void
32
- } & ThreeElements["group"]) {
33
- const gltfResult = useGLTF(url)
34
- let gltf
35
- try {
36
- const parsed = parseRobotModel(gltfResult, 'robot.glb')
37
- gltf = parsed.gltf
38
- } catch (err) {
39
- throw err;
40
- }
22
+ export function GenericRobot({
23
+ modelURL,
24
+ flangeRef,
25
+ postModelRender,
26
+ ...props
27
+ }: RobotModelProps) {
28
+ const { gltf } = parseRobotModel(
29
+ useGLTF(modelURL),
30
+ modelURL.split("/").pop() || modelURL,
31
+ )
41
32
 
42
33
  const groupRef: React.RefCallback<Group> = useCallback(
43
34
  (group) => {
@@ -45,45 +36,33 @@ function LoadedRobotModel({
45
36
  postModelRender()
46
37
  }
47
38
  },
48
- [postModelRender],
39
+ [modelURL],
49
40
  )
50
41
 
51
42
  function renderNode(node: Object3D): React.ReactNode {
52
- try {
53
- if (isMesh(node)) {
54
- // Defensive: only render mesh if geometry exists
55
- if ((node as Mesh).geometry) {
56
- return (
57
- <mesh
58
- name={node.name}
59
- key={node.uuid}
60
- geometry={(node as Mesh).geometry}
61
- material={(node as Mesh).material}
62
- position={node.position}
63
- rotation={node.rotation}
64
- />
65
- )
66
- }
67
- // Fallback to empty group if geometry is missing
68
- return (
69
- <group name={node.name} key={node.uuid} position={node.position} rotation={node.rotation} />
70
- )
71
- } else {
72
- return (
73
- <group
74
- name={node.name}
75
- key={node.uuid}
76
- position={node.position}
77
- rotation={node.rotation}
78
- ref={isFlange(node) ? flangeRef : undefined}
79
- >
80
- {node.children.map(renderNode)}
81
- </group>
82
- )
83
- }
84
- } catch (e) {
85
- console.warn('Error rendering node', node.name, e)
86
- return null
43
+ if (isMesh(node)) {
44
+ return (
45
+ <mesh
46
+ name={node.name}
47
+ key={node.uuid}
48
+ geometry={node.geometry}
49
+ material={node.material}
50
+ position={node.position}
51
+ rotation={node.rotation}
52
+ />
53
+ )
54
+ } else {
55
+ return (
56
+ <group
57
+ name={node.name}
58
+ key={node.uuid}
59
+ position={node.position}
60
+ rotation={node.rotation}
61
+ ref={isFlange(node) ? flangeRef : undefined}
62
+ >
63
+ {node.children.map(renderNode)}
64
+ </group>
65
+ )
87
66
  }
88
67
  }
89
68
 
@@ -93,43 +72,3 @@ function LoadedRobotModel({
93
72
  </group>
94
73
  )
95
74
  }
96
-
97
- export function GenericRobot({
98
- modelURL,
99
- flangeRef,
100
- postModelRender,
101
- ...props
102
- }: RobotModelProps) {
103
- const [resolvedURL, setResolvedURL] = useState<string | null>(null)
104
-
105
- useEffect(() => {
106
- const resolveURL = async () => {
107
- try {
108
- if (typeof modelURL === 'string') {
109
- setResolvedURL(modelURL)
110
- } else {
111
- const url = await modelURL
112
- setResolvedURL(url)
113
- }
114
- } catch (error) {
115
- console.error('Failed to resolve model URL:', error)
116
- }
117
- }
118
-
119
- resolveURL()
120
- }, [modelURL])
121
-
122
- // Don't render until we have a resolved URL
123
- if (!resolvedURL) {
124
- return null // Loading state
125
- }
126
-
127
- return (
128
- <LoadedRobotModel
129
- url={resolvedURL}
130
- flangeRef={flangeRef}
131
- postModelRender={postModelRender}
132
- {...props}
133
- />
134
- )
135
- }
@@ -1,13 +1,13 @@
1
1
  import type { ThreeElements } from "@react-three/fiber"
2
2
 
3
+ import type { ConnectedMotionGroup } from "@wandelbots/nova-js/v1"
3
4
  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
 
8
8
  export type RobotProps = {
9
9
  connectedMotionGroup: ConnectedMotionGroup
10
- getModel?: (modelFromController: string) => Promise<string>
10
+ getModel?: (modelFromController: string) => string
11
11
  flangeRef?: React.Ref<Group>
12
12
  transparentColor?: string
13
13
  postModelRender?: () => void
@@ -51,5 +51,3 @@ export function Robot({
51
51
  />
52
52
  )
53
53
  }
54
-
55
- export { defaultGetModel }
@@ -1,4 +1,7 @@
1
- import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
1
+ import type {
2
+ DHParameter,
3
+ MotionGroupStateResponse,
4
+ } from "@wandelbots/nova-api/v1"
2
5
  import { describe, expect, it, vi } from "vitest"
3
6
  import RobotAnimator from "./RobotAnimator"
4
7
 
@@ -23,8 +26,12 @@ describe("RobotAnimator", () => {
23
26
 
24
27
  it("should handle props with different numbers of joints", () => {
25
28
  // Test that the component accepts different numbers of DH parameters
26
- const mockMotionState4Joints: MotionGroupState = {
27
- joint_position: [0.1, 0.2, 0.3, 0.4],
29
+ const mockMotionState4Joints: MotionGroupStateResponse = {
30
+ state: {
31
+ joint_position: {
32
+ joints: [0.1, 0.2, 0.3, 0.4],
33
+ },
34
+ },
28
35
  } as any
29
36
 
30
37
  const mockDHParameters4Joints: DHParameter[] = [
@@ -34,8 +41,12 @@ describe("RobotAnimator", () => {
34
41
  { theta: 0, reverse_rotation_direction: false },
35
42
  ]
36
43
 
37
- const mockMotionState7Joints: MotionGroupState = {
38
- joint_position: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7],
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
+ },
39
50
  } as any
40
51
 
41
52
  const mockDHParameters7Joints: DHParameter[] = Array(7).fill({
@@ -52,7 +63,9 @@ describe("RobotAnimator", () => {
52
63
  }
53
64
  // Verify props are correctly typed
54
65
  expect(props4.dhParameters).toHaveLength(4)
55
- expect(props4.rapidlyChangingMotionState.joint_position).toHaveLength(4)
66
+ expect(
67
+ props4.rapidlyChangingMotionState.state.joint_position.joints,
68
+ ).toHaveLength(4)
56
69
  }).not.toThrow()
57
70
 
58
71
  expect(() => {
@@ -62,7 +75,9 @@ describe("RobotAnimator", () => {
62
75
  children: null,
63
76
  }
64
77
  expect(props7.dhParameters).toHaveLength(7)
65
- expect(props7.rapidlyChangingMotionState.joint_position).toHaveLength(7)
78
+ expect(
79
+ props7.rapidlyChangingMotionState.state.joint_position.joints,
80
+ ).toHaveLength(7)
66
81
  }).not.toThrow()
67
82
  })
68
83
 
@@ -1,13 +1,16 @@
1
1
  import { useFrame, useThree } from "@react-three/fiber"
2
- import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
3
- import React, { useEffect, useRef, useCallback } from "react"
2
+ import type {
3
+ DHParameter,
4
+ MotionGroupStateResponse,
5
+ } from "@wandelbots/nova-api/v1"
6
+ import React, { useCallback, useEffect, useRef } from "react"
4
7
  import type { Group, Object3D } from "three"
5
8
  import { useAutorun } from "../utils/hooks"
6
9
  import { ValueInterpolator } from "../utils/interpolation"
7
10
  import { collectJoints } from "./robotModelLogic"
8
11
 
9
12
  type RobotAnimatorProps = {
10
- rapidlyChangingMotionState: MotionGroupState
13
+ rapidlyChangingMotionState: MotionGroupStateResponse
11
14
  dhParameters: DHParameter[]
12
15
  onRotationChanged?: (joints: Object3D[], jointValues: number[]) => void
13
16
  children: React.ReactNode
@@ -26,9 +29,10 @@ export default function RobotAnimator({
26
29
 
27
30
  // Initialize interpolator
28
31
  useEffect(() => {
29
- const initialJointValues = rapidlyChangingMotionState.joint_position.filter(
30
- (item) => item !== undefined,
31
- )
32
+ const initialJointValues =
33
+ rapidlyChangingMotionState.state.joint_position.joints.filter(
34
+ (item) => item !== undefined,
35
+ )
32
36
 
33
37
  interpolatorRef.current = new ValueInterpolator(initialJointValues, {
34
38
  tension: 120, // Controls spring stiffness - higher values create faster, more responsive motion
@@ -82,9 +86,10 @@ export default function RobotAnimator({
82
86
  }
83
87
 
84
88
  const updateJoints = useCallback(() => {
85
- const newJointValues = rapidlyChangingMotionState.joint_position.filter(
86
- (item) => item !== undefined,
87
- )
89
+ const newJointValues =
90
+ rapidlyChangingMotionState.state.joint_position.joints.filter(
91
+ (item) => item !== undefined,
92
+ )
88
93
 
89
94
  requestAnimationFrame(() => {
90
95
  jointValues.current = newJointValues
@@ -1,5 +1,8 @@
1
1
  import type { ThreeElements } from "@react-three/fiber"
2
- import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
2
+ import type {
3
+ DHParameter,
4
+ MotionGroupStateResponse,
5
+ } from "@wandelbots/nova-api/v1"
3
6
  import { Suspense, useCallback, useEffect, useState } from "react"
4
7
  import { DHRobot } from "./DHRobot"
5
8
 
@@ -13,16 +16,16 @@ import { applyGhostStyle, removeGhostStyle } from "./ghostStyle"
13
16
  import { defaultGetModel } from "./robotModelLogic"
14
17
 
15
18
  export type DHRobotProps = {
16
- rapidlyChangingMotionState: MotionGroupState
19
+ rapidlyChangingMotionState: MotionGroupStateResponse
17
20
  dhParameters: Array<DHParameter>
18
21
  } & ThreeElements["group"]
19
22
 
20
23
  export type SupportedRobotProps = {
21
- rapidlyChangingMotionState: MotionGroupState
24
+ rapidlyChangingMotionState: MotionGroupStateResponse
22
25
  modelFromController: string
23
26
  dhParameters: DHParameter[]
24
27
  flangeRef?: React.Ref<THREE.Group>
25
- getModel?: (modelFromController: string) => Promise<string> | undefined
28
+ getModel?: (modelFromController: string) => string
26
29
  postModelRender?: () => void
27
30
  transparentColor?: string
28
31
  } & ThreeElements["group"]
@@ -67,7 +70,7 @@ export const SupportedRobot = externalizeComponent(
67
70
  fallback={dhrobot}
68
71
  onError={(err) => {
69
72
  // Missing model; show the fallback for now
70
- console.warn(err)
73
+ console.error(err)
71
74
  }}
72
75
  >
73
76
  <Suspense fallback={dhrobot}>
@@ -77,15 +80,7 @@ export const SupportedRobot = externalizeComponent(
77
80
  dhParameters={dhParameters}
78
81
  >
79
82
  <GenericRobot
80
- modelURL={(() => {
81
- const result = getModel(modelFromController)
82
- if (!result) {
83
- const mockBlob = new Blob([], { type: 'model/gltf-binary' })
84
- const mockFile = new File([mockBlob], `${modelFromController}.glb`, { type: 'model/gltf-binary' })
85
- return Promise.resolve(URL.createObjectURL(mockFile))
86
- }
87
- return result
88
- })()}
83
+ modelURL={getModel(modelFromController)}
89
84
  postModelRender={postModelRender}
90
85
  flangeRef={flangeRef}
91
86
  {...props}
@@ -1,4 +1,4 @@
1
- import { Manufacturer } from "@wandelbots/nova-js/v2"
1
+ import { Manufacturer } from "@wandelbots/nova-api/v1"
2
2
 
3
3
  /**
4
4
  * Default home configs for different robot manufacturers.