@wandelbots/wandelbots-js-react-components 4.2.0 → 4.3.0-pr.feat-RB-3171-dynamic-motion-visualization.517.0fc2fb2

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 (57) hide show
  1. package/README.md +1 -1
  2. package/dist/3d.cjs.js +1 -1
  3. package/dist/3d.es.js +1 -1
  4. package/dist/MotionGroupVisualizer-DptISfx-.cjs +2 -0
  5. package/dist/{MotionGroupVisualizer-C3CB-L2z.cjs.map → MotionGroupVisualizer-DptISfx-.cjs.map} +1 -1
  6. package/dist/{MotionGroupVisualizer-CrLamHYm.js → MotionGroupVisualizer-HpVtcaDR.js} +307 -343
  7. package/dist/{MotionGroupVisualizer-CrLamHYm.js.map → MotionGroupVisualizer-HpVtcaDR.js.map} +1 -1
  8. package/dist/{auth0-spa-js.production.esm-mvPojIrB.js → auth0-spa-js.production.esm-DNao6_S5.js} +1478 -1457
  9. package/dist/auth0-spa-js.production.esm-DNao6_S5.js.map +1 -0
  10. package/dist/auth0-spa-js.production.esm-DaBMfOV8.cjs +5 -0
  11. package/dist/auth0-spa-js.production.esm-DaBMfOV8.cjs.map +1 -0
  12. package/dist/components/jogging/JoggingJointTab.d.ts +1 -1
  13. package/dist/components/jogging/JoggingJointTab.d.ts.map +1 -1
  14. package/dist/components/jogging/JoggingJointValueControl.d.ts +16 -0
  15. package/dist/components/jogging/JoggingJointValueControl.d.ts.map +1 -0
  16. package/dist/components/jogging/JoggingStore.d.ts +17 -19
  17. package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
  18. package/dist/components/robots/MotionGroupVisualizer.d.ts +1 -1
  19. package/dist/components/robots/MotionGroupVisualizer.d.ts.map +1 -1
  20. package/dist/core.cjs.js +1 -1
  21. package/dist/core.d.ts +1 -1
  22. package/dist/core.d.ts.map +1 -1
  23. package/dist/core.es.js +8 -8
  24. package/dist/index.cjs.js +1 -1
  25. package/dist/index.es.js +10 -10
  26. package/dist/interpolation-BoUHwUGn.cjs +20 -0
  27. package/dist/interpolation-BoUHwUGn.cjs.map +1 -0
  28. package/dist/{interpolation-Cs2pC1zE.js → interpolation-CQDo4nal.js} +3042 -2894
  29. package/dist/interpolation-CQDo4nal.js.map +1 -0
  30. package/dist/lib/ConnectedMotionGroup.d.ts +1 -0
  31. package/dist/lib/ConnectedMotionGroup.d.ts.map +1 -1
  32. package/dist/lib/JoggerConnection.d.ts +4 -3
  33. package/dist/lib/JoggerConnection.d.ts.map +1 -1
  34. package/dist/{theming-C-zvh022.js → theming-B0LgsoBF.js} +2915 -2891
  35. package/dist/theming-B0LgsoBF.js.map +1 -0
  36. package/dist/{theming-Dk07SE2_.cjs → theming-BfCyghaY.cjs} +36 -36
  37. package/dist/theming-BfCyghaY.cjs.map +1 -0
  38. package/package.json +2 -2
  39. package/src/components/jogging/JoggingJointTab.tsx +18 -18
  40. package/src/components/jogging/{JoggingJointRotationControl.tsx → JoggingJointValueControl.tsx} +51 -28
  41. package/src/components/jogging/JoggingPanel.tsx +1 -1
  42. package/src/components/jogging/JoggingStore.ts +42 -12
  43. package/src/components/robots/MotionGroupVisualizer.tsx +18 -79
  44. package/src/core.ts +2 -1
  45. package/src/lib/JoggerConnection.test.ts +4 -2
  46. package/src/lib/JoggerConnection.ts +8 -4
  47. package/dist/MotionGroupVisualizer-C3CB-L2z.cjs +0 -2
  48. package/dist/auth0-spa-js.production.esm-D_IhPirK.cjs +0 -5
  49. package/dist/auth0-spa-js.production.esm-D_IhPirK.cjs.map +0 -1
  50. package/dist/auth0-spa-js.production.esm-mvPojIrB.js.map +0 -1
  51. package/dist/components/jogging/JoggingJointRotationControl.d.ts +0 -15
  52. package/dist/components/jogging/JoggingJointRotationControl.d.ts.map +0 -1
  53. package/dist/interpolation-C5OTEwAm.cjs +0 -20
  54. package/dist/interpolation-C5OTEwAm.cjs.map +0 -1
  55. package/dist/interpolation-Cs2pC1zE.js.map +0 -1
  56. package/dist/theming-C-zvh022.js.map +0 -1
  57. package/dist/theming-Dk07SE2_.cjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "4.2.0",
3
+ "version": "4.3.0-pr.feat-RB-3171-dynamic-motion-visualization.517.0fc2fb2",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -93,7 +93,7 @@
93
93
  "@types/react": "^19.1.8",
94
94
  "@types/three": "^0.182.0",
95
95
  "@vitejs/plugin-react": "^4.3.4",
96
- "@wandelbots/nova-js": "^3.5.2",
96
+ "@wandelbots/nova-js": "3.5.3-pr.feat-RB-3171-dymamic-rendering.230.d40ec9a",
97
97
  "add": "^2.0.6",
98
98
  "eslint-plugin-storybook": "^10.1.10",
99
99
  "glob": "^13.0.0",
@@ -1,10 +1,9 @@
1
1
  import { Divider, Stack, Typography, useTheme } from "@mui/material"
2
- import { radiansToDegrees } from "@wandelbots/nova-js"
3
2
  import { observer } from "mobx-react-lite"
4
3
  import type { ReactNode } from "react"
5
4
  import { JoggingJointLimitDetector } from "./JoggingJointLimitDetector"
6
- import { JoggingJointRotationControl } from "./JoggingJointRotationControl"
7
- import type { JoggingStore } from "./JoggingStore"
5
+ import { JoggingJointValueControl } from "./JoggingJointValueControl"
6
+ import { type JoggingStore, JointCategory } from "./JoggingStore"
8
7
  import { JoggingVelocitySlider } from "./JoggingVelocitySlider"
9
8
 
