@wandelbots/wandelbots-js-react-components 3.5.1-pr.feat-add-eight-abbs-v2.450.4419c66 → 3.6.0-pr.feat-model-retrieval-from-rdp.463.3cb7d2e
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 +79 -10
- package/dist/3d.cjs.js +2 -0
- package/dist/3d.cjs.js.map +1 -0
- package/dist/3d.d.ts +11 -0
- package/dist/3d.d.ts.map +1 -0
- package/dist/3d.es.js +16 -0
- package/dist/3d.es.js.map +1 -0
- package/dist/LoadingCover-6gWr11KP.js +88 -0
- package/dist/LoadingCover-6gWr11KP.js.map +1 -0
- package/dist/LoadingCover-CukpS_aj.cjs +2 -0
- package/dist/LoadingCover-CukpS_aj.cjs.map +1 -0
- package/dist/WandelscriptEditor-7eN-Yw7m.js +140 -0
- package/dist/WandelscriptEditor-7eN-Yw7m.js.map +1 -0
- package/dist/WandelscriptEditor-D6_vS5Uk.cjs +2 -0
- package/dist/WandelscriptEditor-D6_vS5Uk.cjs.map +1 -0
- package/dist/auth0-spa-js.production.esm-BMSlxZC5.js +3877 -0
- package/dist/auth0-spa-js.production.esm-BMSlxZC5.js.map +1 -0
- package/dist/auth0-spa-js.production.esm-DZ6lsBvD.cjs +5 -0
- package/dist/auth0-spa-js.production.esm-DZ6lsBvD.cjs.map +1 -0
- package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts +1 -1
- package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts.map +1 -1
- package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts.map +1 -1
- package/dist/components/3d-viewport/collider/ColliderCollection.d.ts +1 -1
- package/dist/components/3d-viewport/collider/ColliderCollection.d.ts.map +1 -1
- package/dist/components/3d-viewport/collider/ColliderElement.d.ts +1 -1
- package/dist/components/3d-viewport/collider/ColliderElement.d.ts.map +1 -1
- package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts +1 -1
- package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts.map +1 -1
- package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts +1 -1
- package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts.map +1 -1
- package/dist/components/ProgramStateIndicator.d.ts +3 -3
- package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
- package/dist/components/RobotCard.d.ts +5 -4
- package/dist/components/RobotCard.d.ts.map +1 -1
- package/dist/components/jogging/JoggingBlocked.d.ts +7 -0
- package/dist/components/jogging/JoggingBlocked.d.ts.map +1 -0
- package/dist/components/jogging/JoggingCartesianTab.d.ts.map +1 -1
- package/dist/components/jogging/JoggingOptions.d.ts.map +1 -1
- package/dist/components/jogging/JoggingPanel.d.ts +1 -1
- package/dist/components/jogging/JoggingPanel.d.ts.map +1 -1
- package/dist/components/jogging/JoggingStore.d.ts +10 -5
- package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
- package/dist/components/jogging/PoseCartesianValues.d.ts +2 -2
- package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
- package/dist/components/jogging/PoseJointValues.d.ts +1 -2
- package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
- package/dist/components/robots/DHRobot.d.ts.map +1 -1
- package/dist/components/robots/GenericRobot.d.ts +2 -2
- package/dist/components/robots/GenericRobot.d.ts.map +1 -1
- package/dist/components/robots/Robot.d.ts +2 -2
- package/dist/components/robots/Robot.d.ts.map +1 -1
- package/dist/components/robots/RobotAnimator.d.ts +2 -2
- package/dist/components/robots/RobotAnimator.d.ts.map +1 -1
- package/dist/components/robots/SupportedRobot.d.ts +4 -4
- package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
- package/dist/components/robots/manufacturerHomePositions.d.ts +1 -1
- package/dist/components/robots/manufacturerHomePositions.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/components/safetyBar/ControllerTypeIndicator.d.ts.map +1 -1
- package/dist/components/safetyBar/OperationModeIndicator.d.ts +2 -2
- package/dist/components/safetyBar/OperationModeIndicator.d.ts.map +1 -1
- package/dist/components/safetyBar/SafetyBar.d.ts +3 -3
- package/dist/components/safetyBar/SafetyBar.d.ts.map +1 -1
- package/dist/components/safetyBar/SafetyStateIndicator.d.ts +2 -2
- package/dist/components/safetyBar/SafetyStateIndicator.d.ts.map +1 -1
- package/dist/components/utils/errorHandling.d.ts.map +1 -1
- package/dist/components/utils/errorHandling.test.d.ts +2 -0
- package/dist/components/utils/errorHandling.test.d.ts.map +1 -0
- package/dist/core.cjs.js +2 -0
- package/dist/core.cjs.js.map +1 -0
- package/dist/core.d.ts +33 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.es.js +54 -0
- package/dist/core.es.js.map +1 -0
- package/dist/externalizeComponent-CkVWk2F_.cjs +24 -0
- package/dist/externalizeComponent-CkVWk2F_.cjs.map +1 -0
- package/dist/externalizeComponent-Dc3fViZA.js +489 -0
- package/dist/externalizeComponent-Dc3fViZA.js.map +1 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +3 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +69 -0
- package/dist/index.es.js.map +1 -0
- package/dist/interpolation-DAXKfoDS.cjs +20 -0
- package/dist/interpolation-DAXKfoDS.cjs.map +1 -0
- package/dist/interpolation-DcPbemBD.js +6924 -0
- package/dist/interpolation-DcPbemBD.js.map +1 -0
- package/dist/lib/ConnectedMotionGroup.d.ts +90 -0
- package/dist/lib/ConnectedMotionGroup.d.ts.map +1 -0
- package/dist/lib/JoggerConnection.d.ts +113 -0
- package/dist/lib/JoggerConnection.d.ts.map +1 -0
- package/dist/lib/JoggerConnection.test.d.ts +2 -0
- package/dist/lib/JoggerConnection.test.d.ts.map +1 -0
- package/dist/lib/MotionStreamConnection.d.ts +24 -0
- package/dist/lib/MotionStreamConnection.d.ts.map +1 -0
- package/dist/lib/MotionStreamConnection.test.d.ts +2 -0
- package/dist/lib/MotionStreamConnection.test.d.ts.map +1 -0
- package/dist/lib/motionStateUpdate.d.ts +7 -0
- package/dist/lib/motionStateUpdate.d.ts.map +1 -0
- package/dist/lib/motionStateUpdate.test.d.ts +2 -0
- package/dist/lib/motionStateUpdate.test.d.ts.map +1 -0
- package/dist/manufacturerHomePositions-BaS-GAxw.js +1025 -0
- package/dist/manufacturerHomePositions-BaS-GAxw.js.map +1 -0
- package/dist/manufacturerHomePositions-cD52vnEi.cjs +2 -0
- package/dist/manufacturerHomePositions-cD52vnEi.cjs.map +1 -0
- package/dist/theming-B7ojcJTM.js +22239 -0
- package/dist/theming-B7ojcJTM.js.map +1 -0
- package/dist/theming-C9apy9Ov.cjs +115 -0
- package/dist/theming-C9apy9Ov.cjs.map +1 -0
- package/dist/wandelscript.cjs.js +2 -0
- package/dist/wandelscript.cjs.js.map +1 -0
- package/dist/wandelscript.d.ts +2 -0
- package/dist/wandelscript.d.ts.map +1 -0
- package/dist/wandelscript.es.js +5 -0
- package/dist/wandelscript.es.js.map +1 -0
- package/package.json +68 -30
- package/src/3d.ts +15 -0
- package/src/components/3d-viewport/CoordinateSystemTransform.tsx +1 -1
- package/src/components/3d-viewport/SafetyZonesRenderer.tsx +1 -2
- package/src/components/3d-viewport/collider/ColliderCollection.tsx +1 -1
- package/src/components/3d-viewport/collider/ColliderElement.tsx +1 -1
- package/src/components/3d-viewport/collider/CollisionSceneRenderer.tsx +1 -1
- package/src/components/3d-viewport/collider/colliderShapeToBufferGeometry.ts +1 -1
- package/src/components/AppHeader.md +1 -1
- package/src/components/ProgramStateIndicator.tsx +3 -6
- package/src/components/RobotCard.tsx +5 -8
- package/src/components/jogging/JoggingBlocked.tsx +37 -0
- package/src/components/jogging/JoggingCartesianTab.tsx +13 -11
- package/src/components/jogging/JoggingJointLimitDetector.tsx +2 -2
- package/src/components/jogging/JoggingJointTab.tsx +4 -4
- package/src/components/jogging/JoggingOptions.tsx +6 -5
- package/src/components/jogging/JoggingPanel.tsx +6 -3
- package/src/components/jogging/JoggingStore.ts +66 -39
- package/src/components/jogging/PoseCartesianValues.tsx +3 -4
- package/src/components/jogging/PoseJointValues.tsx +3 -4
- package/src/components/robots/DHRobot.tsx +2 -3
- package/src/components/robots/GenericRobot.tsx +56 -13
- package/src/components/robots/Robot.tsx +2 -2
- package/src/components/robots/RobotAnimator.test.tsx +7 -22
- package/src/components/robots/RobotAnimator.tsx +8 -13
- package/src/components/robots/SupportedRobot.tsx +13 -8
- package/src/components/robots/manufacturerHomePositions.ts +1 -1
- package/src/components/robots/robotModelLogic.ts +40 -6
- package/src/components/safetyBar/ControllerTypeIndicator.tsx +4 -2
- package/src/components/safetyBar/OperationModeIndicator.tsx +7 -5
- package/src/components/safetyBar/SafetyBar.tsx +3 -6
- package/src/components/safetyBar/SafetyStateIndicator.tsx +9 -7
- package/src/components/utils/errorHandling.test.ts +41 -0
- package/src/components/utils/errorHandling.ts +4 -0
- package/src/core.ts +33 -0
- package/src/env.d.ts +3 -0
- package/src/i18n/locales/de/translations.json +3 -0
- package/src/i18n/locales/en/translations.json +3 -0
- package/src/index.ts +4 -43
- package/src/lib/ConnectedMotionGroup.ts +444 -0
- package/src/lib/JoggerConnection.test.ts +120 -0
- package/src/lib/JoggerConnection.ts +674 -0
- package/src/lib/MotionStreamConnection.test.ts +23 -0
- package/src/lib/MotionStreamConnection.ts +189 -0
- package/src/lib/motionStateUpdate.test.ts +28 -0
- package/src/lib/motionStateUpdate.ts +117 -0
- package/src/wandelscript.ts +2 -0
- package/dist/auth0-spa-js.production.esm-1QXzndwB.js +0 -950
- package/dist/auth0-spa-js.production.esm-1QXzndwB.js.map +0 -1
- package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs +0 -5
- package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs.map +0 -1
- package/dist/index.cjs +0 -155
- package/dist/index.cjs.map +0 -1
- package/dist/index.js +0 -34927
- package/dist/index.js.map +0 -1
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { tryParseJson } from "@wandelbots/nova-js"
|
|
2
2
|
import type {
|
|
3
3
|
CoordinateSystem,
|
|
4
|
-
|
|
5
|
-
MotionGroupSpecification,
|
|
4
|
+
MotionGroupDescription,
|
|
6
5
|
RobotTcp,
|
|
7
|
-
} from "@wandelbots/nova-js/
|
|
6
|
+
} from "@wandelbots/nova-js/v2"
|
|
8
7
|
import { countBy } from "lodash-es"
|
|
9
8
|
import keyBy from "lodash-es/keyBy"
|
|
10
9
|
import uniqueId from "lodash-es/uniqueId"
|
|
11
10
|
import { autorun, makeAutoObservable, type IReactionDisposer } from "mobx"
|
|
11
|
+
import type {
|
|
12
|
+
JoggerConnection,
|
|
13
|
+
JoggerOrientation,
|
|
14
|
+
Vector3Simple,
|
|
15
|
+
} from "../../lib/JoggerConnection"
|
|
12
16
|
|
|
13
17
|
const discreteIncrementOptions = [
|
|
14
18
|
{ id: "0.1", mm: 0.1, degrees: 0.05 },
|
|
@@ -55,6 +59,9 @@ export class JoggingStore {
|
|
|
55
59
|
/** Locks to prevent UI interactions during certain operations */
|
|
56
60
|
locks = new Set<string>()
|
|
57
61
|
|
|
62
|
+
/** Block jogging UI interactions when connection is taken by another jogger */
|
|
63
|
+
blocked: boolean = false
|
|
64
|
+
|
|
58
65
|
/**
|
|
59
66
|
* Id of selected coordinate system from among those defined on the API side
|
|
60
67
|
*/
|
|
@@ -105,7 +112,7 @@ export class JoggingStore {
|
|
|
105
112
|
maxRotationVelocityDegPerSec: number = 60
|
|
106
113
|
|
|
107
114
|
/** Whether to show the coordinate system select dropdown in the UI */
|
|
108
|
-
showCoordSystemSelect: boolean =
|
|
115
|
+
showCoordSystemSelect: boolean = false
|
|
109
116
|
|
|
110
117
|
/** Whether to show the TCP select dropdown in the UI */
|
|
111
118
|
showTcpSelect: boolean = true
|
|
@@ -138,34 +145,34 @@ export class JoggingStore {
|
|
|
138
145
|
const { nova } = jogger
|
|
139
146
|
|
|
140
147
|
// Find out what TCPs this motion group has (we need it for jogging)
|
|
141
|
-
const [
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
148
|
+
const [coordinatesystems, description] = await Promise.all([
|
|
149
|
+
// Fetch coord systems so user can select between them
|
|
150
|
+
nova.api.controller.listCoordinateSystems(
|
|
151
|
+
jogger.motionStream.controllerId,
|
|
152
|
+
"ROTATION_VECTOR",
|
|
153
|
+
),
|
|
154
|
+
|
|
155
|
+
// Same for TCPs and other info from description
|
|
156
|
+
nova.api.motionGroup.getMotionGroupDescription(
|
|
157
|
+
jogger.motionStream.controllerId,
|
|
158
|
+
jogger.motionGroupId,
|
|
159
|
+
),
|
|
160
|
+
])
|
|
161
|
+
|
|
162
|
+
const tcps = Object.entries(description.tcps || {}).map(([id, tcp]) => ({
|
|
163
|
+
id,
|
|
164
|
+
readable_name: tcp.name,
|
|
165
|
+
position: tcp.pose.position as Vector3Simple,
|
|
166
|
+
orientation: tcp.pose.orientation as Vector3Simple,
|
|
167
|
+
}))
|
|
168
|
+
|
|
169
|
+
return new JoggingStore(jogger, coordinatesystems || [], description, tcps)
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
constructor(
|
|
166
173
|
readonly jogger: JoggerConnection,
|
|
167
|
-
readonly motionGroupSpec: MotionGroupSpecification,
|
|
168
174
|
readonly coordSystems: CoordinateSystem[],
|
|
175
|
+
readonly motionGroupDescription: MotionGroupDescription,
|
|
169
176
|
readonly tcps: RobotTcp[],
|
|
170
177
|
) {
|
|
171
178
|
// TODO workaround for default coord system on backend having a canonical id
|
|
@@ -179,13 +186,21 @@ export class JoggingStore {
|
|
|
179
186
|
this.selectedCoordSystemId = coordSystems[0]?.coordinate_system || "world"
|
|
180
187
|
this.selectedTcpId = tcps[0]?.id || ""
|
|
181
188
|
|
|
189
|
+
// Make all properties observable and actions auto-bound
|
|
182
190
|
makeAutoObservable(this, {}, { autoBind: true })
|
|
183
191
|
|
|
192
|
+
// Register blocked watching
|
|
193
|
+
this.jogger.onBlocked = () => {
|
|
194
|
+
this.block()
|
|
195
|
+
}
|
|
196
|
+
|
|
184
197
|
// Load user settings from local storage if available
|
|
185
198
|
this.loadFromLocalStorage()
|
|
186
199
|
|
|
187
200
|
// Automatically save user settings to local storage when save changes
|
|
188
201
|
this.disposers.push(autorun(() => this.saveToLocalStorage()))
|
|
202
|
+
|
|
203
|
+
// Assign joggingStore to window
|
|
189
204
|
;(window as any).joggingStore = this
|
|
190
205
|
}
|
|
191
206
|
|
|
@@ -201,30 +216,31 @@ export class JoggingStore {
|
|
|
201
216
|
}
|
|
202
217
|
|
|
203
218
|
async deactivate() {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
this.jogger.setJoggingMode("increment")
|
|
207
|
-
|
|
208
|
-
if (websocket) {
|
|
209
|
-
await websocket.closed()
|
|
219
|
+
if (this.jogger.mode === "jogging") {
|
|
220
|
+
return this.jogger.stop()
|
|
210
221
|
}
|
|
211
222
|
}
|
|
212
223
|
|
|
213
224
|
/** Activate the jogger with current settings */
|
|
214
225
|
async activate() {
|
|
215
226
|
if (this.currentTab.id === "cartesian") {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
227
|
+
if (
|
|
228
|
+
this.jogger.tcp !== this.selectedTcpId ||
|
|
229
|
+
this.jogger.orientation !== this.selectedOrientation
|
|
230
|
+
) {
|
|
231
|
+
this.jogger.setOptions({
|
|
232
|
+
tcp: this.selectedTcpId,
|
|
233
|
+
orientation: this.selectedOrientation as JoggerOrientation,
|
|
234
|
+
})
|
|
219
235
|
}
|
|
220
236
|
|
|
221
237
|
if (this.activeDiscreteIncrement) {
|
|
222
|
-
this.jogger.setJoggingMode("
|
|
238
|
+
this.jogger.setJoggingMode("trajectory")
|
|
223
239
|
} else {
|
|
224
|
-
this.jogger.setJoggingMode("
|
|
240
|
+
this.jogger.setJoggingMode("jogging")
|
|
225
241
|
}
|
|
226
242
|
} else {
|
|
227
|
-
this.jogger.setJoggingMode("
|
|
243
|
+
this.jogger.setJoggingMode("jogging")
|
|
228
244
|
}
|
|
229
245
|
|
|
230
246
|
return this.jogger
|
|
@@ -433,6 +449,17 @@ export class JoggingStore {
|
|
|
433
449
|
this.locks.delete(id)
|
|
434
450
|
}
|
|
435
451
|
|
|
452
|
+
block() {
|
|
453
|
+
this.blocked = true
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
unblock() {
|
|
457
|
+
this.blocked = false
|
|
458
|
+
if (this.jogger.mode === "jogging") {
|
|
459
|
+
this.jogger.initializeJoggingWebsocket()
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
436
463
|
/** Lock the UI until the given async callback resolves */
|
|
437
464
|
async withMotionLock(fn: () => Promise<void>) {
|
|
438
465
|
const lockId = uniqueId()
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Button, Stack } from "@mui/material"
|
|
2
|
-
import { poseToWandelscriptString } from "@wandelbots/nova-js"
|
|
3
|
-
import type { TcpPose } from "@wandelbots/nova-js/v1"
|
|
2
|
+
import { poseToWandelscriptString, type Pose } from "@wandelbots/nova-js/v2"
|
|
4
3
|
import { observer } from "mobx-react-lite"
|
|
5
4
|
import { useState } from "react"
|
|
6
5
|
import { externalizeComponent } from "../../externalizeComponent"
|
|
7
6
|
import { CopyableText } from "../CopyableText"
|
|
8
7
|
|
|
9
8
|
export type PoseCartesianValuesProps = {
|
|
10
|
-
tcpPose:
|
|
9
|
+
tcpPose: Pose
|
|
11
10
|
showCopyButton?: boolean
|
|
12
11
|
}
|
|
13
12
|
|
|
@@ -44,7 +43,7 @@ export const PoseCartesianValues = externalizeComponent(
|
|
|
44
43
|
onClick={handleCopy}
|
|
45
44
|
sx={{ flexShrink: 0 }}
|
|
46
45
|
>
|
|
47
|
-
{
|
|
46
|
+
{copyMessage ? copyMessage : "Copy"}
|
|
48
47
|
</Button>
|
|
49
48
|
)}
|
|
50
49
|
</Stack>
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { Button, Stack } from "@mui/material"
|
|
2
|
-
import type { Joints } from "@wandelbots/nova-api/v1"
|
|
3
2
|
import { observer } from "mobx-react-lite"
|
|
4
3
|
import { useState } from "react"
|
|
5
4
|
import { externalizeComponent } from "../../externalizeComponent"
|
|
6
5
|
import { CopyableText } from "../CopyableText"
|
|
7
6
|
|
|
8
7
|
export type PoseJointValuesProps = {
|
|
9
|
-
joints:
|
|
8
|
+
joints: Array<number>
|
|
10
9
|
showCopyButton?: boolean
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export const PoseJointValues = externalizeComponent(
|
|
14
13
|
observer(({ joints, showCopyButton = false }: PoseJointValuesProps) => {
|
|
15
14
|
const [copyMessage, setCopyMessage] = useState<string | null>(null)
|
|
16
|
-
const poseString = `[${joints.
|
|
15
|
+
const poseString = `[${joints.map((j: number) => parseFloat(j.toFixed(4))).join(", ")}]`
|
|
17
16
|
|
|
18
17
|
const handleCopy = async () => {
|
|
19
18
|
try {
|
|
@@ -43,7 +42,7 @@ export const PoseJointValues = externalizeComponent(
|
|
|
43
42
|
onClick={handleCopy}
|
|
44
43
|
sx={{ flexShrink: 0 }}
|
|
45
44
|
>
|
|
46
|
-
{
|
|
45
|
+
{copyMessage ? copyMessage : "Copy"}
|
|
47
46
|
</Button>
|
|
48
47
|
)}
|
|
49
48
|
</Stack>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Line } from "@react-three/drei"
|
|
2
|
-
import type { DHParameter } from "@wandelbots/nova-
|
|
2
|
+
import type { DHParameter } from "@wandelbots/nova-js/v2"
|
|
3
3
|
import React, { useRef } from "react"
|
|
4
4
|
import type * as THREE from "three"
|
|
5
5
|
import { Matrix4, Quaternion, Vector3 } from "three"
|
|
@@ -113,8 +113,7 @@ export function DHRobot({
|
|
|
113
113
|
{dhParameters!.map((param, index) => {
|
|
114
114
|
const { a, b } = getLinePoints(
|
|
115
115
|
param,
|
|
116
|
-
rapidlyChangingMotionState.
|
|
117
|
-
0,
|
|
116
|
+
rapidlyChangingMotionState.joint_position[index] ?? 0,
|
|
118
117
|
)
|
|
119
118
|
const jointName = `dhrobot_J0${index}`
|
|
120
119
|
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 } from "react"
|
|
3
|
+
import React, { useCallback, useEffect, useState } 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
|
|
9
|
+
modelURL: string | Promise<string>
|
|
10
10
|
/**
|
|
11
11
|
* Called after a robot model has been loaded and
|
|
12
12
|
* rendered into the threejs scene
|
|
@@ -19,16 +19,19 @@ function isMesh(node: Object3D): node is Mesh {
|
|
|
19
19
|
return node.type === "Mesh"
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
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
|
+
const { gltf } = parseRobotModel(gltfResult, 'robot.glb')
|
|
32
35
|
|
|
33
36
|
const groupRef: React.RefCallback<Group> = useCallback(
|
|
34
37
|
(group) => {
|
|
@@ -36,7 +39,7 @@ export function GenericRobot({
|
|
|
36
39
|
postModelRender()
|
|
37
40
|
}
|
|
38
41
|
},
|
|
39
|
-
[
|
|
42
|
+
[postModelRender],
|
|
40
43
|
)
|
|
41
44
|
|
|
42
45
|
function renderNode(node: Object3D): React.ReactNode {
|
|
@@ -72,3 +75,43 @@ export function GenericRobot({
|
|
|
72
75
|
</group>
|
|
73
76
|
)
|
|
74
77
|
}
|
|
78
|
+
|
|
79
|
+
export function GenericRobot({
|
|
80
|
+
modelURL,
|
|
81
|
+
flangeRef,
|
|
82
|
+
postModelRender,
|
|
83
|
+
...props
|
|
84
|
+
}: RobotModelProps) {
|
|
85
|
+
const [resolvedURL, setResolvedURL] = useState<string | null>(null)
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const resolveURL = async () => {
|
|
89
|
+
try {
|
|
90
|
+
if (typeof modelURL === 'string') {
|
|
91
|
+
setResolvedURL(modelURL)
|
|
92
|
+
} else {
|
|
93
|
+
const url = await modelURL
|
|
94
|
+
setResolvedURL(url)
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error('Failed to resolve model URL:', error)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
resolveURL()
|
|
102
|
+
}, [modelURL])
|
|
103
|
+
|
|
104
|
+
// Don't render until we have a resolved URL
|
|
105
|
+
if (!resolvedURL) {
|
|
106
|
+
return null // Loading state
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<LoadedRobotModel
|
|
111
|
+
url={resolvedURL}
|
|
112
|
+
flangeRef={flangeRef}
|
|
113
|
+
postModelRender={postModelRender}
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { ThreeElements } from "@react-three/fiber"
|
|
2
2
|
|
|
3
|
-
import type { ConnectedMotionGroup } from "@wandelbots/nova-js/v1"
|
|
4
3
|
import type { Group } from "three"
|
|
4
|
+
import type { ConnectedMotionGroup } from "../../lib/ConnectedMotionGroup"
|
|
5
5
|
import { defaultGetModel } from "./robotModelLogic"
|
|
6
6
|
import { SupportedRobot } from "./SupportedRobot"
|
|
7
7
|
|
|
8
8
|
export type RobotProps = {
|
|
9
9
|
connectedMotionGroup: ConnectedMotionGroup
|
|
10
|
-
getModel?: (modelFromController: string) => string
|
|
10
|
+
getModel?: (modelFromController: string) => Promise<string>
|
|
11
11
|
flangeRef?: React.Ref<Group>
|
|
12
12
|
transparentColor?: string
|
|
13
13
|
postModelRender?: () => void
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
DHParameter,
|
|
3
|
-
MotionGroupStateResponse,
|
|
4
|
-
} from "@wandelbots/nova-api/v1"
|
|
1
|
+
import type { DHParameter, MotionGroupState } from "@wandelbots/nova-api/v2"
|
|
5
2
|
import { describe, expect, it, vi } from "vitest"
|
|
6
3
|
import RobotAnimator from "./RobotAnimator"
|
|
7
4
|
|
|
@@ -26,12 +23,8 @@ describe("RobotAnimator", () => {
|
|
|
26
23
|
|
|
27
24
|
it("should handle props with different numbers of joints", () => {
|
|
28
25
|
// Test that the component accepts different numbers of DH parameters
|
|
29
|
-
const mockMotionState4Joints:
|
|
30
|
-
|
|
31
|
-
joint_position: {
|
|
32
|
-
joints: [0.1, 0.2, 0.3, 0.4],
|
|
33
|
-
},
|
|
34
|
-
},
|
|
26
|
+
const mockMotionState4Joints: MotionGroupState = {
|
|
27
|
+
joint_position: [0.1, 0.2, 0.3, 0.4],
|
|
35
28
|
} as any
|
|
36
29
|
|
|
37
30
|
const mockDHParameters4Joints: DHParameter[] = [
|
|
@@ -41,12 +34,8 @@ describe("RobotAnimator", () => {
|
|
|
41
34
|
{ theta: 0, reverse_rotation_direction: false },
|
|
42
35
|
]
|
|
43
36
|
|
|
44
|
-
const mockMotionState7Joints:
|
|
45
|
-
|
|
46
|
-
joint_position: {
|
|
47
|
-
joints: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
37
|
+
const mockMotionState7Joints: MotionGroupState = {
|
|
38
|
+
joint_position: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7],
|
|
50
39
|
} as any
|
|
51
40
|
|
|
52
41
|
const mockDHParameters7Joints: DHParameter[] = Array(7).fill({
|
|
@@ -63,9 +52,7 @@ describe("RobotAnimator", () => {
|
|
|
63
52
|
}
|
|
64
53
|
// Verify props are correctly typed
|
|
65
54
|
expect(props4.dhParameters).toHaveLength(4)
|
|
66
|
-
expect(
|
|
67
|
-
props4.rapidlyChangingMotionState.state.joint_position.joints,
|
|
68
|
-
).toHaveLength(4)
|
|
55
|
+
expect(props4.rapidlyChangingMotionState.joint_position).toHaveLength(4)
|
|
69
56
|
}).not.toThrow()
|
|
70
57
|
|
|
71
58
|
expect(() => {
|
|
@@ -75,9 +62,7 @@ describe("RobotAnimator", () => {
|
|
|
75
62
|
children: null,
|
|
76
63
|
}
|
|
77
64
|
expect(props7.dhParameters).toHaveLength(7)
|
|
78
|
-
expect(
|
|
79
|
-
props7.rapidlyChangingMotionState.state.joint_position.joints,
|
|
80
|
-
).toHaveLength(7)
|
|
65
|
+
expect(props7.rapidlyChangingMotionState.joint_position).toHaveLength(7)
|
|
81
66
|
}).not.toThrow()
|
|
82
67
|
})
|
|
83
68
|
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { useFrame, useThree } from "@react-three/fiber"
|
|
2
|
-
import type {
|
|
3
|
-
DHParameter,
|
|
4
|
-
MotionGroupStateResponse,
|
|
5
|
-
} from "@wandelbots/nova-api/v1"
|
|
2
|
+
import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
|
|
6
3
|
import React, { useEffect, useRef } from "react"
|
|
7
4
|
import type { Group, Object3D } from "three"
|
|
8
5
|
import { useAutorun } from "../utils/hooks"
|
|
@@ -10,7 +7,7 @@ import { ValueInterpolator } from "../utils/interpolation"
|
|
|
10
7
|
import { collectJoints } from "./robotModelLogic"
|
|
11
8
|
|
|
12
9
|
type RobotAnimatorProps = {
|
|
13
|
-
rapidlyChangingMotionState:
|
|
10
|
+
rapidlyChangingMotionState: MotionGroupState
|
|
14
11
|
dhParameters: DHParameter[]
|
|
15
12
|
onRotationChanged?: (joints: Object3D[], jointValues: number[]) => void
|
|
16
13
|
children: React.ReactNode
|
|
@@ -29,10 +26,9 @@ export default function RobotAnimator({
|
|
|
29
26
|
|
|
30
27
|
// Initialize interpolator
|
|
31
28
|
useEffect(() => {
|
|
32
|
-
const initialJointValues =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
)
|
|
29
|
+
const initialJointValues = rapidlyChangingMotionState.joint_position.filter(
|
|
30
|
+
(item) => item !== undefined,
|
|
31
|
+
)
|
|
36
32
|
|
|
37
33
|
interpolatorRef.current = new ValueInterpolator(initialJointValues, {
|
|
38
34
|
tension: 120, // Controls spring stiffness - higher values create faster, more responsive motion
|
|
@@ -91,10 +87,9 @@ export default function RobotAnimator({
|
|
|
91
87
|
}
|
|
92
88
|
|
|
93
89
|
useAutorun(() => {
|
|
94
|
-
const newJointValues =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
90
|
+
const newJointValues = rapidlyChangingMotionState.joint_position.filter(
|
|
91
|
+
(item) => item !== undefined,
|
|
92
|
+
)
|
|
98
93
|
|
|
99
94
|
requestAnimationFrame(() => updateJoints(newJointValues))
|
|
100
95
|
})
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { ThreeElements } from "@react-three/fiber"
|
|
2
|
-
import type {
|
|
3
|
-
DHParameter,
|
|
4
|
-
MotionGroupStateResponse,
|
|
5
|
-
} from "@wandelbots/nova-api/v1"
|
|
2
|
+
import type { DHParameter, MotionGroupState } from "@wandelbots/nova-js/v2"
|
|
6
3
|
import { Suspense, useCallback, useEffect, useState } from "react"
|
|
7
4
|
import { DHRobot } from "./DHRobot"
|
|
8
5
|
|
|
@@ -16,16 +13,16 @@ import { applyGhostStyle, removeGhostStyle } from "./ghostStyle"
|
|
|
16
13
|
import { defaultGetModel } from "./robotModelLogic"
|
|
17
14
|
|
|
18
15
|
export type DHRobotProps = {
|
|
19
|
-
rapidlyChangingMotionState:
|
|
16
|
+
rapidlyChangingMotionState: MotionGroupState
|
|
20
17
|
dhParameters: Array<DHParameter>
|
|
21
18
|
} & ThreeElements["group"]
|
|
22
19
|
|
|
23
20
|
export type SupportedRobotProps = {
|
|
24
|
-
rapidlyChangingMotionState:
|
|
21
|
+
rapidlyChangingMotionState: MotionGroupState
|
|
25
22
|
modelFromController: string
|
|
26
23
|
dhParameters: DHParameter[]
|
|
27
24
|
flangeRef?: React.Ref<THREE.Group>
|
|
28
|
-
getModel?: (modelFromController: string) => string
|
|
25
|
+
getModel?: (modelFromController: string) => Promise<string> | undefined
|
|
29
26
|
postModelRender?: () => void
|
|
30
27
|
transparentColor?: string
|
|
31
28
|
} & ThreeElements["group"]
|
|
@@ -80,7 +77,15 @@ export const SupportedRobot = externalizeComponent(
|
|
|
80
77
|
dhParameters={dhParameters}
|
|
81
78
|
>
|
|
82
79
|
<GenericRobot
|
|
83
|
-
modelURL={
|
|
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
|
+
})()}
|
|
84
89
|
postModelRender={postModelRender}
|
|
85
90
|
flangeRef={flangeRef}
|
|
86
91
|
{...props}
|
|
@@ -1,13 +1,47 @@
|
|
|
1
|
+
import { NovaClient } from "@wandelbots/nova-js/v2"
|
|
1
2
|
import type { Object3D } from "three"
|
|
2
3
|
import type { GLTF } from "three-stdlib"
|
|
3
|
-
import { version } from "../../../package.json"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const modelCache = new Map<string, Promise<string>>()
|
|
6
|
+
|
|
7
|
+
export async function defaultGetModel(modelFromController: string): Promise<string> {
|
|
8
|
+
// Check cache first
|
|
9
|
+
if (modelCache.has(modelFromController)) {
|
|
10
|
+
return modelCache.get(modelFromController)!
|
|
9
11
|
}
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
// Create the promise and cache it immediately to prevent duplicate calls
|
|
14
|
+
const modelPromise = (async () => {
|
|
15
|
+
const instanceUrl = import.meta.env.WANDELAPI_BASE_URL || import.meta.env.VITE_NOVA_INSTANCE_URL
|
|
16
|
+
|
|
17
|
+
const nova = new NovaClient({ instanceUrl })
|
|
18
|
+
|
|
19
|
+
// Configure axios to handle binary responses for GLB files
|
|
20
|
+
const apiInstance = nova.api.motionGroupModels as any
|
|
21
|
+
if (apiInstance.axios?.interceptors) {
|
|
22
|
+
apiInstance.axios.interceptors.request.use((config: any) => {
|
|
23
|
+
if (config.url?.includes('/glb')) {
|
|
24
|
+
config.responseType = 'blob'
|
|
25
|
+
}
|
|
26
|
+
return config
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const file = await nova.api.motionGroupModels.getMotionGroupGlbModel(modelFromController)
|
|
32
|
+
|
|
33
|
+
// Create object URL from the file and return it
|
|
34
|
+
const url = URL.createObjectURL(file)
|
|
35
|
+
return url
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error("Failed to fetch model:", error)
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
})()
|
|
41
|
+
|
|
42
|
+
// Cache the promise
|
|
43
|
+
modelCache.set(modelFromController, modelPromise)
|
|
44
|
+
return modelPromise
|
|
11
45
|
}
|
|
12
46
|
|
|
13
47
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useTheme, type PopoverOrigin } from "@mui/material"
|
|
2
2
|
import { observer } from "mobx-react-lite"
|
|
3
|
+
import { useId } from "react"
|
|
3
4
|
import { Trans, useTranslation } from "react-i18next"
|
|
4
5
|
import ControllerTypePhysicalIcon from "./icons/controller-type-physical.svg"
|
|
5
6
|
import ControllerTypeVirtualIcon from "./icons/controller-type-virtual.svg"
|
|
@@ -22,12 +23,13 @@ export const ControllerTypeIndicator = observer(
|
|
|
22
23
|
compact,
|
|
23
24
|
}: ControllerTypeIndicatorProps) => {
|
|
24
25
|
const theme = useTheme()
|
|
26
|
+
const componentId = useId()
|
|
25
27
|
const { t } = useTranslation()
|
|
26
28
|
|
|
27
29
|
if (isVirtual) {
|
|
28
30
|
return (
|
|
29
31
|
<IndicatorWithExplanation
|
|
30
|
-
id=
|
|
32
|
+
id={`motion-group-virtual-${componentId}`}
|
|
31
33
|
icon={ControllerTypeVirtualIcon}
|
|
32
34
|
color={theme.palette.tertiary.main}
|
|
33
35
|
name={t("SafetyBar.ControllerType.Virtual.lb")}
|
|
@@ -52,7 +54,7 @@ export const ControllerTypeIndicator = observer(
|
|
|
52
54
|
|
|
53
55
|
return (
|
|
54
56
|
<IndicatorWithExplanation
|
|
55
|
-
id=
|
|
57
|
+
id={`motion-group-physical-${componentId}`}
|
|
56
58
|
icon={ControllerTypePhysicalIcon}
|
|
57
59
|
color={theme.palette.primary.main}
|
|
58
60
|
name={t("SafetyBar.ControllerType.Physical.lb")}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useTheme, type PopoverOrigin } from "@mui/material"
|
|
2
|
-
import type {
|
|
2
|
+
import type { OperationMode } from "@wandelbots/nova-js/v2"
|
|
3
3
|
import { observer } from "mobx-react-lite"
|
|
4
|
+
import { useId } from "react"
|
|
4
5
|
import { Trans, useTranslation } from "react-i18next"
|
|
5
6
|
import OperationModeAutomaticIcon from "./icons/operation-mode-automatic.svg"
|
|
6
7
|
import OperationModeErrorIcon from "./icons/operation-mode-error.svg"
|
|
@@ -8,7 +9,7 @@ import OperationModeManualIcon from "./icons/operation-mode-manual.svg"
|
|
|
8
9
|
import { IndicatorWithExplanation } from "./IndicatorWithExplanation"
|
|
9
10
|
|
|
10
11
|
interface OperationModeIndicatorProps {
|
|
11
|
-
operationMode:
|
|
12
|
+
operationMode: OperationMode
|
|
12
13
|
anchorOrigin?: PopoverOrigin
|
|
13
14
|
transformOrigin?: PopoverOrigin
|
|
14
15
|
compact: boolean
|
|
@@ -23,12 +24,13 @@ export const OperationModeIndicator = observer(
|
|
|
23
24
|
}: OperationModeIndicatorProps) => {
|
|
24
25
|
const { t } = useTranslation()
|
|
25
26
|
const theme = useTheme()
|
|
27
|
+
const componentId = useId()
|
|
26
28
|
|
|
27
29
|
switch (operationMode) {
|
|
28
30
|
case "OPERATION_MODE_AUTO":
|
|
29
31
|
return (
|
|
30
32
|
<IndicatorWithExplanation
|
|
31
|
-
id=
|
|
33
|
+
id={`operation-mode-auto-${componentId}`}
|
|
32
34
|
icon={OperationModeAutomaticIcon}
|
|
33
35
|
title={t("SafetyBar.OperationMode.ti")}
|
|
34
36
|
name={t("SafetyBar.OperationMode.Automatic.ti")}
|
|
@@ -49,7 +51,7 @@ export const OperationModeIndicator = observer(
|
|
|
49
51
|
case "OPERATION_MODE_MANUAL_T2": {
|
|
50
52
|
return (
|
|
51
53
|
<IndicatorWithExplanation
|
|
52
|
-
id=
|
|
54
|
+
id={`operation-mode-manual-${componentId}`}
|
|
53
55
|
icon={OperationModeManualIcon}
|
|
54
56
|
color={theme.palette.warning.main}
|
|
55
57
|
title={t("SafetyBar.OperationMode.ti")}
|
|
@@ -71,7 +73,7 @@ export const OperationModeIndicator = observer(
|
|
|
71
73
|
default:
|
|
72
74
|
return (
|
|
73
75
|
<IndicatorWithExplanation
|
|
74
|
-
id=
|
|
76
|
+
id={`operation-mode-error-${componentId}`}
|
|
75
77
|
icon={OperationModeErrorIcon}
|
|
76
78
|
color={theme.palette.warning.main}
|
|
77
79
|
title={t("SafetyBar.OperationMode.ti")}
|