@wandelbots/wandelbots-js-react-components 2.54.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +1 -1
  2. package/dist/auth0-spa-js.production.esm-Bb4L9JDU.js +1423 -0
  3. package/dist/auth0-spa-js.production.esm-Bb4L9JDU.js.map +1 -0
  4. package/dist/auth0-spa-js.production.esm-CEI5Uihg.cjs +5 -0
  5. package/dist/auth0-spa-js.production.esm-CEI5Uihg.cjs.map +1 -0
  6. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts +1 -1
  7. package/dist/components/3d-viewport/CoordinateSystemTransform.d.ts.map +1 -1
  8. package/dist/components/3d-viewport/SafetyZonesRenderer.d.ts.map +1 -1
  9. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts +1 -1
  10. package/dist/components/3d-viewport/collider/ColliderCollection.d.ts.map +1 -1
  11. package/dist/components/3d-viewport/collider/ColliderElement.d.ts +1 -1
  12. package/dist/components/3d-viewport/collider/ColliderElement.d.ts.map +1 -1
  13. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts +1 -1
  14. package/dist/components/3d-viewport/collider/CollisionSceneRenderer.d.ts.map +1 -1
  15. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts +1 -1
  16. package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts.map +1 -1
  17. package/dist/components/ProgramStateIndicator.d.ts +3 -3
  18. package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
  19. package/dist/components/RobotCard.d.ts +4 -3
  20. package/dist/components/RobotCard.d.ts.map +1 -1
  21. package/dist/components/jogging/JoggingBlocked.d.ts +7 -0
  22. package/dist/components/jogging/JoggingBlocked.d.ts.map +1 -0
  23. package/dist/components/jogging/JoggingCartesianTab.d.ts.map +1 -1
  24. package/dist/components/jogging/JoggingJointTab.d.ts.map +1 -1
  25. package/dist/components/jogging/JoggingPanel.d.ts +1 -1
  26. package/dist/components/jogging/JoggingPanel.d.ts.map +1 -1
  27. package/dist/components/jogging/JoggingStore.d.ts +10 -5
  28. package/dist/components/jogging/JoggingStore.d.ts.map +1 -1
  29. package/dist/components/jogging/PoseCartesianValues.d.ts +2 -2
  30. package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
  31. package/dist/components/jogging/PoseJointValues.d.ts +1 -2
  32. package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
  33. package/dist/components/robots/DHRobot.d.ts.map +1 -1
  34. package/dist/components/robots/Robot.d.ts +1 -1
  35. package/dist/components/robots/Robot.d.ts.map +1 -1
  36. package/dist/components/robots/RobotAnimator.d.ts +2 -2
  37. package/dist/components/robots/RobotAnimator.d.ts.map +1 -1
  38. package/dist/components/robots/SupportedRobot.d.ts +3 -3
  39. package/dist/components/robots/SupportedRobot.d.ts.map +1 -1
  40. package/dist/components/robots/manufacturerHomePositions.d.ts +1 -1
  41. package/dist/components/robots/manufacturerHomePositions.d.ts.map +1 -1
  42. package/dist/components/safetyBar/OperationModeIndicator.d.ts +2 -2
  43. package/dist/components/safetyBar/OperationModeIndicator.d.ts.map +1 -1
  44. package/dist/components/safetyBar/SafetyBar.d.ts +3 -3
  45. package/dist/components/safetyBar/SafetyBar.d.ts.map +1 -1
  46. package/dist/components/safetyBar/SafetyStateIndicator.d.ts +2 -2
  47. package/dist/components/safetyBar/SafetyStateIndicator.d.ts.map +1 -1
  48. package/dist/components/utils/errorHandling.d.ts.map +1 -1
  49. package/dist/components/utils/errorHandling.test.d.ts +2 -0
  50. package/dist/components/utils/errorHandling.test.d.ts.map +1 -0
  51. package/dist/index.cjs +48 -50
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.js +14058 -18706
  54. package/dist/index.js.map +1 -1
  55. package/dist/lib/ConnectedMotionGroup.d.ts +90 -0
  56. package/dist/lib/ConnectedMotionGroup.d.ts.map +1 -0
  57. package/dist/lib/JoggerConnection.d.ts +113 -0
  58. package/dist/lib/JoggerConnection.d.ts.map +1 -0
  59. package/dist/lib/JoggerConnection.test.d.ts +2 -0
  60. package/dist/lib/JoggerConnection.test.d.ts.map +1 -0
  61. package/dist/lib/MotionStreamConnection.d.ts +24 -0
  62. package/dist/lib/MotionStreamConnection.d.ts.map +1 -0
  63. package/dist/lib/MotionStreamConnection.test.d.ts +2 -0
  64. package/dist/lib/MotionStreamConnection.test.d.ts.map +1 -0
  65. package/dist/lib/motionStateUpdate.d.ts +7 -0
  66. package/dist/lib/motionStateUpdate.d.ts.map +1 -0
  67. package/dist/lib/motionStateUpdate.test.d.ts +2 -0
  68. package/dist/lib/motionStateUpdate.test.d.ts.map +1 -0
  69. package/package.json +2 -2
  70. package/src/components/3d-viewport/CoordinateSystemTransform.tsx +1 -1
  71. package/src/components/3d-viewport/SafetyZonesRenderer.tsx +1 -2
  72. package/src/components/3d-viewport/collider/ColliderCollection.tsx +1 -1
  73. package/src/components/3d-viewport/collider/ColliderElement.tsx +1 -1
  74. package/src/components/3d-viewport/collider/CollisionSceneRenderer.tsx +1 -1
  75. package/src/components/3d-viewport/collider/colliderShapeToBufferGeometry.ts +1 -1
  76. package/src/components/ProgramStateIndicator.tsx +3 -6
  77. package/src/components/RobotCard.tsx +4 -7
  78. package/src/components/jogging/JoggingBlocked.tsx +37 -0
  79. package/src/components/jogging/JoggingCartesianTab.tsx +13 -11
  80. package/src/components/jogging/JoggingJointLimitDetector.tsx +2 -2
  81. package/src/components/jogging/JoggingJointTab.tsx +4 -3
  82. package/src/components/jogging/JoggingPanel.tsx +6 -3
  83. package/src/components/jogging/JoggingStore.ts +66 -39
  84. package/src/components/jogging/PoseCartesianValues.tsx +3 -4
  85. package/src/components/jogging/PoseJointValues.tsx +3 -4
  86. package/src/components/robots/DHRobot.tsx +2 -3
  87. package/src/components/robots/Robot.tsx +1 -1
  88. package/src/components/robots/RobotAnimator.test.tsx +7 -22
  89. package/src/components/robots/RobotAnimator.tsx +8 -13
  90. package/src/components/robots/SupportedRobot.tsx +3 -6
  91. package/src/components/robots/manufacturerHomePositions.ts +1 -1
  92. package/src/components/safetyBar/OperationModeIndicator.tsx +2 -2
  93. package/src/components/safetyBar/SafetyBar.tsx +3 -6
  94. package/src/components/safetyBar/SafetyStateIndicator.tsx +2 -2
  95. package/src/components/utils/errorHandling.test.ts +41 -0
  96. package/src/components/utils/errorHandling.ts +4 -0
  97. package/src/i18n/locales/de/translations.json +3 -0
  98. package/src/i18n/locales/en/translations.json +3 -0
  99. package/src/lib/ConnectedMotionGroup.ts +444 -0
  100. package/src/lib/JoggerConnection.test.ts +120 -0
  101. package/src/lib/JoggerConnection.ts +674 -0
  102. package/src/lib/MotionStreamConnection.test.ts +23 -0
  103. package/src/lib/MotionStreamConnection.ts +186 -0
  104. package/src/lib/motionStateUpdate.test.ts +28 -0
  105. package/src/lib/motionStateUpdate.ts +117 -0
  106. package/dist/auth0-spa-js.production.esm-1QXzndwB.js +0 -950
  107. package/dist/auth0-spa-js.production.esm-1QXzndwB.js.map +0 -1
  108. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs +0 -5
  109. package/dist/auth0-spa-js.production.esm-BLRAk7Yh.cjs.map +0 -1
