@wandelbots/wandelbots-js-react-components 4.1.1 → 4.2.0-pr.feat-JoggingPanelSupportForLinearAxis.514.bd93b8d
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.
- package/README.md +1 -1
- package/dist/3d.cjs.js +1 -1
- package/dist/3d.d.ts +1 -0
- package/dist/3d.d.ts.map +1 -1
- package/dist/3d.es.js +13 -12
- package/dist/MotionGroupVisualizer-C3CB-L2z.cjs +2 -0
- package/dist/MotionGroupVisualizer-C3CB-L2z.cjs.map +1 -0
- package/dist/{manufacturerHomePositions-DAaWLJKB.js → MotionGroupVisualizer-CrLamHYm.js} +408 -356
- package/dist/MotionGroupVisualizer-CrLamHYm.js.map +1 -0
- package/dist/components/jogging/JoggingJointTab.d.ts +1 -1
- package/dist/components/jogging/JoggingJointTab.d.ts.map +1 -1
- package/dist/components/jogging/JoggingJointValueControl.d.ts +16 -0
- package/dist/components/jogging/JoggingJointValueControl.d.ts.map +1 -0
- package/dist/components/jogging/JoggingStore.d.ts +17 -19
- package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
- package/dist/components/robots/MotionGroupVisualizer.d.ts +9 -0
- package/dist/components/robots/MotionGroupVisualizer.d.ts.map +1 -0
- package/dist/components/robots/SupportedLinearAxis.d.ts +3 -2
- package/dist/components/robots/SupportedLinearAxis.d.ts.map +1 -1
- package/dist/components/robots/SupportedRobot.d.ts +3 -2
- package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
- package/dist/components/robots/robotModelLogic.d.ts +1 -1
- package/dist/components/robots/robotModelLogic.d.ts.map +1 -1
- package/dist/core.cjs.js +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.es.js +8 -8
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +56 -55
- package/dist/{interpolation-DZhBKo-u.cjs → interpolation-C5OTEwAm.cjs} +3 -3
- package/dist/{interpolation-DZhBKo-u.cjs.map → interpolation-C5OTEwAm.cjs.map} +1 -1
- package/dist/{interpolation-baUmFLkh.js → interpolation-Cs2pC1zE.js} +694 -637
- package/dist/{interpolation-baUmFLkh.js.map → interpolation-Cs2pC1zE.js.map} +1 -1
- package/dist/lib/JoggerConnection.d.ts +4 -3
- package/dist/lib/JoggerConnection.d.ts.map +1 -1
- package/dist/{theming-BTlS2afw.js → theming-DDgLNzuF.js} +2915 -2891
- package/dist/theming-DDgLNzuF.js.map +1 -0
- package/dist/{theming-DPoEjzxv.cjs → theming-DU4-bToO.cjs} +36 -36
- package/dist/theming-DU4-bToO.cjs.map +1 -0
- package/package.json +3 -3
- package/src/3d.ts +1 -0
- package/src/components/jogging/JoggingJointTab.tsx +18 -18
- package/src/components/jogging/{JoggingJointRotationControl.tsx → JoggingJointValueControl.tsx} +51 -28
- package/src/components/jogging/JoggingStore.ts +42 -12
- package/src/components/robots/MotionGroupVisualizer.tsx +113 -0
- package/src/components/robots/SupportedLinearAxis.tsx +4 -2
- package/src/components/robots/SupportedRobot.tsx +4 -2
- package/src/components/robots/robotModelLogic.ts +2 -2
- package/src/core.ts +2 -1
- package/src/lib/JoggerConnection.test.ts +4 -2
- package/src/lib/JoggerConnection.ts +10 -6
- package/dist/components/jogging/JoggingJointRotationControl.d.ts +0 -15
- package/dist/components/jogging/JoggingJointRotationControl.d.ts.map +0 -1
- package/dist/manufacturerHomePositions-5E6JP4Zd.cjs +0 -2
- package/dist/manufacturerHomePositions-5E6JP4Zd.cjs.map +0 -1
- package/dist/manufacturerHomePositions-DAaWLJKB.js.map +0 -1
- package/dist/theming-BTlS2afw.js.map +0 -1
- package/dist/theming-DPoEjzxv.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.
|
|
3
|
+
"version": "4.2.0-pr.feat-JoggingPanelSupportForLinearAxis.514.bd93b8d",
|
|
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.
|
|
96
|
+
"@wandelbots/nova-js": "^3.5.2",
|
|
97
97
|
"add": "^2.0.6",
|
|
98
98
|
"eslint-plugin-storybook": "^10.1.10",
|
|
99
99
|
"glob": "^13.0.0",
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
"dependencies": {
|
|
177
177
|
"@mui/x-charts": "^8.27.0",
|
|
178
178
|
"@mui/x-data-grid": "^8.27.0",
|
|
179
|
-
"@wandelbots/nova-js": "3.5.
|
|
179
|
+
"@wandelbots/nova-js": "^3.5.2",
|
|
180
180
|
"axios": "^1.13.2",
|
|
181
181
|
"dotenv": "^17.2.3",
|
|
182
182
|
"i18next-browser-languagedetector": "^8.2.0",
|
package/src/3d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export * from "./components/robots/Robot"
|
|
|
14
14
|
export { defaultGetModel } from "./components/robots/robotModelLogic"
|
|
15
15
|
export * from "./components/robots/SupportedLinearAxis"
|
|
16
16
|
export * from "./components/robots/SupportedRobot"
|
|
17
|
+
export * from "./components/robots/MotionGroupVisualizer"
|
|
17
18
|
|
|
@@ -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 {
|
|
7
|
-
import type
|
|
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
|
-
|
|
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
|
-
<
|
|
75
|
+
<JoggingJointValueControl
|
|
77
76
|
disabled={store.isLocked}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
?
|
|
85
|
+
? value
|
|
86
86
|
: undefined
|
|
87
87
|
}}
|
|
88
88
|
startJogging={(direction: "-" | "+") =>
|
package/src/components/jogging/{JoggingJointRotationControl.tsx → JoggingJointValueControl.tsx}
RENAMED
|
@@ -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
|
|
13
|
+
type JoggingJointValueControlProps = {
|
|
13
14
|
startJogging: (direction: "-" | "+") => void
|
|
14
15
|
stopJogging: () => void
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
24
|
+
export const JoggingJointValueControl = externalizeComponent(
|
|
24
25
|
observer(
|
|
25
26
|
({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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(
|
|
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
|
-
|
|
142
|
-
|
|
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={
|
|
181
|
-
max={
|
|
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
|
-
|
|
210
|
-
|
|
232
|
+
lowerLimit !== undefined &&
|
|
233
|
+
upperLimit !== undefined && [
|
|
211
234
|
{
|
|
212
|
-
value:
|
|
213
|
-
label: formatDegrees(
|
|
235
|
+
value: (useDegree ? convertToDegree(lowerLimit) : lowerLimit) as number,
|
|
236
|
+
label: useDegree ? formatDegrees(convertToDegree(lowerLimit),0) : formatMm(lowerLimit),
|
|
214
237
|
},
|
|
215
238
|
{
|
|
216
|
-
value:
|
|
217
|
-
label: formatDegrees(
|
|
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
|
-
|
|
240
|
-
|
|
262
|
+
theme.componentsExt?.JoggingPanel?.JoggingJoint?.Joint
|
|
263
|
+
?.arrowColor,
|
|
241
264
|
}}
|
|
242
265
|
/>
|
|
243
266
|
</IconButton>
|
|
@@ -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:
|
|
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
|
-
|
|
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: "
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
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
|
-
|
|
399
|
-
|
|
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 requst 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
|
|
@@ -0,0 +1,113 @@
|
|
|
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"
|
|
4
|
+
|
|
5
|
+
import { externalizeComponent } from "../../externalizeComponent"
|
|
6
|
+
import { SupportedRobot, type SupportedRobotProps } from "./SupportedRobot"
|
|
7
|
+
import { SupportedLinearAxis, type SupportedLinearAxisProps } from "./SupportedLinearAxis"
|
|
8
|
+
|
|
9
|
+
export type MotionGroupVisualizerProps = {
|
|
10
|
+
instanceUrl: string
|
|
11
|
+
inverseSolver?: string | null
|
|
12
|
+
} & (SupportedRobotProps | SupportedLinearAxisProps)
|
|
13
|
+
|
|
14
|
+
export const MotionGroupVisualizer: React.FC<MotionGroupVisualizerProps> = externalizeComponent((props: MotionGroupVisualizerProps) => {
|
|
15
|
+
const {
|
|
16
|
+
instanceUrl,
|
|
17
|
+
inverseSolver: inverseSolverProp,
|
|
18
|
+
modelFromController,
|
|
19
|
+
...rest
|
|
20
|
+
} = props
|
|
21
|
+
|
|
22
|
+
const [inverseSolver, setInverseSolver] = useState<string | null | undefined>(
|
|
23
|
+
inverseSolverProp,
|
|
24
|
+
)
|
|
25
|
+
const [, forceThreeRerender] = useState<boolean>(false)
|
|
26
|
+
|
|
27
|
+
/**
|
|
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
|
|
30
|
+
*/
|
|
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])
|
|
59
|
+
|
|
60
|
+
/**
|
|
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
|
|
64
|
+
*/
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const shouldKinematicBeFetched =
|
|
67
|
+
inverseSolverProp === undefined && !!modelFromController && !!instanceUrl
|
|
68
|
+
|
|
69
|
+
if (shouldKinematicBeFetched) {
|
|
70
|
+
fetchKinematicModel()
|
|
71
|
+
}
|
|
72
|
+
}, [inverseSolverProp, modelFromController, fetchKinematicModel, instanceUrl])
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The turntable models return inverseSolver = null - however these models
|
|
76
|
+
* 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
|
+
*/
|
|
82
|
+
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])
|
|
91
|
+
|
|
92
|
+
if (inverseSolver || isTurnTable) {
|
|
93
|
+
return (
|
|
94
|
+
<SupportedRobot
|
|
95
|
+
instanceUrl={instanceUrl}
|
|
96
|
+
modelFromController={modelFromController}
|
|
97
|
+
{...rest}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (inverseSolver === null) {
|
|
103
|
+
return (
|
|
104
|
+
<SupportedLinearAxis
|
|
105
|
+
instanceUrl={instanceUrl}
|
|
106
|
+
modelFromController={modelFromController}
|
|
107
|
+
{...rest}
|
|
108
|
+
/>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return null
|
|
113
|
+
})
|
|
@@ -21,7 +21,8 @@ export type SupportedLinearAxisProps = {
|
|
|
21
21
|
modelFromController: string
|
|
22
22
|
dhParameters: DHParameter[]
|
|
23
23
|
flangeRef?: React.Ref<THREE.Group>
|
|
24
|
-
|
|
24
|
+
instanceUrl?: string
|
|
25
|
+
getModel?: (modelFromController: string, instanceUrl?: string) => Promise<string> | undefined
|
|
25
26
|
postModelRender?: () => void
|
|
26
27
|
transparentColor?: string
|
|
27
28
|
} & ThreeElements["group"]
|
|
@@ -35,6 +36,7 @@ export const SupportedLinearAxis = externalizeComponent(
|
|
|
35
36
|
flangeRef,
|
|
36
37
|
postModelRender,
|
|
37
38
|
transparentColor,
|
|
39
|
+
instanceUrl,
|
|
38
40
|
...props
|
|
39
41
|
}: SupportedLinearAxisProps) => {
|
|
40
42
|
const [robotGroup, setRobotGroup] = useState<THREE.Group | null>(null)
|
|
@@ -77,7 +79,7 @@ export const SupportedLinearAxis = externalizeComponent(
|
|
|
77
79
|
>
|
|
78
80
|
<GenericRobot
|
|
79
81
|
modelURL={(() => {
|
|
80
|
-
const result = getModel(modelFromController)
|
|
82
|
+
const result = getModel(modelFromController, instanceUrl)
|
|
81
83
|
if (!result) {
|
|
82
84
|
const mockBlob = new Blob([], { type: 'model/gltf-binary' })
|
|
83
85
|
const mockFile = new File([mockBlob], `${modelFromController}.glb`, { type: 'model/gltf-binary' })
|
|
@@ -22,7 +22,8 @@ export type SupportedRobotProps = {
|
|
|
22
22
|
modelFromController: string
|
|
23
23
|
dhParameters: DHParameter[]
|
|
24
24
|
flangeRef?: React.Ref<THREE.Group>
|
|
25
|
-
|
|
25
|
+
instanceUrl?: string
|
|
26
|
+
getModel?: (modelFromController: string, instanceUrl?: string) => Promise<string> | undefined
|
|
26
27
|
postModelRender?: () => void
|
|
27
28
|
transparentColor?: string
|
|
28
29
|
} & ThreeElements["group"]
|
|
@@ -36,6 +37,7 @@ export const SupportedRobot = externalizeComponent(
|
|
|
36
37
|
flangeRef,
|
|
37
38
|
postModelRender,
|
|
38
39
|
transparentColor,
|
|
40
|
+
instanceUrl,
|
|
39
41
|
...props
|
|
40
42
|
}: SupportedRobotProps) => {
|
|
41
43
|
const [robotGroup, setRobotGroup] = useState<THREE.Group | null>(null)
|
|
@@ -78,7 +80,7 @@ export const SupportedRobot = externalizeComponent(
|
|
|
78
80
|
>
|
|
79
81
|
<GenericRobot
|
|
80
82
|
modelURL={(() => {
|
|
81
|
-
const result = getModel(modelFromController)
|
|
83
|
+
const result = getModel(modelFromController, instanceUrl)
|
|
82
84
|
if (!result) {
|
|
83
85
|
const mockBlob = new Blob([], { type: 'model/gltf-binary' })
|
|
84
86
|
const mockFile = new File([mockBlob], `${modelFromController}.glb`, { type: 'model/gltf-binary' })
|
|
@@ -40,7 +40,7 @@ export async function revokeAllModelUrls(): Promise<void> {
|
|
|
40
40
|
modelCache.clear()
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export async function defaultGetModel(modelFromController: string): Promise<string> {
|
|
43
|
+
export async function defaultGetModel(modelFromController: string, instanceUrlProp?: string): Promise<string> {
|
|
44
44
|
// Check cache first
|
|
45
45
|
if (modelCache.has(modelFromController)) {
|
|
46
46
|
return modelCache.get(modelFromController)!
|
|
@@ -48,7 +48,7 @@ export async function defaultGetModel(modelFromController: string): Promise<stri
|
|
|
48
48
|
|
|
49
49
|
// Create the promise and cache it immediately to prevent duplicate calls
|
|
50
50
|
const modelPromise = (async () => {
|
|
51
|
-
const instanceUrl = import.meta.env.WANDELAPI_BASE_URL
|
|
51
|
+
const instanceUrl = instanceUrlProp || import.meta.env.WANDELAPI_BASE_URL
|
|
52
52
|
const nova = new NovaClient({ instanceUrl })
|
|
53
53
|
|
|
54
54
|
// Configure axios to handle binary responses for GLB files
|
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/
|
|
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
|
-
|
|
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
|
-
|
|
98
|
+
velocityValue: 0.1,
|
|
99
|
+
velocityUnit: "rad/s",
|
|
98
100
|
})
|
|
99
101
|
await delay(500)
|
|
100
102
|
await jogger.stop()
|
|
@@ -280,16 +280,20 @@ export class JoggerConnection {
|
|
|
280
280
|
* Jogging: Start rotation of a single robot joint at the specified velocity
|
|
281
281
|
*/
|
|
282
282
|
async rotateJoints({
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
joint,
|
|
284
|
+
direction,
|
|
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
|
|
292
|
-
|
|
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 === "-" ? -
|
|
307
|
+
direction === "-" ? - velocityValue : velocityValue
|
|
304
308
|
|
|
305
309
|
this.joggingSocket.sendJson({
|
|
306
310
|
message_type: "JointVelocityRequest",
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import Stack from "@mui/material/Stack";
|
|
2
|
-
type JoggingJointRotationControlProps = {
|
|
3
|
-
startJogging: (direction: "-" | "+") => void;
|
|
4
|
-
stopJogging: () => void;
|
|
5
|
-
lowerLimitDegs?: number;
|
|
6
|
-
upperLimitDegs?: number;
|
|
7
|
-
getValueDegs: () => number | undefined;
|
|
8
|
-
disabled?: boolean;
|
|
9
|
-
} & React.ComponentProps<typeof Stack>;
|
|
10
|
-
/** A input widget to control an individual joint */
|
|
11
|
-
export declare const JoggingJointRotationControl: (({ startJogging, stopJogging, lowerLimitDegs, upperLimitDegs, getValueDegs, disabled, ...rest }: JoggingJointRotationControlProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
12
|
-
displayName: string;
|
|
13
|
-
};
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=JoggingJointRotationControl.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"JoggingJointRotationControl.d.ts","sourceRoot":"","sources":["../../../src/components/jogging/JoggingJointRotationControl.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,qBAAqB,CAAA;AAQvC,KAAK,gCAAgC,GAAG;IACtC,YAAY,EAAE,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,KAAK,IAAI,CAAA;IAC5C,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;IAEtC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,KAAK,CAAC,CAAA;AAEtC,oDAAoD;AACpD,eAAO,MAAM,2BAA2B,oGAUjC,gCAAgC;;CAuNtC,CAAA"}
|