@wandelbots/wandelbots-js-react-components 2.10.3 → 2.11.0-pr.feat-collision-scene.263.cb851a8
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/dist/components/3d-viewport/collider/ColliderCollection.d.ts +11 -0
- package/dist/components/3d-viewport/collider/ColliderCollection.d.ts.map +1 -0
- package/dist/components/3d-viewport/collider/ColliderElement.d.ts +10 -0
- package/dist/components/3d-viewport/collider/ColliderElement.d.ts.map +1 -0
- package/dist/components/3d-viewport/collider/CollisionMotionGroup.d.ts +14 -0
- package/dist/components/3d-viewport/collider/CollisionMotionGroup.d.ts.map +1 -0
- package/dist/components/3d-viewport/collider/CollisionScene.d.ts +16 -0
- package/dist/components/3d-viewport/collider/CollisionScene.d.ts.map +1 -0
- package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts +4 -0
- package/dist/components/3d-viewport/collider/colliderShapeToBufferGeometry.d.ts.map +1 -0
- package/dist/components/robots/DHRobot.d.ts.map +1 -1
- package/dist/components/safetyBar/ControllerTypeIndicator.d.ts +9 -0
- package/dist/components/safetyBar/ControllerTypeIndicator.d.ts.map +1 -0
- package/dist/components/safetyBar/IndicatorWithExplanation.d.ts +15 -0
- package/dist/components/safetyBar/IndicatorWithExplanation.d.ts.map +1 -0
- package/dist/components/safetyBar/OperationModeIndicator.d.ts +9 -0
- package/dist/components/safetyBar/OperationModeIndicator.d.ts.map +1 -0
- package/dist/components/safetyBar/SafetyBar.d.ts +11 -0
- package/dist/components/safetyBar/SafetyBar.d.ts.map +1 -0
- package/dist/components/safetyBar/SafetyStateIndicator.d.ts +9 -0
- package/dist/components/safetyBar/SafetyStateIndicator.d.ts.map +1 -0
- package/dist/components/utils/dhParameter.d.ts +7 -0
- package/dist/components/utils/dhParameter.d.ts.map +1 -0
- package/dist/components/utils/errorHandling.d.ts +1 -0
- package/dist/components/utils/errorHandling.d.ts.map +1 -1
- package/dist/index.cjs +36 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4165 -3759
- package/dist/index.js.map +1 -1
- package/package.json +15 -16
- package/src/components/3d-viewport/collider/ColliderCollection.tsx +34 -0
- package/src/components/3d-viewport/collider/ColliderElement.tsx +32 -0
- package/src/components/3d-viewport/collider/CollisionMotionGroup.tsx +88 -0
- package/src/components/3d-viewport/collider/CollisionScene.tsx +59 -0
- package/src/components/3d-viewport/collider/colliderShapeToBufferGeometry.ts +36 -0
- package/src/components/robots/DHRobot.tsx +22 -44
- package/src/components/safetyBar/ControllerTypeIndicator.tsx +59 -0
- package/src/components/safetyBar/IndicatorWithExplanation.tsx +117 -0
- package/src/components/safetyBar/OperationModeIndicator.tsx +76 -0
- package/src/components/safetyBar/SafetyBar.tsx +43 -0
- package/src/components/safetyBar/SafetyStateIndicator.tsx +131 -0
- package/src/components/safetyBar/icons/controller-type-physical.svg +1 -0
- package/src/components/safetyBar/icons/controller-type-virtual.svg +1 -0
- package/src/components/safetyBar/icons/operation-mode-automatic.svg +1 -0
- package/src/components/safetyBar/icons/operation-mode-error.svg +1 -0
- package/src/components/safetyBar/icons/operation-mode-manual.svg +1 -0
- package/src/components/safetyBar/icons/safety-state-error.svg +1 -0
- package/src/components/safetyBar/icons/safety-state-estop.svg +1 -0
- package/src/components/safetyBar/icons/safety-state-manual-action-required.svg +1 -0
- package/src/components/safetyBar/icons/safety-state-normal.svg +1 -0
- package/src/components/safetyBar/icons/safety-state-stop.svg +1 -0
- package/src/components/utils/dhParameter.ts +58 -0
- package/src/components/utils/errorHandling.ts +4 -0
- package/src/i18n/locales/de/translations.json +27 -1
- package/src/i18n/locales/en/translations.json +27 -1
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wandelbots/wandelbots-js-react-components",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0-pr.feat-collision-scene.263.cb851a8",
|
|
4
4
|
"description": "React UI toolkit for building applications on top of the Wandelbots platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -55,16 +55,16 @@
|
|
|
55
55
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
56
56
|
"@rollup/plugin-terser": "^0.4.4",
|
|
57
57
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
58
|
-
"@storybook/addon-docs": "^8.
|
|
59
|
-
"@storybook/addon-essentials": "^8.
|
|
60
|
-
"@storybook/addon-interactions": "^8.
|
|
61
|
-
"@storybook/blocks": "^8.
|
|
62
|
-
"@storybook/react": "^8.
|
|
63
|
-
"@storybook/csf-tools": "^8.
|
|
64
|
-
"@storybook/react-vite": "^8.
|
|
65
|
-
"@storybook/test": "^8.
|
|
58
|
+
"@storybook/addon-docs": "^8.6.2",
|
|
59
|
+
"@storybook/addon-essentials": "^8.6.2",
|
|
60
|
+
"@storybook/addon-interactions": "^8.6.2",
|
|
61
|
+
"@storybook/blocks": "^8.6.2",
|
|
62
|
+
"@storybook/react": "^8.6.2",
|
|
63
|
+
"@storybook/csf-tools": "^8.6.2",
|
|
64
|
+
"@storybook/react-vite": "^8.6.2",
|
|
65
|
+
"@storybook/test": "^8.6.2",
|
|
66
66
|
"@storybook/test-runner": "^0.21.3",
|
|
67
|
-
"@storybook/types": "^8.
|
|
67
|
+
"@storybook/types": "^8.6.2",
|
|
68
68
|
"@svgr/rollup": "^8.1.0",
|
|
69
69
|
"@types/lodash-es": "^4.17.12",
|
|
70
70
|
"@types/react": "^18.3.12",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
91
91
|
"rollup-plugin-postcss": "^4.0.2",
|
|
92
92
|
"semantic-release": "^24.2.3",
|
|
93
|
-
"storybook": "^8.
|
|
93
|
+
"storybook": "^8.6.2",
|
|
94
94
|
"storybook-dark-mode": "^4.0.2",
|
|
95
95
|
"storybook-preset-inline-svg": "^1.0.1",
|
|
96
96
|
"ts-dedent": "^2.2.0",
|
|
@@ -100,10 +100,9 @@
|
|
|
100
100
|
"vite-plugin-svgr": "^4.3.0",
|
|
101
101
|
"vitest": "^3.0.7",
|
|
102
102
|
"wait-on": "^8.0.2",
|
|
103
|
-
"@wandelbots/wandelbots-js": "^1.
|
|
103
|
+
"@wandelbots/wandelbots-js": "^1.17.1"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
|
-
"@wandelbots/wandelbots-js": "^1.12.0",
|
|
107
106
|
"@emotion/react": "^11.11.1",
|
|
108
107
|
"@emotion/styled": "^11.11.0",
|
|
109
108
|
"@mui/icons-material": "^6",
|
|
@@ -113,7 +112,7 @@
|
|
|
113
112
|
"@react-three/fiber": "~8.18.0",
|
|
114
113
|
"react": "~18.3.1",
|
|
115
114
|
"react-dom": "~18.3.1",
|
|
116
|
-
"three": ">=0.
|
|
115
|
+
"three": ">=0.174",
|
|
117
116
|
"three-stdlib": ">=2"
|
|
118
117
|
},
|
|
119
118
|
"peerDependenciesMeta": {
|
|
@@ -123,13 +122,13 @@
|
|
|
123
122
|
},
|
|
124
123
|
"dependencies": {
|
|
125
124
|
"@monaco-editor/react": "^4.7.0",
|
|
126
|
-
"@shikijs/monaco": "^3.
|
|
125
|
+
"@shikijs/monaco": "^3.1.0",
|
|
127
126
|
"i18next-browser-languagedetector": "^8.0.4",
|
|
128
127
|
"lodash-es": "^4.17.21",
|
|
129
128
|
"mobx": "^6.13.6",
|
|
130
129
|
"mobx-react-lite": "^4.1.0",
|
|
131
130
|
"react-error-boundary": "^5.0.0",
|
|
132
131
|
"react-i18next": "^15.4.1",
|
|
133
|
-
"shiki": "^3.
|
|
132
|
+
"shiki": "^3.1.0"
|
|
134
133
|
}
|
|
135
134
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { GroupProps } from "@react-three/fiber"
|
|
2
|
+
import type { Collider } from "@wandelbots/wandelbots-js"
|
|
3
|
+
import ColliderElement from "./ColliderElement"
|
|
4
|
+
|
|
5
|
+
export type MeshChildrenProvider = (
|
|
6
|
+
key: string,
|
|
7
|
+
collider: Collider,
|
|
8
|
+
) => React.ReactNode
|
|
9
|
+
|
|
10
|
+
type ColliderCollectionProps = {
|
|
11
|
+
name?: string
|
|
12
|
+
colliders: Record<string, Collider>
|
|
13
|
+
meshChildrenProvider: MeshChildrenProvider
|
|
14
|
+
} & GroupProps
|
|
15
|
+
|
|
16
|
+
export default function ColliderCollection({
|
|
17
|
+
name,
|
|
18
|
+
colliders,
|
|
19
|
+
meshChildrenProvider,
|
|
20
|
+
...props
|
|
21
|
+
}: ColliderCollectionProps) {
|
|
22
|
+
return (
|
|
23
|
+
<group name={name} {...props}>
|
|
24
|
+
{Object.entries(colliders).map(([colliderKey, collider]) => (
|
|
25
|
+
<ColliderElement
|
|
26
|
+
key={colliderKey}
|
|
27
|
+
name={colliderKey}
|
|
28
|
+
collider={collider}
|
|
29
|
+
children={meshChildrenProvider(colliderKey, collider)}
|
|
30
|
+
/>
|
|
31
|
+
))}
|
|
32
|
+
</group>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Collider } from "@wandelbots/wandelbots-js"
|
|
2
|
+
import type React from "react"
|
|
3
|
+
import * as THREE from "three"
|
|
4
|
+
import { colliderShapeToBufferGeometry } from "./colliderShapeToBufferGeometry"
|
|
5
|
+
|
|
6
|
+
type ColliderElementProps = {
|
|
7
|
+
name?: string
|
|
8
|
+
collider: Collider
|
|
9
|
+
children?: React.ReactNode
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default function ColliderElement({
|
|
13
|
+
name,
|
|
14
|
+
collider,
|
|
15
|
+
children,
|
|
16
|
+
}: ColliderElementProps) {
|
|
17
|
+
const position = collider.pose?.position ?? [0, 0, 0]
|
|
18
|
+
const rotation = collider.pose?.orientation ?? [0, 0, 0]
|
|
19
|
+
if (collider.margin) {
|
|
20
|
+
console.warn(`${name} margin is not supported`)
|
|
21
|
+
}
|
|
22
|
+
return (
|
|
23
|
+
<mesh
|
|
24
|
+
name={name}
|
|
25
|
+
position={new THREE.Vector3(position[0], position[1], position[2]).divideScalar(1000)}
|
|
26
|
+
rotation={new THREE.Euler(rotation[0], rotation[1], rotation[2], "XYZ")}
|
|
27
|
+
geometry={colliderShapeToBufferGeometry(collider.shape)}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</mesh>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CollisionMotionGroup,
|
|
3
|
+
DHParameter,
|
|
4
|
+
MotionGroupStateResponse,
|
|
5
|
+
} from "@wandelbots/wandelbots-js"
|
|
6
|
+
import * as THREE from "three"
|
|
7
|
+
import { DHRobot } from "../../robots/DHRobot"
|
|
8
|
+
import { getDHTransform } from "../../utils/dhParameter"
|
|
9
|
+
import ColliderCollection, {
|
|
10
|
+
type MeshChildrenProvider,
|
|
11
|
+
} from "./ColliderCollection"
|
|
12
|
+
|
|
13
|
+
type CollisionMotionGroupElementProps = {
|
|
14
|
+
name?: string
|
|
15
|
+
motionGroup: CollisionMotionGroup
|
|
16
|
+
rapidlyChangingMotionState: MotionGroupStateResponse
|
|
17
|
+
dhParameters: DHParameter[]
|
|
18
|
+
mountingPosition?: THREE.Vector3
|
|
19
|
+
|
|
20
|
+
meshChildrenProvider: MeshChildrenProvider
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function CollisionMotionGroupElement({
|
|
24
|
+
name,
|
|
25
|
+
motionGroup,
|
|
26
|
+
rapidlyChangingMotionState,
|
|
27
|
+
dhParameters,
|
|
28
|
+
mountingPosition,
|
|
29
|
+
meshChildrenProvider,
|
|
30
|
+
}: CollisionMotionGroupElementProps) {
|
|
31
|
+
const joints = rapidlyChangingMotionState.state.joint_position?.joints
|
|
32
|
+
const jointTransform = new THREE.Matrix4()
|
|
33
|
+
const jointTransforms = getJointTransforms()
|
|
34
|
+
const toolTransform = jointTransform
|
|
35
|
+
|
|
36
|
+
console.log(joints, jointTransforms)
|
|
37
|
+
if (!joints) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getJointTransforms() {
|
|
42
|
+
jointTransform.identity()
|
|
43
|
+
|
|
44
|
+
return [
|
|
45
|
+
jointTransform.clone(),
|
|
46
|
+
...joints?.map((joint, jointIndex) => {
|
|
47
|
+
jointTransform.multiply(getDHTransform(dhParameters[jointIndex], joint))
|
|
48
|
+
return {
|
|
49
|
+
position: new THREE.Vector3().applyMatrix4(jointTransform),
|
|
50
|
+
rotation: new THREE.Euler().setFromRotationMatrix(jointTransform),
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<group
|
|
58
|
+
name={name}
|
|
59
|
+
position={mountingPosition ?? new THREE.Vector3(0, 0, 0)}
|
|
60
|
+
>
|
|
61
|
+
<DHRobot
|
|
62
|
+
dhParameters={dhParameters}
|
|
63
|
+
rapidlyChangingMotionState={rapidlyChangingMotionState}
|
|
64
|
+
/>
|
|
65
|
+
{motionGroup.link_chain &&
|
|
66
|
+
motionGroup.link_chain.map((chainSegment, jointIndex) => (
|
|
67
|
+
<group name="robot" {...(jointTransforms ?? [])[jointIndex]}>
|
|
68
|
+
<ColliderCollection
|
|
69
|
+
colliders={chainSegment}
|
|
70
|
+
meshChildrenProvider={meshChildrenProvider}
|
|
71
|
+
/>
|
|
72
|
+
</group>
|
|
73
|
+
))}
|
|
74
|
+
{motionGroup.tool && (
|
|
75
|
+
<group
|
|
76
|
+
name="tool"
|
|
77
|
+
position={new THREE.Vector3(0, 0, 0).applyMatrix4(toolTransform)}
|
|
78
|
+
rotation={new THREE.Euler().setFromRotationMatrix(toolTransform)}
|
|
79
|
+
>
|
|
80
|
+
<ColliderCollection
|
|
81
|
+
colliders={motionGroup.tool}
|
|
82
|
+
meshChildrenProvider={meshChildrenProvider}
|
|
83
|
+
/>
|
|
84
|
+
</group>
|
|
85
|
+
)}
|
|
86
|
+
</group>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CollisionScene,
|
|
3
|
+
DHParameter,
|
|
4
|
+
MotionGroupStateResponse,
|
|
5
|
+
} from "@wandelbots/wandelbots-js"
|
|
6
|
+
import * as THREE from "three"
|
|
7
|
+
import ColliderCollection, {
|
|
8
|
+
type MeshChildrenProvider,
|
|
9
|
+
} from "./ColliderCollection"
|
|
10
|
+
import CollisionMotionGroupElement from "./CollisionMotionGroup"
|
|
11
|
+
|
|
12
|
+
type MotionGroupData = {
|
|
13
|
+
state: MotionGroupStateResponse
|
|
14
|
+
dhParameters: DHParameter[]
|
|
15
|
+
mountingPosition: THREE.Vector3
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type CollisionSceneElementProps = {
|
|
19
|
+
scene: CollisionScene
|
|
20
|
+
meshChildrenProvider: MeshChildrenProvider
|
|
21
|
+
motionGroupStates: Record<string, MotionGroupData>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function CollisionSceneElement({
|
|
25
|
+
scene,
|
|
26
|
+
motionGroupStates,
|
|
27
|
+
meshChildrenProvider,
|
|
28
|
+
}: CollisionSceneElementProps) {
|
|
29
|
+
const colliders = scene.colliders
|
|
30
|
+
const motionGroups = scene.motion_groups ?? {}
|
|
31
|
+
return (
|
|
32
|
+
<group>
|
|
33
|
+
{colliders && (
|
|
34
|
+
<ColliderCollection
|
|
35
|
+
meshChildrenProvider={meshChildrenProvider}
|
|
36
|
+
colliders={colliders}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
{Object.entries(motionGroups)
|
|
40
|
+
.filter(
|
|
41
|
+
([motionGroupKey, _]) =>
|
|
42
|
+
motionGroupStates[motionGroupKey] !== undefined,
|
|
43
|
+
)
|
|
44
|
+
.map(([motionGroupKey, motionGroup]) => (
|
|
45
|
+
<CollisionMotionGroupElement
|
|
46
|
+
key={motionGroupKey}
|
|
47
|
+
name={motionGroupKey}
|
|
48
|
+
motionGroup={motionGroup}
|
|
49
|
+
mountingPosition={
|
|
50
|
+
motionGroupStates[motionGroupKey].mountingPosition
|
|
51
|
+
}
|
|
52
|
+
dhParameters={motionGroupStates[motionGroupKey].dhParameters}
|
|
53
|
+
meshChildrenProvider={meshChildrenProvider}
|
|
54
|
+
rapidlyChangingMotionState={motionGroupStates[motionGroupKey].state}
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</group>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ColliderShape } from "@wandelbots/wandelbots-js"
|
|
2
|
+
import * as THREE from "three"
|
|
3
|
+
import { ConvexGeometry } from "three-stdlib"
|
|
4
|
+
|
|
5
|
+
export function colliderShapeToBufferGeometry(
|
|
6
|
+
shape: ColliderShape,
|
|
7
|
+
): THREE.BufferGeometry {
|
|
8
|
+
const shapeType = shape.shape_type
|
|
9
|
+
switch (shapeType) {
|
|
10
|
+
case "convex_hull":
|
|
11
|
+
return new ConvexGeometry(
|
|
12
|
+
shape.vertices.map(
|
|
13
|
+
(vertex) => new THREE.Vector3(vertex[0] / 1000, vertex[1] / 1000, vertex[2] / 1000),
|
|
14
|
+
),
|
|
15
|
+
)
|
|
16
|
+
case "box":
|
|
17
|
+
return new THREE.BoxGeometry(shape.size_x / 1000, shape.size_y / 1000, shape.size_z / 1000)
|
|
18
|
+
case "sphere":
|
|
19
|
+
return new THREE.SphereGeometry(shape.radius / 1000)
|
|
20
|
+
case "capsule":
|
|
21
|
+
return new THREE.CapsuleGeometry(shape.radius / 1000, shape.cylinder_height / 1000)
|
|
22
|
+
case "cylinder":
|
|
23
|
+
return new THREE.CylinderGeometry(
|
|
24
|
+
shape.radius / 1000,
|
|
25
|
+
shape.radius / 1000,
|
|
26
|
+
shape.height / 1000,
|
|
27
|
+
)
|
|
28
|
+
case "rectangle": {
|
|
29
|
+
return new THREE.BoxGeometry(shape.size_x / 1000, shape.size_y / 1000, 0)
|
|
30
|
+
}
|
|
31
|
+
default: {
|
|
32
|
+
console.warn(`${shape.shape_type} is not supported`)
|
|
33
|
+
return new THREE.BufferGeometry()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Line } from "@react-three/drei"
|
|
2
|
-
import type { DHParameter } from "@wandelbots/wandelbots-api-client"
|
|
3
2
|
import type * as THREE from "three"
|
|
4
|
-
import { Matrix4
|
|
3
|
+
import { Matrix4 } from "three"
|
|
5
4
|
import type { LineGeometry } from "three/examples/jsm/lines/LineGeometry.js"
|
|
5
|
+
import { getDHLine, getDHLines } from "../utils/dhParameter"
|
|
6
6
|
import RobotAnimator from "./RobotAnimator"
|
|
7
7
|
import type { DHRobotProps } from "./SupportedRobot"
|
|
8
8
|
|
|
@@ -16,36 +16,11 @@ export function DHRobot({
|
|
|
16
16
|
}: DHRobotProps) {
|
|
17
17
|
// reused in every update
|
|
18
18
|
const accumulatedMatrix = new Matrix4()
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
jointRotation: number,
|
|
25
|
-
): {
|
|
26
|
-
a: THREE.Vector3
|
|
27
|
-
b: THREE.Vector3
|
|
28
|
-
} {
|
|
29
|
-
const position = new Vector3()
|
|
30
|
-
const quaternion = new Quaternion()
|
|
31
|
-
const scale = new Vector3()
|
|
32
|
-
accumulatedMatrix.decompose(position, quaternion, scale)
|
|
33
|
-
const prevPosition = position.clone() // Update the previous position
|
|
34
|
-
|
|
35
|
-
const matrix = new Matrix4()
|
|
36
|
-
.makeRotationY(
|
|
37
|
-
dhParameter.theta! +
|
|
38
|
-
jointRotation * (dhParameter.reverse_rotation_direction ? -1 : 1),
|
|
39
|
-
) // Rotate around Z
|
|
40
|
-
.multiply(new Matrix4().makeTranslation(0, dhParameter.d! / 1000, 0)) // Translate along Z
|
|
41
|
-
.multiply(new Matrix4().makeTranslation(dhParameter.a! / 1000, 0, 0)) // Translate along X
|
|
42
|
-
.multiply(new Matrix4().makeRotationX(dhParameter.alpha!)) // Rotate around X
|
|
43
|
-
|
|
44
|
-
// Accumulate transformations
|
|
45
|
-
accumulatedMatrix.multiply(matrix)
|
|
46
|
-
accumulatedMatrix.decompose(position, quaternion, scale)
|
|
47
|
-
return { a: prevPosition, b: position }
|
|
48
|
-
}
|
|
19
|
+
const dhLines = getDHLines(
|
|
20
|
+
accumulatedMatrix,
|
|
21
|
+
dhParameters,
|
|
22
|
+
rapidlyChangingMotionState.state.joint_position.joints,
|
|
23
|
+
)
|
|
49
24
|
|
|
50
25
|
function setJointLineRotation(
|
|
51
26
|
jointIndex: number,
|
|
@@ -57,16 +32,18 @@ export function DHRobot({
|
|
|
57
32
|
return
|
|
58
33
|
}
|
|
59
34
|
|
|
60
|
-
const
|
|
61
|
-
if (!
|
|
35
|
+
const dhParameter = dhParameters[jointIndex]
|
|
36
|
+
if (!dhParameter) {
|
|
62
37
|
return
|
|
63
38
|
}
|
|
64
39
|
|
|
65
|
-
const
|
|
40
|
+
const dhLine = getDHLine(accumulatedMatrix, dhParameter, jointValue)
|
|
66
41
|
const lineGeometry = line.geometry as LineGeometry
|
|
67
|
-
lineGeometry.setPositions(
|
|
42
|
+
lineGeometry.setPositions(
|
|
43
|
+
[dhLine.start.toArray(), dhLine.end.toArray()].flat(),
|
|
44
|
+
)
|
|
68
45
|
|
|
69
|
-
mesh.position.set(
|
|
46
|
+
mesh.position.set(dhLine.end.x, dhLine.end.y, dhLine.end.z)
|
|
70
47
|
}
|
|
71
48
|
|
|
72
49
|
function setRotation(joints: THREE.Object3D[], jointValues: number[]) {
|
|
@@ -93,22 +70,23 @@ export function DHRobot({
|
|
|
93
70
|
<sphereGeometry args={[0.01, 32, 32]} />
|
|
94
71
|
<meshStandardMaterial color={"black"} depthTest={true} />
|
|
95
72
|
</mesh>
|
|
73
|
+
|
|
96
74
|
{dhParameters!.map((param, index) => {
|
|
97
|
-
const { a, b } = getLinePoints(
|
|
98
|
-
param,
|
|
99
|
-
rapidlyChangingMotionState.state.joint_position.joints[index] ??
|
|
100
|
-
0,
|
|
101
|
-
)
|
|
102
75
|
const jointName = `dhrobot_J0${index}`
|
|
103
76
|
return (
|
|
104
77
|
<group name={jointName} key={jointName}>
|
|
105
78
|
<Line
|
|
106
79
|
name={CHILD_LINE}
|
|
107
|
-
points={[
|
|
80
|
+
points={[dhLines[index].start, dhLines[index].end]}
|
|
108
81
|
color={"white"}
|
|
109
82
|
lineWidth={5}
|
|
83
|
+
segments
|
|
110
84
|
/>
|
|
111
|
-
<mesh
|
|
85
|
+
<mesh
|
|
86
|
+
name={CHILD_MESH}
|
|
87
|
+
key={"mesh_" + index}
|
|
88
|
+
position={dhLines[index].end}
|
|
89
|
+
>
|
|
112
90
|
<sphereGeometry args={[0.01, 32, 32]} />
|
|
113
91
|
<meshStandardMaterial color={"black"} depthTest={true} />
|
|
114
92
|
</mesh>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useTheme } from "@mui/material"
|
|
2
|
+
import { observer } from "mobx-react-lite"
|
|
3
|
+
import { Trans, useTranslation } from "react-i18next"
|
|
4
|
+
import ControllerTypePhysicalIcon from "./icons/controller-type-physical.svg"
|
|
5
|
+
import ControllerTypeVirtualIcon from "./icons/controller-type-virtual.svg"
|
|
6
|
+
import { IndicatorWithExplanation } from "./IndicatorWithExplanation"
|
|
7
|
+
|
|
8
|
+
interface ControllerTypeIndicatorProps {
|
|
9
|
+
isVirtual: boolean
|
|
10
|
+
motionGroupId: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const ControllerTypeIndicator = observer(
|
|
14
|
+
({ isVirtual, motionGroupId }: ControllerTypeIndicatorProps) => {
|
|
15
|
+
const theme = useTheme()
|
|
16
|
+
const { t } = useTranslation()
|
|
17
|
+
|
|
18
|
+
if (isVirtual) {
|
|
19
|
+
return (
|
|
20
|
+
<IndicatorWithExplanation
|
|
21
|
+
id="motion-group-virtual"
|
|
22
|
+
icon={ControllerTypeVirtualIcon}
|
|
23
|
+
color={theme.palette.tertiary.main}
|
|
24
|
+
name={t("SafetyBar.ControllerType.Virtual.lb")}
|
|
25
|
+
explanation={
|
|
26
|
+
<Trans
|
|
27
|
+
i18nKey="SafetyBar.MotionGroup.Virtual.Explanation.lb"
|
|
28
|
+
values={{
|
|
29
|
+
motionGroupId,
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
Motion group <code>{motionGroupId}</code> refers to a virtual
|
|
33
|
+
robot with no physical counterpart. It can be freely manipulated
|
|
34
|
+
without special safety precautions.
|
|
35
|
+
</Trans>
|
|
36
|
+
}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<IndicatorWithExplanation
|
|
43
|
+
id="motion-group-physical"
|
|
44
|
+
icon={ControllerTypePhysicalIcon}
|
|
45
|
+
color={theme.palette.primary.main}
|
|
46
|
+
name={t("SafetyBar.ControllerType.Physical.lb")}
|
|
47
|
+
explanation={
|
|
48
|
+
<Trans
|
|
49
|
+
i18nKey="SafetyBar.MotionGroup.Physical.Explanation.lb"
|
|
50
|
+
values={{
|
|
51
|
+
motionGroupId,
|
|
52
|
+
}}
|
|
53
|
+
components={{ code: <code />, strong: <strong /> }}
|
|
54
|
+
/>
|
|
55
|
+
}
|
|
56
|
+
/>
|
|
57
|
+
)
|
|
58
|
+
},
|
|
59
|
+
)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Popover,
|
|
3
|
+
Stack,
|
|
4
|
+
SvgIcon,
|
|
5
|
+
Typography,
|
|
6
|
+
type TypographyProps,
|
|
7
|
+
} from "@mui/material"
|
|
8
|
+
import { observer, useLocalObservable } from "mobx-react-lite"
|
|
9
|
+
import type { ElementType, ReactNode } from "react"
|
|
10
|
+
|
|
11
|
+
export type IndicatorWithExplanationProps = {
|
|
12
|
+
id: string
|
|
13
|
+
icon: ElementType
|
|
14
|
+
color: TypographyProps["color"]
|
|
15
|
+
title?: ReactNode
|
|
16
|
+
name: ReactNode
|
|
17
|
+
explanation: ReactNode
|
|
18
|
+
literalValue?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const IndicatorWithExplanation = observer(
|
|
22
|
+
({
|
|
23
|
+
id,
|
|
24
|
+
icon,
|
|
25
|
+
color,
|
|
26
|
+
title,
|
|
27
|
+
name,
|
|
28
|
+
explanation,
|
|
29
|
+
literalValue,
|
|
30
|
+
}: IndicatorWithExplanationProps) => {
|
|
31
|
+
const state = useLocalObservable(() => ({
|
|
32
|
+
anchorEl: null as HTMLElement | null,
|
|
33
|
+
|
|
34
|
+
get isPopoverOpen() {
|
|
35
|
+
return !!state.anchorEl
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
openPopover(event: React.MouseEvent<HTMLElement>) {
|
|
39
|
+
state.anchorEl = event.currentTarget
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
closePopover() {
|
|
43
|
+
state.anchorEl = null
|
|
44
|
+
},
|
|
45
|
+
}))
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<Stack
|
|
50
|
+
aria-owns={state.isPopoverOpen ? id : undefined}
|
|
51
|
+
aria-haspopup="true"
|
|
52
|
+
onMouseEnter={state.openPopover}
|
|
53
|
+
onMouseLeave={state.closePopover}
|
|
54
|
+
sx={{
|
|
55
|
+
cursor: "pointer",
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
<SvgIcon
|
|
59
|
+
component={icon}
|
|
60
|
+
sx={{
|
|
61
|
+
color,
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
</Stack>
|
|
65
|
+
<Popover
|
|
66
|
+
id={id}
|
|
67
|
+
sx={{
|
|
68
|
+
pointerEvents: "none",
|
|
69
|
+
}}
|
|
70
|
+
open={state.isPopoverOpen}
|
|
71
|
+
anchorEl={state.anchorEl}
|
|
72
|
+
anchorOrigin={{
|
|
73
|
+
vertical: "bottom",
|
|
74
|
+
horizontal: "left",
|
|
75
|
+
}}
|
|
76
|
+
transformOrigin={{
|
|
77
|
+
vertical: "top",
|
|
78
|
+
horizontal: "left",
|
|
79
|
+
}}
|
|
80
|
+
onClose={state.closePopover}
|
|
81
|
+
disableRestoreFocus
|
|
82
|
+
>
|
|
83
|
+
<Stack
|
|
84
|
+
gap="1rem"
|
|
85
|
+
padding={2}
|
|
86
|
+
maxWidth="450px"
|
|
87
|
+
sx={{
|
|
88
|
+
wordWrap: "break-word",
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<div>
|
|
92
|
+
{title && (
|
|
93
|
+
<Typography component="span" fontSize="14px">
|
|
94
|
+
{`${title}: `}
|
|
95
|
+
</Typography>
|
|
96
|
+
)}
|
|
97
|
+
<Typography
|
|
98
|
+
component="span"
|
|
99
|
+
color={color}
|
|
100
|
+
fontWeight="bold"
|
|
101
|
+
fontSize="14px"
|
|
102
|
+
>
|
|
103
|
+
{name}
|
|
104
|
+
</Typography>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<Typography fontSize="14px">{explanation}</Typography>
|
|
108
|
+
|
|
109
|
+
{literalValue && (
|
|
110
|
+
<Typography fontSize="12px">{literalValue}</Typography>
|
|
111
|
+
)}
|
|
112
|
+
</Stack>
|
|
113
|
+
</Popover>
|
|
114
|
+
</>
|
|
115
|
+
)
|
|
116
|
+
},
|
|
117
|
+
)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useTheme } from "@mui/material"
|
|
2
|
+
import type { RobotControllerStateOperationModeEnum } from "@wandelbots/wandelbots-js"
|
|
3
|
+
import { observer } from "mobx-react-lite"
|
|
4
|
+
import { Trans, useTranslation } from "react-i18next"
|
|
5
|
+
import OperationModeAutomaticIcon from "./icons/operation-mode-automatic.svg"
|
|
6
|
+
import OperationModeErrorIcon from "./icons/operation-mode-error.svg"
|
|
7
|
+
import OperationModeManualIcon from "./icons/operation-mode-manual.svg"
|
|
8
|
+
import { IndicatorWithExplanation } from "./IndicatorWithExplanation"
|
|
9
|
+
|
|
10
|
+
interface OperationModeIndicatorProps {
|
|
11
|
+
operationMode: RobotControllerStateOperationModeEnum
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const OperationModeIndicator = observer(
|
|
15
|
+
({ operationMode }: OperationModeIndicatorProps) => {
|
|
16
|
+
const { t } = useTranslation()
|
|
17
|
+
const theme = useTheme()
|
|
18
|
+
|
|
19
|
+
switch (operationMode) {
|
|
20
|
+
case "OPERATION_MODE_AUTO":
|
|
21
|
+
return (
|
|
22
|
+
<IndicatorWithExplanation
|
|
23
|
+
id="operation-mode-auto"
|
|
24
|
+
icon={OperationModeAutomaticIcon}
|
|
25
|
+
title={t("SafetyBar.OperationMode.ti")}
|
|
26
|
+
name={t("SafetyBar.OperationMode.Automatic.ti")}
|
|
27
|
+
color={"rgba(255, 255, 255, 0.57)"}
|
|
28
|
+
explanation={
|
|
29
|
+
<Trans i18nKey="SafetyBar.OperationMode.Auto.Explanation.lb">
|
|
30
|
+
The robot controller is in automatic operation mode. Automated
|
|
31
|
+
movement without manual confirmation is possible in this mode.
|
|
32
|
+
</Trans>
|
|
33
|
+
}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
case "OPERATION_MODE_MANUAL":
|
|
37
|
+
case "OPERATION_MODE_MANUAL_T1":
|
|
38
|
+
case "OPERATION_MODE_MANUAL_T2": {
|
|
39
|
+
return (
|
|
40
|
+
<IndicatorWithExplanation
|
|
41
|
+
id="operation-mode-manual"
|
|
42
|
+
icon={OperationModeManualIcon}
|
|
43
|
+
color={theme.palette.warning.main}
|
|
44
|
+
title={t("SafetyBar.OperationMode.ti")}
|
|
45
|
+
name={t("SafetyBar.OperationMode.Manual.lb")}
|
|
46
|
+
explanation={
|
|
47
|
+
<Trans i18nKey="SafetyBar.OperationMode.Manual.Explanation.lb">
|
|
48
|
+
The robot controller is in manual operation mode. On a physical
|
|
49
|
+
robot, this generally indicates that an enabling switch must be
|
|
50
|
+
held for the robot to move successfully.
|
|
51
|
+
</Trans>
|
|
52
|
+
}
|
|
53
|
+
literalValue={operationMode}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
return (
|
|
59
|
+
<IndicatorWithExplanation
|
|
60
|
+
id="operation-mode-error"
|
|
61
|
+
icon={OperationModeErrorIcon}
|
|
62
|
+
color={theme.palette.warning.main}
|
|
63
|
+
title={t("SafetyBar.OperationMode.ti")}
|
|
64
|
+
name={t("SafetyBar.OperationMode.Error.lb")}
|
|
65
|
+
explanation={
|
|
66
|
+
<Trans i18nKey="SafetyBar.OperationMode.Error.Explanation.lb">
|
|
67
|
+
The robot controller has entered an unexpected operation mode.
|
|
68
|
+
Motion group movement may not be possible.
|
|
69
|
+
</Trans>
|
|
70
|
+
}
|
|
71
|
+
literalValue={operationMode}
|
|
72
|
+
/>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
)
|