@@ -0,0 +1,186 @@
1
+ import { AutoReconnectingWebsocket, tryParseJson } from "@wandelbots/nova-js"
2
+ import type {
3
+ MotionGroupDescription,
4
+ MotionGroupState,
5
+ NovaClient,
6
+ RobotControllerState,
7
+ } from "@wandelbots/nova-js/v2"
8
+ import { makeAutoObservable, runInAction } from "mobx"
9
+ import type { Vector3Simple } from "./JoggerConnection"
10
+ import {
11
+ jointValuesEqual,
12
+ tcpMotionEqual,
13
+ unwrapRotationVector,
14
+ } from "./motionStateUpdate"
15
+
16
+ const MOTION_DELTA_THRESHOLD = 0.0001
17
+
18
+ /**
19
+ * Store representing the current state of a connected motion group.
20
+ */
21
+ export class MotionStreamConnection {
22
+ static async open(nova: NovaClient, motionGroupId: string) {
23
+ const [_motionGroupIndex, controllerId] = motionGroupId.split("@") as [
24
+ string,
25
+ string,
26
+ ]
27
+
28
+ const controller =
29
+ await nova.api.controller.getCurrentRobotControllerState(controllerId)
30
+ const motionGroup = controller?.motion_groups.find(
31
+ (mg) => mg.motion_group === motionGroupId,
32
+ )
33
+ if (!controller || !motionGroup) {
34
+ throw new Error(
35
+ `Controller ${controllerId} or motion group ${motionGroupId} not found`,
36
+ )
37
+ }
38
+
39
+ const motionStateSocket = nova.openReconnectingWebsocket(
40
+ `/controllers/${controllerId}/motion-groups/${motionGroupId}/state-stream`,
41
+ )
42
+
43
+ // Wait for the first message to get the initial state
44
+ const firstMessage = await motionStateSocket.firstMessage()
45
+ const initialMotionState = tryParseJson(firstMessage.data)
46
+ ?.result as MotionGroupState
47
+
48
+ if (!initialMotionState) {
49
+ throw new Error(
50
+ `Unable to parse initial motion state message ${firstMessage.data}`,
51
+ )
52
+ }
53
+
54
+ console.log(
55
+ `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state:\n `,
56
+ initialMotionState,
57
+ )
58
+
59
+ // Get the motion group description for later usage in jogging
60
+ const description = await nova.api.motionGroup.getMotionGroupDescription(
61
+ controllerId,
62
+ motionGroup.motion_group,
63
+ )
64
+
65
+ return new MotionStreamConnection(
66
+ nova,
67
+ controller,
68
+ motionGroup,
69
+ description,
70
+ initialMotionState,
71
+ motionStateSocket,
72
+ )
73
+ }
74
+
75
+ // Not mobx-observable as this changes very fast; should be observed
76
+ // using animation frames
77
+ rapidlyChangingMotionState: MotionGroupState
78
+
79
+ constructor(
80
+ readonly nova: NovaClient,
81
+ readonly controller: RobotControllerState,
82
+ readonly motionGroup: MotionGroupState,
83
+ readonly description: MotionGroupDescription,
84
+ readonly initialMotionState: MotionGroupState,
85
+ readonly motionStateSocket: AutoReconnectingWebsocket,
86
+ ) {
87
+ this.rapidlyChangingMotionState = initialMotionState
88
+
89
+ motionStateSocket.addEventListener("message", (event) => {
90
+ const latestMotionState = tryParseJson(event.data)?.result as
91
+ | MotionGroupState
92
+ | undefined
93
+
94
+ if (!latestMotionState) {
95
+ throw new Error(
96
+ `Failed to get motion state for ${this.motionGroupId}: ${event.data}`,
97
+ )
98
+ }
99
+
100
+ // handle joint position changes
101
+ if (
102
+ !jointValuesEqual(
103
+ this.rapidlyChangingMotionState.joint_position,
104
+ latestMotionState.joint_position,
105
+ MOTION_DELTA_THRESHOLD,
106
+ )
107
+ ) {
108
+ runInAction(() => {
109
+ this.rapidlyChangingMotionState.joint_position =
110
+ latestMotionState.joint_position
111
+ })
112
+ }
113
+
114
+ // handle tcp pose changes
115
+ if (
116
+ !tcpMotionEqual(
117
+ this.rapidlyChangingMotionState,
118
+ latestMotionState,
119
+ MOTION_DELTA_THRESHOLD,
120
+ )
121
+ ) {
122
+ runInAction(() => {
123
+ if (this.rapidlyChangingMotionState.tcp_pose == null) {
124
+ this.rapidlyChangingMotionState.tcp_pose =
125
+ latestMotionState.tcp_pose
126
+ } else if (
127
+ latestMotionState.tcp_pose?.orientation &&
128
+ latestMotionState.tcp_pose?.position &&
129
+ this.rapidlyChangingMotionState.tcp_pose?.orientation
130
+ ) {
131
+ this.rapidlyChangingMotionState.tcp_pose = {
132
+ position: latestMotionState.tcp_pose.position,
133
+ orientation: unwrapRotationVector(
134
+ latestMotionState.tcp_pose.orientation as Vector3Simple,
135
+ this.rapidlyChangingMotionState.tcp_pose
136
+ .orientation as Vector3Simple,
137
+ ),
138
+ }
139
+ } else {
140
+ console.warn(
141
+ "Received incomplete tcp_pose, ignoring",
142
+ latestMotionState.tcp_pose,
143
+ )
144
+ }
145
+ })
146
+ }
147
+
148
+ // handle standstill changes
149
+ if (
150
+ this.rapidlyChangingMotionState.standstill !==
151
+ latestMotionState.standstill
152
+ ) {
153
+ runInAction(() => {
154
+ this.rapidlyChangingMotionState.standstill =
155
+ latestMotionState.standstill
156
+ })
157
+ }
158
+ })
159
+ makeAutoObservable(this)
160
+ }
161
+
162
+ get motionGroupId() {
163
+ return this.motionGroup.motion_group
164
+ }
165
+
166
+ get controllerId() {
167
+ return this.controller.controller
168
+ }
169
+
170
+ get wandelscriptIdentifier() {
171
+ const num = this.motionGroupId.split("@")[0]
172
+ return `${this.controllerId.replace(/-/g, "_")}_${num}`
173
+ }
174
+
175
+ get joints() {
176
+ return this.initialMotionState.joint_position.map((_, i) => {
177
+ return {
178
+ index: i,
179
+ }
180
+ })
181
+ }
182
+
183
+ dispose() {
184
+ this.motionStateSocket.close()
185
+ }
186
+ }
@@ -0,0 +1,28 @@
1
+ import { describe, expect, test } from "vitest"
2
+ import { poseEqual } from "./motionStateUpdate"
3
+
4
+ describe("poseEqual", async () => {
5
+ test("returns true for identical poses", () => {
6
+ const pose1 = {
7
+ position: [0, 0, 0],
8
+ orientation: [0, 0, 0],
9
+ }
10
+ const pose2 = {
11
+ position: [0, 0, 0],
12
+ orientation: [0, 0, 0],
13
+ }
14
+ expect(poseEqual(pose1, pose2, 0.001)).toBe(true)
15
+ })
16
+
17
+ test("returns false for different poses", () => {
18
+ const pose1 = {
19
+ position: [0, 0, 0],
20
+ orientation: [0, 0, 0],
21
+ }
22
+ const pose2 = {
23
+ position: [1, 1, 1],
24
+ orientation: [1, 1, 1],
25
+ }
26
+ expect(poseEqual(pose1, pose2, 0.001)).toBe(false)
27
+ })
28
+ })
@@ -0,0 +1,117 @@
1
+ import type { MotionGroupState, Pose } from "@wandelbots/nova-js/v2"
2
+ import type { Vector3Simple } from "./JoggerConnection"
3
+ import { Vector3 } from "three"
4
+
5
+ export function jointValuesEqual(
6
+ oldJointValues: number[],
7
+ newJointValues: number[],
8
+ changeDeltaThreshold: number,
9
+ ): boolean {
10
+ if (newJointValues.length !== oldJointValues.length) {
11
+ return true
12
+ }
13
+
14
+ for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) {
15
+ if (
16
+ // biome-ignore lint/style/noNonNullAssertion: legacy code
17
+ Math.abs(newJointValues[jointIndex]! - oldJointValues[jointIndex]!) >
18
+ changeDeltaThreshold
19
+ ) {
20
+ return false
21
+ }
22
+ }
23
+
24
+ return true
25
+ }
26
+
27
+ export function poseEqual(
28
+ oldTcp: Pose | undefined,
29
+ newTcp: Pose | undefined,
30
+ changeDeltaThreshold: number,
31
+ ): boolean {
32
+ // undefined -> defined (+reverse) transition
33
+ if ((oldTcp === undefined && newTcp) || (oldTcp && newTcp === undefined)) {
34
+ return false
35
+ }
36
+
37
+ // Poses might be incomplete (missing orientation or position)
38
+ if (
39
+ oldTcp?.orientation === undefined ||
40
+ newTcp?.orientation === undefined ||
41
+ oldTcp?.position === undefined ||
42
+ newTcp?.position === undefined
43
+ ) {
44
+ return false
45
+ }
46
+
47
+ // the typechecker cannot resolve states to "!= undefined" if "&&" is used
48
+ if (oldTcp === undefined || newTcp === undefined) {
49
+ return true
50
+ }
51
+
52
+ let changedDelta = 0
53
+ changedDelta += Math.abs(oldTcp.orientation[0] - newTcp.orientation[0])
54
+ changedDelta += Math.abs(oldTcp.orientation[1] - newTcp.orientation[1])
55
+ changedDelta += Math.abs(oldTcp.orientation[2] - newTcp.orientation[2])
56
+ changedDelta += Math.abs(oldTcp.position[0] - newTcp.position[0])
57
+ changedDelta += Math.abs(oldTcp.position[1] - newTcp.position[1])
58
+ changedDelta += Math.abs(oldTcp.position[2] - newTcp.position[2])
59
+
60
+ return changedDelta <= changeDeltaThreshold
61
+ }
62
+
63
+ // Runs poseEqual check + coordinate system/tcp name equality
64
+ export function tcpMotionEqual(
65
+ oldMotionState: MotionGroupState,
66
+ newMotionState: MotionGroupState,
67
+ changeDeltaThreshold: number,
68
+ ): boolean {
69
+ return (
70
+ oldMotionState.coordinate_system === newMotionState.coordinate_system &&
71
+ oldMotionState.tcp === newMotionState.tcp &&
72
+ poseEqual(
73
+ oldMotionState.tcp_pose,
74
+ newMotionState.tcp_pose,
75
+ changeDeltaThreshold,
76
+ )
77
+ )
78
+ }
79
+
80
+ export function unwrapRotationVector(
81
+ newRotationVectorApi: Vector3Simple,
82
+ currentRotationVectorApi: Vector3Simple,
83
+ ): Vector3Simple {
84
+ const currentRotationVector = new Vector3(
85
+ currentRotationVectorApi[0],
86
+ currentRotationVectorApi[1],
87
+ currentRotationVectorApi[2],
88
+ )
89
+
90
+ const newRotationVector = new Vector3(
91
+ newRotationVectorApi[0],
92
+ newRotationVectorApi[1],
93
+ newRotationVectorApi[2],
94
+ )
95
+
96
+ const currentAngle = currentRotationVector.length()
97
+ const currentAxis = currentRotationVector.normalize()
98
+
99
+ let newAngle = newRotationVector.length()
100
+ let newAxis = newRotationVector.normalize()
101
+
102
+ // Align rotation axes
103
+ if (newAxis.dot(currentAxis) < 0) {
104
+ newAngle = -newAngle
105
+ newAxis = newAxis.multiplyScalar(-1.0)
106
+ }
107
+
108
+ // Shift rotation angle close to previous one to extend domain of rotation angles beyond [0, pi]
109
+ // - this simplifies interpolation and prevents abruptly changing signs of the rotation angles
110
+ let angleDifference = newAngle - currentAngle
111
+ angleDifference -=
112
+ 2.0 * Math.PI * Math.floor((angleDifference + Math.PI) / (2.0 * Math.PI))
113
+
114
+ newAngle = currentAngle + angleDifference
115
+
116
+ return [...newAxis.multiplyScalar(newAngle)] as Vector3Simple
117
+ }