10
9
  export const JoggingJointTab = observer(
@@ -12,14 +11,22 @@ export const JoggingJointTab = observer(
12
11
  const theme = useTheme()
13
12
  async function startJointJogging(opts: {
14
13
  joint: number
15
- direction: "-" | "+"
14
+ direction: "-" | "+",
16
15
  }) {
17
16
  await store.activate()
18
17
 
19
18
  await store.jogger.rotateJoints({
20
19
  joint: opts.joint,
21
20
  direction: opts.direction,
22
- velocityRadsPerSec: store.rotationVelocityRadsPerSec,
21
+ velocityUnit:
22
+ store.jointCategory === JointCategory.PRISMATIC
23
+ ? "mm/s"
24
+ : "rad/s",
25
+ velocityValue:
26
+ store.jointCategory === JointCategory.PRISMATIC
27
+ ? store.translationVelocityMmPerSec
28
+ : store.rotationVelocityRadsPerSec,
29
+
23
30
  })
24
31
  }
25
32
 
@@ -43,14 +50,6 @@ export const JoggingJointTab = observer(
43
50
  const jointLimits =
44
51
  store.motionGroupDescription.operation_limits.auto_limits
45
52
  ?.joints?.[joint.index]?.position
46
- const lowerLimitDegs =
47
- jointLimits?.lower_limit !== undefined
48
- ? radiansToDegrees(jointLimits.lower_limit)
49
- : undefined
50
- const upperLimitDegs =
51
- jointLimits?.upper_limit !== undefined
52
- ? radiansToDegrees(jointLimits.upper_limit)
53
- : undefined
54
53
 
55
54
  return (
56
55
  <Stack
@@ -73,16 +72,17 @@ export const JoggingJointTab = observer(
73
72
  </Typography>
74
73
  )}
75
74
 
76
- <JoggingJointRotationControl
75
+ <JoggingJointValueControl
77
76
  disabled={store.isLocked}
78
- lowerLimitDegs={lowerLimitDegs}
79
- upperLimitDegs={upperLimitDegs}
80
- getValueDegs={() => {
77
+ lowerLimit={jointLimits?.lower_limit}
78
+ upperLimit={jointLimits?.upper_limit}
79
+ useDegree={store.currentMotionType === "rotate"}
80
+ getValue={() => {
81
81
  const value =
82
82
  store.jogger.motionStream.rapidlyChangingMotionState
83
83
  .joint_position[joint.index]
84
84
  return value !== undefined
85
- ? radiansToDegrees(value)
85
+ ? value
86
86
  : undefined
87
87
  }}
88
88
  startJogging={(direction: "-" | "+") =>
@@ -1,5 +1,6 @@
1
1
  import ChevronLeft from "@mui/icons-material/ChevronLeft"
2
2
  import ChevronRight from "@mui/icons-material/ChevronRight"
3
+ import { radiansToDegrees } from "@wandelbots/nova-js"
3
4
  import { IconButton, Slider, Typography, useTheme } from "@mui/material"
4
5
  import Stack from "@mui/material/Stack"
5
6
  import throttle from "lodash-es/throttle"
@@ -9,28 +10,29 @@ import { useTranslation } from "react-i18next"
9
10
  import { externalizeComponent } from "../../externalizeComponent"
10
11
  import { useAnimationFrame } from "../utils/hooks"
11
12
 
12
- type JoggingJointRotationControlProps = {
13
+ type JoggingJointValueControlProps = {
13
14
  startJogging: (direction: "-" | "+") => void
14
15
  stopJogging: () => void
15
- lowerLimitDegs?: number
16
- upperLimitDegs?: number
17
- getValueDegs: () => number | undefined
18
-
16
+ lowerLimit?: number
17
+ upperLimit?: number
18
+ useDegree: boolean
19
+ getValue: () => number | undefined
19
20
  disabled?: boolean
20
21
  } & React.ComponentProps<typeof Stack>
21
22
 
22
23
  /** A input widget to control an individual joint */
23
- export const JoggingJointRotationControl = externalizeComponent(
24
+ export const JoggingJointValueControl = externalizeComponent(
24
25
  observer(
25
26
  ({
26
- startJogging,
27
- stopJogging,
28
- lowerLimitDegs,
29
- upperLimitDegs,
30
- getValueDegs,
31
- disabled,
32
- ...rest
33
- }: JoggingJointRotationControlProps) => {
27
+ startJogging,
28
+ stopJogging,
29
+ lowerLimit,
30
+ upperLimit,
31
+ useDegree,
32
+ getValue,
33
+ disabled,
34
+ ...rest
35
+ }: JoggingJointValueControlProps) => {
34
36
  const { t } = useTranslation()
35
37
  const [currentValue, setCurrentValue] = useState<number | undefined>()
36
38
  const theme = useTheme()
@@ -55,11 +57,18 @@ export const JoggingJointRotationControl = externalizeComponent(
55
57
  }))
56
58
 
57
59
  const updateValue = throttle(() => {
58
- setCurrentValue(getValueDegs())
60
+ setCurrentValue(useDegree ? convertToDegree(getValue()) : getValue())
59
61
  }, 50)
60
62
 
61
63
  useAnimationFrame(updateValue)
62
64
 
65
+ function convertToDegree(value: number| undefined){
66
+ if (value == undefined){
67
+ return undefined;
68
+ }
69
+ return radiansToDegrees(value);
70
+ }
71
+
63
72
  function onPointerDownMinus(ev: React.PointerEvent) {
64
73
  // Stop right click from triggering jog
65
74
  if (ev.button === 0) state.startJogging("-")
@@ -90,6 +99,20 @@ export const JoggingJointRotationControl = externalizeComponent(
90
99
  return output
91
100
  }
92
101
  }
102
+ function formatMm(value: number | undefined, precision = 1) {
103
+ if (value === undefined || isNaN(value)) return ""
104
+
105
+ const output = t("General.mm.variable", {
106
+ amount: value.toFixed(precision),
107
+ })
108
+
109
+ if (value > 0 && precision === 0) {
110
+ return `+${output}`
111
+ } else {
112
+ return output
113
+ }
114
+ }
115
+
93
116
 
94
117
  return (
95
118
  <Stack
@@ -138,8 +161,8 @@ export const JoggingJointRotationControl = externalizeComponent(
138
161
  sx={{
139
162
  pointerEvents: "none",
140
163
  color:
141
- theme.componentsExt?.JoggingPanel?.JoggingJoint?.Joint
142
- ?.arrowColor,
164
+ theme.componentsExt?.JoggingPanel?.JoggingJoint?.Joint
165
+ ?.arrowColor,
143
166
  }}
144
167
  />
145
168
  </IconButton>
@@ -171,14 +194,14 @@ export const JoggingJointRotationControl = externalizeComponent(
171
194
  : theme.palette.text.primary,
172
195
  }}
173
196
  >
174
- {formatDegrees(currentValue)}
197
+ {useDegree ? formatDegrees(currentValue) : formatMm(currentValue)}
175
198
  </Typography>
176
199
 
177
200
  <Slider
178
201
  disabled
179
202
  aria-label="Joint position"
180
- min={lowerLimitDegs}
181
- max={upperLimitDegs}
203
+ min={ useDegree ? convertToDegree(lowerLimit) : lowerLimit}
204
+ max={ useDegree ? convertToDegree(upperLimit) : upperLimit}
182
205
  value={currentValue || 0}
183
206
  track={false}
184
207
  sx={{
@@ -206,15 +229,15 @@ export const JoggingJointRotationControl = externalizeComponent(
206
229
  },
207
230
  }}
208
231
  marks={
209
- lowerLimitDegs !== undefined &&
210
- upperLimitDegs !== undefined && [
232
+ lowerLimit !== undefined &&
233
+ upperLimit !== undefined && [
211
234
  {
212
- value: lowerLimitDegs,
213
- label: formatDegrees(lowerLimitDegs, 0),
235
+ value: (useDegree ? convertToDegree(lowerLimit) : lowerLimit) as number,
236
+ label: useDegree ? formatDegrees(convertToDegree(lowerLimit),0) : formatMm(lowerLimit),
214
237
  },
215
238
  {
216
- value: upperLimitDegs,
217
- label: formatDegrees(upperLimitDegs, 0),
239
+ value: (useDegree ? convertToDegree(upperLimit) : upperLimit) as number,
240
+ label: useDegree ? formatDegrees(convertToDegree(upperLimit),0) : formatMm(upperLimit),
218
241
  },
219
242
  ]
220
243
  }
@@ -236,8 +259,8 @@ export const JoggingJointRotationControl = externalizeComponent(
236
259
  sx={{
237
260
  pointerEvents: "none",
238
261
  color:
239
- theme.componentsExt?.JoggingPanel?.JoggingJoint?.Joint
240
- ?.arrowColor,
262
+ theme.componentsExt?.JoggingPanel?.JoggingJoint?.Joint
263
+ ?.arrowColor,
241
264
  }}
242
265
  />
243
266
  </IconButton>
@@ -153,7 +153,7 @@ const JoggingPanelInner = observer(
153
153
  >
154
154
  {store.tabs.map((tab) => {
155
155
  const label =
156
- tab.label === "cartesian"
156
+ tab.label === "Cartesian"
157
157
  ? t("Jogging.Cartesian.bt")
158
158
  : t("Jogging.Joints.bt")
159
159
 
@@ -40,8 +40,16 @@ export type IncrementJogInProgress = {
40
40
  axis: JoggingAxis
41
41
  }
42
42
 
43
+ export enum JointCategory {
44
+ REVOLUTE = "REVOLUTE",
45
+ PRISMATIC = "PRISMATIC",
46
+ }
47
+
48
+ type TabType = "cartesian" | "joint" | "debug";
49
+
50
+
43
51
  export class JoggingStore {
44
- selectedTabId: "cartesian" | "joint" | "debug" = "cartesian"
52
+ selectedTabId: TabType = "cartesian";
45
53
 
46
54
  /**
47
55
  * State of the jogging panel. Starts as "inactive"
@@ -298,18 +306,20 @@ export class JoggingStore {
298
306
  }
299
307
 
300
308
  get tabs() {
301
- return [
302
- {
309
+ const tempTabs : {id: TabType, label: string}[] = [{
310
+ id: "joint",
311
+ label: "Joints",
312
+ }] ;
313
+ if(this.isTcpCartesianMoveable){
314
+ tempTabs.unshift({
303
315
  id: "cartesian",
304
- label: "cartesian",
305
- },
306
- {
307
- id: "joint",
308
- label: "joint",
309
- },
310
- ] as const
316
+ label: "Cartesian",
317
+ })}
318
+
319
+ return tempTabs;
311
320
  }
312
321
 
322
+
313
323
  get incrementOptions() {
314
324
  return incrementOptions
315
325
  }
@@ -395,8 +405,10 @@ export class JoggingStore {
395
405
  */
396
406
  get currentMotionType() {
397
407
  if (
398
- this.selectedTabId === "cartesian" &&
399
- this.selectedCartesianMotionType === "translate"
408
+ (
409
+ this.selectedTabId === "cartesian" &&
410
+ this.selectedCartesianMotionType === "translate"
411
+ ) || this.jointCategory === JointCategory.PRISMATIC
400
412
  ) {
401
413
  return "translate"
402
414
  } else {
@@ -404,6 +416,24 @@ export class JoggingStore {
404
416
  }
405
417
  }
406
418
 
419
+
420
+ /*
421
+ * ToDo replace Hardcoded Models with an api request that delivers the type (will become part of DH-Parameters)
422
+ * Ticket already created
423
+ * */
424
+ get jointCategory(): JointCategory {
425
+ return this.motionGroupDescription.motion_group_model === "ABB_IRT710"
426
+ ? JointCategory.PRISMATIC
427
+ : JointCategory.REVOLUTE
428
+ }
429
+
430
+ get isTcpCartesianMoveable(): boolean{
431
+ if(this.motionGroupDescription.motion_group_model === "ABB_IRT710"){
432
+ return false;
433
+ }
434
+ return true;
435
+ }
436
+
407
437
  onTabChange(_event: React.SyntheticEvent, newValue: number) {
408
438
  const tab = this.tabs[newValue] || this.tabs[0]!
409
439
  this.selectedTabId = tab.id
@@ -1,6 +1,5 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from "react"
2
- import { NovaClient } from "@wandelbots/nova-js/v2"
3
- import type { KinematicModel } from "@wandelbots/nova-api/v2"
1
+ import React, { useEffect, useMemo, useState } from "react"
2
+ import { JointTypeEnum } from "@wandelbots/nova-js/v2"
4
3
 
5
4
  import { externalizeComponent } from "../../externalizeComponent"
6
5
  import { SupportedRobot, type SupportedRobotProps } from "./SupportedRobot"
@@ -8,106 +7,46 @@ import { SupportedLinearAxis, type SupportedLinearAxisProps } from "./SupportedL
8
7
 
9
8
  export type MotionGroupVisualizerProps = {
10
9
  instanceUrl: string
11
- inverseSolver?: string | null
10
+ inverseSolver: string | null
12
11
  } & (SupportedRobotProps | SupportedLinearAxisProps)
13
12
 
14
13
  export const MotionGroupVisualizer: React.FC<MotionGroupVisualizerProps> = externalizeComponent((props: MotionGroupVisualizerProps) => {
15
14
  const {
16
- instanceUrl,
17
- inverseSolver: inverseSolverProp,
18
- modelFromController,
15
+ inverseSolver,
16
+ dhParameters,
19
17
  ...rest
20
18
  } = props
21
19
 
22
- const [inverseSolver, setInverseSolver] = useState<string | null | undefined>(
23
- inverseSolverProp,
24
- )
25
- const [, forceThreeRerender] = useState<boolean>(false)
26
-
27
20
  /**
28
- * Fetches the kinematic model from the API and saved the inverse_solver property, which defined
29
- * whether the motion group should be displayed as a robot or linear axis
21
+ * Joint type to find out - in combination with inverseSolver - whether the
22
+ * active robot is a turn table
30
23
  */
31
- const fetchKinematicModel = useCallback(async () => {
32
- const nova = new NovaClient({ instanceUrl })
33
-
34
- try {
35
- const kinematicModel: KinematicModel =
36
- await nova.api.motionGroupModels.getMotionGroupKinematicModel(
37
- modelFromController,
38
- )
39
-
40
- setInverseSolver(kinematicModel.inverse_solver)
41
- } catch (err) {
42
- console.warn(
43
- `Failed to fetch kinematic model from API for ${modelFromController}, falling back to local config`,
44
- )
45
- } finally {
46
- /**
47
- * The following is a workaround to force a rerender of the Three.js scene, due
48
- * to a race condition (if the component gets re-initialized, the robot
49
- * is rendered with the initial joint position). The forceThreeRerender tells
50
- * the Three.JS to re-render with the right joint position
51
- *
52
- * TODO remove the three rerender function and get rid of the
53
- * stale state condition
54
- * https://wandelbots.atlassian.net/browse/RB-3134
55
- */
56
- setTimeout(() => forceThreeRerender(true), 0)
57
- }
58
- }, [modelFromController, instanceUrl])
24
+ const [jointType, setJointType] = useState<JointTypeEnum>(JointTypeEnum.RevoluteJoint)
59
25
 
60
26
  /**
61
- * Checks the delivered inverseSolver property from the consumer
62
- * Defined, Null - carry on with the delivered value - the inverseSolver was fetched via consumer app
63
- * Undefined - carry out a request to fetch the inverseSolver value
27
+ * Sets the joint type according to delivered dh parameter type
64
28
  */
65
29
  useEffect(() => {
66
- const shouldKinematicBeFetched =
67
- inverseSolverProp === undefined && !!modelFromController && !!instanceUrl
68
-
69
- if (shouldKinematicBeFetched) {
70
- fetchKinematicModel()
30
+ if (dhParameters?.length) {
31
+ setJointType(dhParameters[0]?.type ?? JointTypeEnum.RevoluteJoint)
71
32
  }
72
- }, [inverseSolverProp, modelFromController, fetchKinematicModel, instanceUrl])
33
+ }, [dhParameters])
73
34
 
74
35
  /**
75
36
  * The turntable models return inverseSolver = null - however these models
76
37
  * should be rendered with SupportedRobot instead of SupportedLinearAxis
77
- *
78
- * TODO
79
- * In the future - this hard coded check would be replaced with a new "type" property
80
- * from dh parameters
81
38
  */
82
39
  const isTurnTable = useMemo(() => {
83
- return [
84
- "KUKA_DKP250",
85
- "KUKA_DKP500_2",
86
- "YASKAWA_TURN1",
87
- "YASKAWA_TURN2",
88
- "YASKAWA_TURN3",
89
- ].includes(modelFromController)
90
- }, [modelFromController])
40
+ return !inverseSolver && jointType === "REVOLUTE_JOINT"
41
+ }, [inverseSolver, jointType])
91
42
 
92
43
  if (inverseSolver || isTurnTable) {
93
44
  return (
94
- <SupportedRobot
95
- instanceUrl={instanceUrl}
96
- modelFromController={modelFromController}
97
- {...rest}
98
- />
45
+ <SupportedRobot dhParameters={dhParameters} {...rest} />
99
46
  )
100
47
  }
101
48
 
102
- if (inverseSolver === null) {
103
- return (
104
- <SupportedLinearAxis
105
- instanceUrl={instanceUrl}
106
- modelFromController={modelFromController}
107
- {...rest}
108
- />
109
- )
110
- }
111
-
112
- return null
49
+ return (
50
+ <SupportedLinearAxis dhParameters={dhParameters} {...rest} />
51
+ )
113
52
  })
package/src/core.ts CHANGED
@@ -3,7 +3,7 @@ export * from "./components/AppHeader"
3
3
  export * from "./components/CycleTimer"
4
4
  export * from "./components/DataGrid"
5
5
  export * from "./components/jogging/JoggingCartesianAxisControl"
6
- export * from "./components/jogging/JoggingJointRotationControl"
6
+ export * from "./components/jogging/JoggingJointValueControl"
7
7
  export * from "./components/jogging/JoggingPanel"
8
8
  export { JoggingStore } from "./components/jogging/JoggingStore"
9
9
  export * from "./components/jogging/PoseCartesianValues"
@@ -31,3 +31,4 @@ export * from "./lib/motionStateUpdate"
31
31
  export * from "./lib/MotionStreamConnection"
32
32
  export * from "./themes/themeTypes"
33
33
  export { createNovaMuiTheme } from "./themes/theming"
34
+
@@ -77,7 +77,8 @@ test("jog a robot somewhat", async () => {
77
77
  await jogger.rotateJoints({
78
78
  joint: 0,
79
79
  direction: "+",
80
- velocityRadsPerSec: 0.1,
80
+ velocityValue: 0.1,
81
+ velocityUnit: "rad/s",
81
82
  })
82
83
 
83
84
  await delay(500)
@@ -94,7 +95,8 @@ test("jog a robot somewhat", async () => {
94
95
  await jogger.rotateJoints({
95
96
  joint: 0,
96
97
  direction: "-",
97
- velocityRadsPerSec: 0.1,
98
+ velocityValue: 0.1,
99
+ velocityUnit: "rad/s",
98
100
  })
99
101
  await delay(500)
100
102
  await jogger.stop()
@@ -282,14 +282,18 @@ export class JoggerConnection {
282
282
  async rotateJoints({
283
283
  joint,
284
284
  direction,
285
- velocityRadsPerSec,
285
+ velocityValue,
286
+ velocityUnit
287
+
286
288
  }: {
287
289
  /** Index of the joint to rotate */
288
290
  joint: number
289
291
  /** Direction of rotation ("+" or "-") */
290
292
  direction: "+" | "-"
291
- /** Speed of the rotation in radians per second */
292
- velocityRadsPerSec: number
293
+ /** Speed of the rotation, unit is currently unused, but i wanted it there to raise awareness that not everything here is rad/s*/
294
+ velocityValue: number
295
+ velocityUnit: "mm/s" | "rad/s"
296
+
293
297
  }) {
294
298
  if (!this.joggingSocket || this.mode !== "jogging") {
295
299
  throw new Error(
@@ -300,7 +304,7 @@ export class JoggerConnection {
300
304
  const velocity = new Array(this.numJoints).fill(0)
301
305
 
302
306
  velocity[joint] =
303
- direction === "-" ? -velocityRadsPerSec : velocityRadsPerSec
307
+ direction === "-" ? - velocityValue : velocityValue
304
308
 
305
309
  this.joggingSocket.sendJson({
306
310
  message_type: "JointVelocityRequest",
@@ -1,2 +0,0 @@
1
- "use strict";const t=require("./externalizeComponent-CkVWk2F_.cjs"),g=require("three"),K=require("three-stdlib"),_=require("@react-three/fiber"),M=require("@react-three/drei"),y=require("@mui/material"),ae=require("mobx-react-lite"),p=require("react"),ue=require("react-i18next"),E=require("./interpolation-C5OTEwAm.cjs"),N=require("react-error-boundary");function ce(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,s.get?s:{enumerable:!0,get:()=>e[r]})}}return n.default=e,Object.freeze(n)}const j=ce(g);function le(e){switch(e.shape_type){case"convex_hull":return new K.ConvexGeometry(e.vertices.map(r=>new j.Vector3(r[0]/1e3,r[1]/1e3,r[2]/1e3)));case"box":return new j.BoxGeometry(e.size_x/1e3,e.size_y/1e3,e.size_z/1e3);case"sphere":return new j.SphereGeometry(e.radius/1e3);case"capsule":return new j.CapsuleGeometry(e.radius/1e3,e.cylinder_height/1e3);case"cylinder":return new j.CylinderGeometry(e.radius/1e3,e.radius/1e3,e.height/1e3);case"rectangle":return new j.BoxGeometry(e.size_x/1e3,e.size_y/1e3,0);default:return console.warn(`${e.shape_type} is not supported`),new j.BufferGeometry}}function xe({name:e,collider:n,children:r}){var l,a;const s=((l=n.pose)==null?void 0:l.position)??[0,0,0],o=((a=n.pose)==null?void 0:a.orientation)??[0,0,0];return n.margin&&console.warn(`${e} margin is not supported`),t.jsxRuntimeExports.jsx("mesh",{name:e,position:new j.Vector3(s[0],s[1],s[2]).divideScalar(1e3),rotation:new j.Euler(o[0],o[1],o[2],"XYZ"),geometry:le(n.shape),children:r})}function me({name:e,colliders:n,meshChildrenProvider:r,...s}){return t.jsxRuntimeExports.jsx("group",{name:e,...s,children:Object.entries(n).map(([o,l])=>t.jsxRuntimeExports.jsx(xe,{name:o,collider:l,children:r(o,l)},o))})}function pe({scene:e,meshChildrenProvider:n}){const r=e.colliders;return t.jsxRuntimeExports.jsx("group",{children:r&&t.jsxRuntimeExports.jsx(me,{meshChildrenProvider:n,colliders:r})})}function F(){return t.jsxRuntimeExports.jsx(M.Environment,{children:t.jsxRuntimeExports.jsx(fe,{})})}function fe({positions:e=[2,0,2,0,2,0,2,0]}){return t.jsxRuntimeExports.jsxs(t.jsxRuntimeExports.Fragment,{children:[t.jsxRuntimeExports.jsx(M.Lightformer,{intensity:5,"rotation-x":Math.PI/2,position:[0,5,-9],scale:[10,10,1]}),t.jsxRuntimeExports.jsx("group",{rotation:[0,.5,0],children:t.jsxRuntimeExports.jsx("group",{children:e.map((n,r)=>t.jsxRuntimeExports.jsx(M.Lightformer,{form:"circle",intensity:5,rotation:[Math.PI/2,0,0],position:[n,4,r*4],scale:[3,1,1]},r))})}),t.jsxRuntimeExports.jsx(M.Lightformer,{intensity:40,"rotation-y":Math.PI/2,position:[-5,1,-1],scale:[20,.1,1]}),t.jsxRuntimeExports.jsx(M.Lightformer,{intensity:20,"rotation-y":-Math.PI,position:[-5,-2,-1],scale:[20,.1,1]}),t.jsxRuntimeExports.jsx(M.Lightformer,{"rotation-y":Math.PI/2,position:[-5,-1,-1],scale:[20,.5,1],intensity:5}),t.jsxRuntimeExports.jsx(M.Lightformer,{"rotation-y":-Math.PI/2,position:[10,1,0],scale:[20,1,1],intensity:10}),t.jsxRuntimeExports.jsx(M.Lightformer,{form:"ring",color:"white",intensity:5,scale:10,position:[-15,4,-18],target:[0,0,0]})]})}function de(e){if(e.length<3)return console.log("Not enough vertices to define a plane"),{isCoplanar:!1};const n=new j.Vector3(e[0].x,e[0].y,e[0].z),r=new j.Vector3(e[1].x,e[1].y,e[1].z),s=new j.Vector3(e[2].x,e[2].y,e[2].z),o=new j.Vector3().subVectors(r,n),l=new j.Vector3().subVectors(s,n),a=new j.Vector3().crossVectors(o,l).normalize();for(let x=3;x<e.length;x++){const u=new j.Vector3(e[x].x,e[x].y,e[x].z),m=new j.Vector3().subVectors(u,n),f=a.dot(m);if(Math.abs(f)>1e-6)return console.log("Vertices are not on the same plane"),{isCoplanar:!1}}return{isCoplanar:!0,normal:a}}function he({safetyZones:e,...n}){return t.jsxRuntimeExports.jsx("group",{...n,children:e.map((r,s)=>{let o=[];return r.geometry&&(r.geometry.compound?o=r.geometry.compound.child_geometries:r.geometry.convex_hull&&(o=[r.geometry])),o.map((l,a)=>{if(!l.convex_hull)return null;const x=l.convex_hull.vertices.map(f=>new j.Vector3(f.x/1e3,f.y/1e3,f.z/1e3)),u=de(x);if(u.isCoplanar&&u.normal){const i=new j.Vector3().addVectors(x[0],u.normal.multiplyScalar(1e-4));x.push(i)}let m;try{m=new K.ConvexGeometry(x)}catch(f){return console.log("Error creating ConvexGeometry:",f),null}return t.jsxRuntimeExports.jsx("mesh",{geometry:m,children:t.jsxRuntimeExports.jsx("meshStandardMaterial",{attach:"material",color:"#009f4d",opacity:.2,depthTest:!1,depthWrite:!1,transparent:!0,polygonOffset:!0,polygonOffsetFactor:-a},s)},`${s}-${a}`)})})})}function je({trajectory:e,...n}){var s;const r=((s=e.trajectory)==null?void 0:s.map(o=>o.tcp_pose?new j.Vector3(o.tcp_pose.position.x/1e3,o.tcp_pose.position.z/1e3,-o.tcp_pose.position.y/1e3):null).filter(o=>o!==null))||[];return t.jsxRuntimeExports.jsx("group",{...n,children:r.length>0&&t.jsxRuntimeExports.jsx(M.Line,{points:r,lineWidth:3,polygonOffset:!0,polygonOffsetFactor:10,polygonOffsetUnits:10})})}const G=new Map;async function S(e,n){if(G.has(e))return G.get(e);const r=(async()=>{var a;const s=n||"",o=new E.NovaClient({instanceUrl:s}),l=o.api.motionGroupModels;(a=l.axios)!=null&&a.interceptors&&l.axios.interceptors.request.use(x=>{var u;return(u=x.url)!=null&&u.includes("/glb")&&(x.responseType="blob"),x});try{const x=await o.api.motionGroupModels.getMotionGroupGlbModel(e);return URL.createObjectURL(x)}catch(x){throw console.error("Failed to fetch model:",x),x}})();return G.set(e,r),r}function $(e){function n(r){return r.children.length===0?[r]:[r,...r.children.flatMap(s=>n(s))]}return n(e).filter(r=>J(r))}function H(e){return e.name.endsWith("_FLG")}function J(e){return/_J[0-9]+$/.test(e.name)}function Re(e,n){let r;function s(o){if(H(o)){if(r)throw Error(`Found multiple flange groups in robot model ${n}; first ${r.name} then ${o.name}. Only one _FLG group is allowed.`);r=o}J(o),o.children.map(s)}if(s(e.scene),!r)throw Error(`No flange group found in robot model ${n}. Flange must be identified with a name ending in _FLG.`);return{gltf:e}}function Y({rapidlyChangingMotionState:e,dhParameters:n,onRotationChanged:r,children:s}){const o=p.useRef([]),l=p.useRef([]),a=p.useRef(null),{invalidate:x}=_.useThree();p.useEffect(()=>{const i=e.joint_position.filter(c=>c!==void 0);return a.current=new E.ValueInterpolator(i,{tension:120,friction:20,threshold:.001}),()=>{var c;(c=a.current)==null||c.destroy()}},[]),_.useFrame((i,c)=>{if(a.current){const d=a.current.update(c);m(),d||x()}});function u(i){i&&(l.current=$(i),m(),x())}function m(){var c;const i=((c=a.current)==null?void 0:c.getCurrentValues())||[];if(r)r(l.current,i);else for(const[d,R]of l.current.entries()){const h=n[d],w=h.theta||0,b=h.reverse_rotation_direction?-1:1;R.rotation.y=b*(i[d]||0)+w}}const f=p.useCallback(()=>{const i=e.joint_position.filter(c=>c!==void 0);requestAnimationFrame(()=>{var c;o.current=i,(c=a.current)==null||c.setTarget(i)})},[e]);return p.useEffect(()=>{f()},[e,f]),E.useAutorun(()=>{f()}),t.jsxRuntimeExports.jsx("group",{ref:u,children:s})}const ge="line",ye="mesh";function Ee({rapidlyChangingMotionState:e,dhParameters:n,...r}){const s=new g.Matrix4,o=p.useRef([]),l=p.useRef([]);p.useEffect(()=>{o.current=new Array(n.length).fill(null),l.current=new Array(n.length).fill(null)},[n.length]);function a(m,f){const i=new g.Vector3,c=new g.Quaternion,d=new g.Vector3;s.decompose(i,c,d);const R=i.clone(),h=new g.Matrix4().makeRotationY(m.theta+f*(m.reverse_rotation_direction?-1:1)).multiply(new g.Matrix4().makeTranslation(0,m.d/1e3,0)).multiply(new g.Matrix4().makeTranslation(m.a/1e3,0,0)).multiply(new g.Matrix4().makeRotationX(m.alpha));return s.multiply(h),s.decompose(i,c,d),{a:R,b:i}}function x(m,f,i,c){if(!n)return;const d=n[m];if(!d)return;const{a:R,b:h}=a(d,c);f.geometry.setPositions([R.toArray(),h.toArray()].flat()),i.position.set(h.x,h.y,h.z)}function u(m,f){s.identity();for(let i=0;i<Math.min(m.length,f.length);i++){const c=o.current[i],d=l.current[i];c&&d&&x(i,c,d,f[i])}}return t.jsxRuntimeExports.jsx(t.jsxRuntimeExports.Fragment,{children:t.jsxRuntimeExports.jsx(Y,{rapidlyChangingMotionState:e,dhParameters:n,onRotationChanged:u,children:t.jsxRuntimeExports.jsxs("group",{...r,name:"Scene",children:[t.jsxRuntimeExports.jsxs("mesh",{children:[t.jsxRuntimeExports.jsx("sphereGeometry",{args:[.01,32,32]}),t.jsxRuntimeExports.jsx("meshStandardMaterial",{color:"black",depthTest:!0})]}),n.map((m,f)=>{const{a:i,b:c}=a(m,e.joint_position[f]??0),d=`dhrobot_J0${f}`;return t.jsxRuntimeExports.jsxs("group",{name:d,children:[t.jsxRuntimeExports.jsx(M.Line,{ref:R=>{o.current[f]=R},name:ge,points:[i,c],color:"white",lineWidth:5}),t.jsxRuntimeExports.jsxs("mesh",{ref:R=>{l.current[f]=R},name:ye,position:c,children:[t.jsxRuntimeExports.jsx("sphereGeometry",{args:[.01,32,32]}),t.jsxRuntimeExports.jsx("meshStandardMaterial",{color:"black",depthTest:!0})]},"mesh_"+f)]},d)})]})})})}const be=console.warn;function X(){return p.useEffect(()=>{console.warn=e=>{e!=="Cannot call the manual advancement of rafz whilst frameLoop is not set as demand"&&be(e)}},[]),t.jsxRuntimeExports.jsx(t.jsxRuntimeExports.Fragment,{})}function we(e){return e.type==="Mesh"}function Me({url:e,flangeRef:n,postModelRender:r,...s}){const o=M.useGLTF(e);let l;try{l=Re(o,"robot.glb").gltf}catch(u){throw u}const a=p.useCallback(u=>{u&&r&&r()},[r]);function x(u){try{return we(u)?u.geometry?t.jsxRuntimeExports.jsx("mesh",{name:u.name,geometry:u.geometry,material:u.material,position:u.position,rotation:u.rotation},u.uuid):t.jsxRuntimeExports.jsx("group",{name:u.name,position:u.position,rotation:u.rotation},u.uuid):t.jsxRuntimeExports.jsx("group",{name:u.name,position:u.position,rotation:u.rotation,ref:H(u)?n:void 0,children:u.children.map(x)},u.uuid)}catch(m){return console.warn("Error rendering node",u.name,m),null}}return t.jsxRuntimeExports.jsx("group",{...s,dispose:null,ref:a,children:x(l.scene)})}function Q({modelURL:e,flangeRef:n,postModelRender:r,...s}){const[o,l]=p.useState(null);return p.useEffect(()=>{(async()=>{try{if(typeof e=="string")l(e);else{const x=await e;l(x)}}catch(x){console.error("Failed to resolve model URL:",x)}})()},[e]),o?t.jsxRuntimeExports.jsx(Me,{url:o,flangeRef:n,postModelRender:r,...s}):null}const Z=(e,n)=>{e.userData.isGhost||(e.traverse(r=>{if(r instanceof j.Mesh){r.material instanceof j.Material&&(r.material.colorWrite=!1);const s=r.clone(),o=r.clone();s.material=new j.MeshStandardMaterial({depthTest:!0,depthWrite:!0,colorWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,side:j.DoubleSide}),s.userData.isGhost=!0,o.material=new j.MeshStandardMaterial({color:n,opacity:.3,depthTest:!0,depthWrite:!1,transparent:!0,polygonOffset:!0,polygonOffsetFactor:-2,side:j.DoubleSide}),o.userData.isGhost=!0,r.parent&&(r.parent.add(s),r.parent.add(o))}}),e.userData.isGhost=!0)},ee=e=>{if(!e.userData.isGhost)return;const n=[];e.traverse(r=>{var s;r instanceof j.Mesh&&((s=r.userData)!=null&&s.isGhost?n.push(r):r.material instanceof j.Material&&(r.material.colorWrite=!0))}),n.forEach(r=>{r.parent&&r.parent.remove(r)}),e.userData.isGhost=!1},I=t.externalizeComponent(({rapidlyChangingMotionState:e,modelFromController:n,dhParameters:r,getModel:s=S,flangeRef:o,postModelRender:l,transparentColor:a,instanceUrl:x,...u})=>{const[m,f]=p.useState(null),i=p.useCallback(d=>{f(d)},[]);p.useEffect(()=>{m&&(a?Z(m,a):ee(m))},[m,a]);const c=t.jsxRuntimeExports.jsx(Ee,{rapidlyChangingMotionState:e,dhParameters:r,...u});return t.jsxRuntimeExports.jsxs(N.ErrorBoundary,{fallback:c,onError:d=>{console.warn(d)},children:[t.jsxRuntimeExports.jsx(p.Suspense,{fallback:c,children:t.jsxRuntimeExports.jsx("group",{ref:i,children:t.jsxRuntimeExports.jsx(Y,{rapidlyChangingMotionState:e,dhParameters:r,children:t.jsxRuntimeExports.jsx(Q,{modelURL:(()=>{const d=s(n,x);if(!d){const R=new Blob([],{type:"model/gltf-binary"}),h=new File([R],`${n}.glb`,{type:"model/gltf-binary"});return Promise.resolve(URL.createObjectURL(h))}return d})(),postModelRender:l,flangeRef:o,...u})})})}),t.jsxRuntimeExports.jsx(X,{})]})});function te({connectedMotionGroup:e,getModel:n=S,flangeRef:r,transparentColor:s,postModelRender:o,...l}){return e.dhParameters?t.jsxRuntimeExports.jsx(I,{rapidlyChangingMotionState:e.rapidlyChangingMotionState,modelFromController:e.modelFromController||"",dhParameters:e.dhParameters,getModel:n,flangeRef:r,transparentColor:s,postModelRender:o,...l}):null}const ve=t.externalizeComponent(ae.observer(({robotName:e,programState:n,safetyState:r,operationMode:s,driveToHomeEnabled:o=!1,onDriveToHomePress:l,onDriveToHomeRelease:a,connectedMotionGroup:x,robotComponent:u=te,customContentComponent:m,className:f})=>{var z;const i=y.useTheme(),{t:c}=ue.useTranslation(),[d,R]=p.useState(!1),h=p.useRef(null),w=p.useRef(null),[b,V]=p.useState(!1),[A,oe]=p.useState({width:400,height:600}),[Te,ie]=p.useState(0);p.useEffect(()=>{const L=()=>{if(w.current){const{offsetWidth:W,offsetHeight:q}=w.current;V(W>q),oe({width:W,height:q})}};L();const O=new ResizeObserver(L);return w.current&&O.observe(w.current),()=>{O.disconnect()}},[]);const D=p.useCallback(()=>{ie(L=>L+1)},[]),C=p.useCallback(()=>{!o||!l||(R(!0),l())},[o,l]),T=p.useCallback(()=>{!o||!a||(R(!1),a())},[o,a]),U=p.useCallback(()=>{d&&a&&(R(!1),a())},[d,a]),v=b?A.width<350:A.height<200,k=b?A.height<310:A.height<450;return t.jsxRuntimeExports.jsx(y.Card,{ref:w,className:f,sx:{width:"100%",height:"100%",display:"flex",flexDirection:b?"row":"column",position:"relative",overflow:"hidden",minWidth:{xs:180,sm:220,md:250},minHeight:b?{xs:200,sm:240,md:260}:{xs:150,sm:180,md:220},border:`1px solid ${i.palette.divider}`,borderRadius:"18px",boxShadow:"none",backgroundColor:((z=i.palette.backgroundPaperElevation)==null?void 0:z[8])||"#2A2A3F",backgroundImage:"none"},children:b?t.jsxRuntimeExports.jsxs(t.jsxRuntimeExports.Fragment,{children:[t.jsxRuntimeExports.jsx(y.Box,{sx:{flex:"0 0 50%",position:"relative",height:"100%",minHeight:"100%",maxHeight:"100%",borderRadius:1,m:{xs:1.5,sm:2,md:3},mr:{xs:.75,sm:1,md:1.5},overflow:"hidden",display:v?"none":"block"},children:!v&&t.jsxRuntimeExports.jsxs(_.Canvas,{orthographic:!0,camera:{position:[3,2,3],zoom:1},shadows:!0,frameloop:"demand",style:{borderRadius:i.shape.borderRadius,width:"100%",height:"100%",background:"transparent",position:"absolute",top:0,left:0},dpr:[1,2],gl:{alpha:!0,antialias:!0},children:[t.jsxRuntimeExports.jsx(F,{}),t.jsxRuntimeExports.jsx(M.Bounds,{fit:!0,observe:!0,margin:1,maxDuration:1,children:t.jsxRuntimeExports.jsx(u,{connectedMotionGroup:x,postModelRender:D})})]})}),t.jsxRuntimeExports.jsxs(y.Box,{sx:{flex:"1",display:"flex",flexDirection:"column",justifyContent:"flex-start",width:v?"100%":"50%"},children:[t.jsxRuntimeExports.jsxs(y.Box,{sx:{p:{xs:1.5,sm:2,md:3},pb:{xs:1,sm:1.5,md:2},textAlign:"left"},children:[t.jsxRuntimeExports.jsx(y.Typography,{variant:"h6",component:"h2",sx:{mb:1},children:e}),t.jsxRuntimeExports.jsx(E.ProgramStateIndicator,{programState:n,safetyState:r,operationMode:s})]}),t.jsxRuntimeExports.jsxs(y.Box,{sx:{p:{xs:1.5,sm:2,md:3},pt:0,flex:"1",display:"flex",flexDirection:"column",justifyContent:"space-between"},children:[!k&&m&&t.jsxRuntimeExports.jsxs(y.Box,{children:[t.jsxRuntimeExports.jsx(m,{}),t.jsxRuntimeExports.jsx(y.Divider,{sx:{mt:1,mb:0,borderColor:i.palette.divider,opacity:.5}})]}),t.jsxRuntimeExports.jsx(y.Box,{sx:{mt:!k&&m?"auto":0},children:t.jsxRuntimeExports.jsx(y.Box,{sx:{display:"flex",justifyContent:"flex-start",mt:{xs:1,sm:1.5,md:2},mb:{xs:.5,sm:.75,md:1}},children:t.jsxRuntimeExports.jsx(y.Button,{ref:h,variant:"contained",color:"secondary",size:"small",disabled:!o,onMouseDown:C,onMouseUp:T,onMouseLeave:U,onTouchStart:C,onTouchEnd:T,sx:{textTransform:"none",px:1.5,py:.5},children:c("RobotCard.DriveToHome.bt")})})})]})]})]}):t.jsxRuntimeExports.jsx(t.jsxRuntimeExports.Fragment,{children:t.jsxRuntimeExports.jsxs(y.Box,{sx:{p:3,height:"100%",display:"flex",flexDirection:"column"},children:[t.jsxRuntimeExports.jsxs(y.Box,{children:[t.jsxRuntimeExports.jsx(y.Typography,{variant:"h6",component:"h2",sx:{mb:1},children:e}),t.jsxRuntimeExports.jsx(E.ProgramStateIndicator,{programState:n,safetyState:r,operationMode:s})]}),t.jsxRuntimeExports.jsx(y.Box,{sx:{flex:v?0:1,position:"relative",minHeight:v?0:{xs:120,sm:150,md:200},height:v?0:"auto",borderRadius:1,overflow:"hidden",display:v?"none":"block"},children:!v&&t.jsxRuntimeExports.jsxs(_.Canvas,{orthographic:!0,camera:{position:[3,2,3],zoom:1},shadows:!0,frameloop:"demand",style:{borderRadius:i.shape.borderRadius,width:"100%",height:"100%",background:"transparent",position:"absolute"},dpr:[1,2],gl:{alpha:!0,antialias:!0},children:[t.jsxRuntimeExports.jsx(F,{}),t.jsxRuntimeExports.jsx(M.Bounds,{fit:!0,clip:!0,observe:!0,margin:1,maxDuration:1,children:t.jsxRuntimeExports.jsx(u,{connectedMotionGroup:x,postModelRender:D})})]})}),t.jsxRuntimeExports.jsxs(y.Box,{children:[!k&&m&&t.jsxRuntimeExports.jsxs(t.jsxRuntimeExports.Fragment,{children:[t.jsxRuntimeExports.jsx(m,{}),t.jsxRuntimeExports.jsx(y.Divider,{sx:{mt:1,mb:0,borderColor:i.palette.divider,opacity:.5}})]}),t.jsxRuntimeExports.jsx(y.Box,{sx:{display:"flex",justifyContent:"flex-start",mt:!k&&m?{xs:1,sm:2,md:5}:{xs:.5,sm:1,md:2},mb:{xs:.5,sm:.75,md:1}},children:t.jsxRuntimeExports.jsx(y.Button,{ref:h,variant:"contained",color:"secondary",size:"small",disabled:!o,onMouseDown:C,onMouseUp:T,onMouseLeave:U,onTouchStart:C,onTouchEnd:T,sx:{textTransform:"none",px:1.5,py:.5},children:c("RobotCard.DriveToHome.bt")})})]})]})})})})),_e=Array(6).fill(2*Math.PI);function re({rapidlyChangingMotionState:e,dhParameters:n,onTranslationChanged:r,children:s}){const o=p.useRef([]),l=p.useRef([]),a=p.useRef(null),{invalidate:x}=_.useThree();p.useEffect(()=>{const i=e.joint_position.filter(c=>c!==void 0);return a.current=new E.ValueInterpolator(i,{tension:120,friction:20,threshold:.001}),()=>{var c;(c=a.current)==null||c.destroy()}},[]),_.useFrame((i,c)=>{if(a.current){const d=a.current.update(c);m(),d||x()}});function u(i){i&&(l.current=$(i),m(),x())}function m(){var c;const i=((c=a.current)==null?void 0:c.getCurrentValues())||[];if(r)r(l.current,i);else for(const[d,R]of l.current.entries()){const w=n[d].reverse_rotation_direction?-1:1;R.position.y=w*(i[d]||0)/1e3}}const f=p.useCallback(()=>{const i=e.joint_position.filter(c=>c!==void 0);requestAnimationFrame(()=>{var c;o.current=i,(c=a.current)==null||c.setTarget(i)})},[e]);return p.useEffect(()=>{f()},[e,f]),E.useAutorun(()=>{f()}),t.jsxRuntimeExports.jsx("group",{ref:u,children:s})}function ne({rapidlyChangingMotionState:e,dhParameters:n,...r}){const s=new g.Matrix4,o=p.useRef(null),l=p.useRef(null);function a(m){const f=new g.Matrix4;for(let R=0;R<n.length;R++){const h=n[R],w=m[R]??0,b=new g.Matrix4().makeRotationY(h.theta).multiply(new g.Matrix4().makeTranslation(h.a/1e3,(h.d+w*(h.reverse_rotation_direction?-1:1))/1e3,0)).multiply(new g.Matrix4().makeRotationX(h.alpha));f.multiply(b)}const i=new g.Vector3,c=new g.Quaternion,d=new g.Vector3;return f.decompose(i,c,d),i}const x=a(e.joint_position);function u(m,f){s.identity();let i=new g.Vector3;for(let h=0;h<n.length;h++){const w=f[h]??0,b=n[h],V=new g.Matrix4().makeRotationY(b.theta).multiply(new g.Matrix4().makeTranslation(b.a/1e3,(b.d+w*(b.reverse_rotation_direction?-1:1))/1e3,0)).multiply(new g.Matrix4().makeRotationX(b.alpha));s.multiply(V)}const c=new g.Vector3,d=new g.Quaternion,R=new g.Vector3;if(s.decompose(c,d,R),i=c,o.current&&o.current.position.set(i.x,i.y,i.z),l.current){const h=l.current.geometry;h&&h.setPositions&&h.setPositions([0,0,0,i.x,i.y,i.z])}}return t.jsxRuntimeExports.jsx(t.jsxRuntimeExports.Fragment,{children:t.jsxRuntimeExports.jsx(re,{rapidlyChangingMotionState:e,dhParameters:n,onTranslationChanged:u,children:t.jsxRuntimeExports.jsxs("group",{...r,name:"Scene",children:[t.jsxRuntimeExports.jsxs("mesh",{name:"Base",position:[0,0,0],children:[t.jsxRuntimeExports.jsx("sphereGeometry",{args:[.02,32,32]}),t.jsxRuntimeExports.jsx("meshStandardMaterial",{color:"green",depthTest:!0})]}),t.jsxRuntimeExports.jsx(M.Line,{ref:l,points:[new g.Vector3(0,0,0),x],color:"White",lineWidth:5}),t.jsxRuntimeExports.jsxs("mesh",{ref:o,name:"TCP",position:x,children:[t.jsxRuntimeExports.jsx("sphereGeometry",{args:[.025,32,32]}),t.jsxRuntimeExports.jsx("meshStandardMaterial",{color:"red",depthTest:!0})]})]})})})}const B=t.externalizeComponent(({rapidlyChangingMotionState:e,modelFromController:n,dhParameters:r,getModel:s=S,flangeRef:o,postModelRender:l,transparentColor:a,instanceUrl:x,...u})=>{const[m,f]=p.useState(null),i=p.useCallback(d=>{f(d)},[]);p.useEffect(()=>{m&&(a?Z(m,a):ee(m))},[m,a]);const c=t.jsxRuntimeExports.jsx(ne,{rapidlyChangingMotionState:e,dhParameters:r,...u});return t.jsxRuntimeExports.jsxs(N.ErrorBoundary,{fallback:c,onError:d=>{console.warn(d)},children:[t.jsxRuntimeExports.jsx(p.Suspense,{fallback:c,children:t.jsxRuntimeExports.jsx("group",{ref:i,children:t.jsxRuntimeExports.jsx(re,{rapidlyChangingMotionState:e,dhParameters:r,children:t.jsxRuntimeExports.jsx(Q,{modelURL:(()=>{const d=s(n,x);if(!d){const R=new Blob([],{type:"model/gltf-binary"}),h=new File([R],`${n}.glb`,{type:"model/gltf-binary"});return Promise.resolve(URL.createObjectURL(h))}return d})(),postModelRender:l,flangeRef:o,...u})})})}),t.jsxRuntimeExports.jsx(X,{})]})});function Se({connectedMotionGroup:e,getModel:n=S,flangeRef:r,transparentColor:s,postModelRender:o,...l}){if(!e.dhParameters)return null;const a=e.modelFromController||"";return a&&n(a)?t.jsxRuntimeExports.jsx(B,{rapidlyChangingMotionState:e.rapidlyChangingMotionState,modelFromController:a,dhParameters:e.dhParameters,getModel:n,flangeRef:r,transparentColor:s,postModelRender:o,...l}):t.jsxRuntimeExports.jsx(ne,{rapidlyChangingMotionState:e.rapidlyChangingMotionState,dhParameters:e.dhParameters,...l})}const P={[E.Manufacturer.Abb]:[0,0,0,0,Math.PI/2,0,0],[E.Manufacturer.Fanuc]:[0,0,0,0,-Math.PI/2,0,0],[E.Manufacturer.Yaskawa]:[0,0,0,0,-Math.PI/2,0,0],[E.Manufacturer.Kuka]:[0,-Math.PI/2,Math.PI/2,0,Math.PI/2,0,0],[E.Manufacturer.Universalrobots]:[0,-Math.PI/2,-Math.PI/2,-Math.PI/2,Math.PI/2,-Math.PI/2,0]};function se(e){const[n]=e.split("_");switch(n){case"ABB":return E.Manufacturer.Abb;case"FANUC":return E.Manufacturer.Fanuc;case"YASKAWA":return E.Manufacturer.Yaskawa;case"KUKA":return E.Manufacturer.Kuka;case"UniversalRobots":return E.Manufacturer.Universalrobots;default:return null}}function Ae(e,n){const r=se(e);return r&&r in P?P[r]:n||null}const Ce=t.externalizeComponent(e=>{const{instanceUrl:n,inverseSolver:r,modelFromController:s,...o}=e,[l,a]=p.useState(r),[,x]=p.useState(!1),u=p.useCallback(async()=>{const f=new E.NovaClient({instanceUrl:n});try{const i=await f.api.motionGroupModels.getMotionGroupKinematicModel(s);a(i.inverse_solver)}catch{console.warn(`Failed to fetch kinematic model from API for ${s}, falling back to local config`)}finally{setTimeout(()=>x(!0),0)}},[s,n]);p.useEffect(()=>{r===void 0&&!!s&&!!n&&u()},[r,s,u,n]);const m=p.useMemo(()=>["KUKA_DKP250","KUKA_DKP500_2","YASKAWA_TURN1","YASKAWA_TURN2","YASKAWA_TURN3"].includes(s),[s]);return l||m?t.jsxRuntimeExports.jsx(I,{instanceUrl:n,modelFromController:s,...o}):l===null?t.jsxRuntimeExports.jsx(B,{instanceUrl:n,modelFromController:s,...o}):null});exports.CollisionSceneRenderer=pe;exports.LinearAxis=Se;exports.MANUFACTURER_HOME_CONFIGS=P;exports.MotionGroupVisualizer=Ce;exports.PresetEnvironment=F;exports.Robot=te;exports.RobotCard=ve;exports.SafetyZonesRenderer=he;exports.SupportedLinearAxis=B;exports.SupportedRobot=I;exports.TrajectoryRenderer=je;exports.defaultAxisConfig=_e;exports.defaultGetModel=S;exports.extractManufacturer=se;exports.getDefaultHomeConfig=Ae;
2
- //# sourceMappingURL=MotionGroupVisualizer-C3CB-L2z.cjs.map