@viamrobotics/motion-tools 1.23.1 → 1.25.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.
- package/README.md +4 -6
- package/dist/components/Entities/Capsule.svelte +137 -0
- package/dist/components/Entities/Capsule.svelte.d.ts +19 -0
- package/dist/components/Entities/Mesh.svelte +121 -68
- package/dist/components/PCD.svelte +16 -2
- package/dist/components/PCD.svelte.d.ts +5 -0
- package/dist/components/overlay/Details.svelte +1 -1
- package/dist/hooks/useArmKinematics.svelte.js +12 -8
- package/dist/hooks/usePose.svelte.js +8 -6
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## Documentation
|
|
6
6
|
|
|
7
|
-
📚 **[viamrobotics.github.io/visualization](https://viamrobotics.github.io/visualization/)** is
|
|
7
|
+
📚 **[viamrobotics.github.io/visualization](https://viamrobotics.github.io/visualization/)** is our guide to a few popular use cases. It covers:
|
|
8
8
|
|
|
9
9
|
- [Running locally](https://viamrobotics.github.io/visualization/guides/local-usage/) — set up the app and drive it from Go via `client/api`.
|
|
10
|
-
- [Embedding `<
|
|
11
|
-
- [Implementing WorldStateStoreService](https://viamrobotics.github.io/visualization/guides/worldstatestore/) — produce `Transform`s for a Viam
|
|
12
|
-
-
|
|
13
|
-
- [v1 → v2 migration guide](https://viamrobotics.github.io/visualization/migration/v1-to-v2/).
|
|
14
|
-
- A live [playground](https://viamrobotics.github.io/visualization/playground/) rendering a baked snapshot.
|
|
10
|
+
- [Embedding `<Visualizer />`](https://viamrobotics.github.io/visualization/guides/embedding/) — drop the visualizer into your own Svelte app.
|
|
11
|
+
- [Implementing WorldStateStoreService](https://viamrobotics.github.io/visualization/guides/worldstatestore/) — produce `Transform`s for a Viam WorldStateStoreService module with `draw`.
|
|
12
|
+
- A live [playground](https://viamrobotics.github.io/visualization/playground/snapshot) rendering a snapshot.
|
|
15
13
|
|
|
16
14
|
## Quick start
|
|
17
15
|
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
|
|
4
|
+
A compound capsule via a shared open-ended unit cylinder and two
|
|
5
|
+
hemispheres, each scaled per `r` and `l`, so dimension changes update
|
|
6
|
+
transforms only and cause no geometry rebuild.
|
|
7
|
+
|
|
8
|
+
Viam's capsule `l` is the *total* length, including the rounded caps, so the
|
|
9
|
+
midsection has length `l - 2r`.
|
|
10
|
+
-->
|
|
11
|
+
<script
|
|
12
|
+
module
|
|
13
|
+
lang="ts"
|
|
14
|
+
>
|
|
15
|
+
import { CylinderGeometry, EdgesGeometry, SphereGeometry } from 'three'
|
|
16
|
+
|
|
17
|
+
const unitCylinder = new CylinderGeometry(1, 1, 1, 16, 1, true)
|
|
18
|
+
unitCylinder.rotateX(Math.PI / 2)
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hemisphere with rounded part toward +Z and an open boundary on the XY plane.
|
|
22
|
+
* 6 height segments matches the existing sphere's density (`Mesh.svelte` uses `SphereGeometry(1, 16, 12)`).
|
|
23
|
+
*/
|
|
24
|
+
const unitHemisphere = new SphereGeometry(1, 16, 6, 0, Math.PI * 2, 0, Math.PI / 2)
|
|
25
|
+
unitHemisphere.rotateX(Math.PI / 2)
|
|
26
|
+
|
|
27
|
+
const unitCylinderEdges = new EdgesGeometry(unitCylinder, 0)
|
|
28
|
+
const unitHemisphereEdges = new EdgesGeometry(unitHemisphere, 0)
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<script lang="ts">
|
|
32
|
+
import type { ColorRepresentation } from 'three'
|
|
33
|
+
|
|
34
|
+
import { T, useThrelte } from '@threlte/core'
|
|
35
|
+
import { LineBasicMaterial, MeshToonMaterial } from 'three'
|
|
36
|
+
|
|
37
|
+
import { darkenColor } from '../../color'
|
|
38
|
+
|
|
39
|
+
interface Props {
|
|
40
|
+
r: number
|
|
41
|
+
l: number
|
|
42
|
+
color: ColorRepresentation
|
|
43
|
+
opacity?: number
|
|
44
|
+
depthTest?: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let { r, l, color, opacity = 1, depthTest = true }: Props = $props()
|
|
48
|
+
|
|
49
|
+
const { invalidate } = useThrelte()
|
|
50
|
+
const material = new MeshToonMaterial()
|
|
51
|
+
const lineMaterial = new LineBasicMaterial()
|
|
52
|
+
|
|
53
|
+
$effect(() => {
|
|
54
|
+
material.color.set(color)
|
|
55
|
+
lineMaterial.color.set(darkenColor(color, 10))
|
|
56
|
+
invalidate()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
$effect(() => {
|
|
60
|
+
const isTransparent = opacity < 1
|
|
61
|
+
material.opacity = opacity
|
|
62
|
+
material.depthWrite = opacity === 1
|
|
63
|
+
material.depthTest = depthTest
|
|
64
|
+
lineMaterial.depthTest = depthTest
|
|
65
|
+
if (material.transparent !== isTransparent) {
|
|
66
|
+
material.transparent = isTransparent
|
|
67
|
+
material.needsUpdate = true
|
|
68
|
+
}
|
|
69
|
+
invalidate()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const midsection = $derived(Math.max(0, l - 2 * r))
|
|
73
|
+
const halfMid = $derived(midsection / 2)
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
{#if midsection > 0}
|
|
77
|
+
<T.Mesh scale={[r, r, midsection]}>
|
|
78
|
+
<T
|
|
79
|
+
is={unitCylinder}
|
|
80
|
+
dispose={false}
|
|
81
|
+
/>
|
|
82
|
+
<T is={material} />
|
|
83
|
+
<T.LineSegments
|
|
84
|
+
raycast={() => null}
|
|
85
|
+
bvh={{ enabled: false }}
|
|
86
|
+
>
|
|
87
|
+
<T
|
|
88
|
+
is={unitCylinderEdges}
|
|
89
|
+
dispose={false}
|
|
90
|
+
/>
|
|
91
|
+
<T is={lineMaterial} />
|
|
92
|
+
</T.LineSegments>
|
|
93
|
+
</T.Mesh>
|
|
94
|
+
{/if}
|
|
95
|
+
|
|
96
|
+
<T.Mesh
|
|
97
|
+
position={[0, 0, halfMid]}
|
|
98
|
+
scale={r}
|
|
99
|
+
>
|
|
100
|
+
<T
|
|
101
|
+
is={unitHemisphere}
|
|
102
|
+
dispose={false}
|
|
103
|
+
/>
|
|
104
|
+
<T is={material} />
|
|
105
|
+
<T.LineSegments
|
|
106
|
+
raycast={() => null}
|
|
107
|
+
bvh={{ enabled: false }}
|
|
108
|
+
>
|
|
109
|
+
<T
|
|
110
|
+
is={unitHemisphereEdges}
|
|
111
|
+
dispose={false}
|
|
112
|
+
/>
|
|
113
|
+
<T is={lineMaterial} />
|
|
114
|
+
</T.LineSegments>
|
|
115
|
+
</T.Mesh>
|
|
116
|
+
|
|
117
|
+
<T.Mesh
|
|
118
|
+
position={[0, 0, -halfMid]}
|
|
119
|
+
rotation={[Math.PI, 0, 0]}
|
|
120
|
+
scale={[r, r, r]}
|
|
121
|
+
>
|
|
122
|
+
<T
|
|
123
|
+
is={unitHemisphere}
|
|
124
|
+
dispose={false}
|
|
125
|
+
/>
|
|
126
|
+
<T is={material} />
|
|
127
|
+
<T.LineSegments
|
|
128
|
+
raycast={() => null}
|
|
129
|
+
bvh={{ enabled: false }}
|
|
130
|
+
>
|
|
131
|
+
<T
|
|
132
|
+
is={unitHemisphereEdges}
|
|
133
|
+
dispose={false}
|
|
134
|
+
/>
|
|
135
|
+
<T is={lineMaterial} />
|
|
136
|
+
</T.LineSegments>
|
|
137
|
+
</T.Mesh>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ColorRepresentation } from 'three';
|
|
2
|
+
interface Props {
|
|
3
|
+
r: number;
|
|
4
|
+
l: number;
|
|
5
|
+
color: ColorRepresentation;
|
|
6
|
+
opacity?: number;
|
|
7
|
+
depthTest?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A compound capsule via a shared open-ended unit cylinder and two
|
|
11
|
+
* hemispheres, each scaled per `r` and `l`, so dimension changes update
|
|
12
|
+
* transforms only and cause no geometry rebuild.
|
|
13
|
+
*
|
|
14
|
+
* Viam's capsule `l` is the *total* length, including the rounded caps, so the
|
|
15
|
+
* midsection has length `l - 2r`.
|
|
16
|
+
*/
|
|
17
|
+
declare const Capsule: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type Capsule = ReturnType<typeof Capsule>;
|
|
19
|
+
export default Capsule;
|
|
@@ -1,20 +1,36 @@
|
|
|
1
|
+
<script
|
|
2
|
+
module
|
|
3
|
+
lang="ts"
|
|
4
|
+
>
|
|
5
|
+
import { BoxGeometry, EdgesGeometry, SphereGeometry } from 'three'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Shared unit geometries — every mesh references these and sets
|
|
9
|
+
* dimensions through `mesh.scale`, so resizing never rebuilds GPU buffers.
|
|
10
|
+
*/
|
|
11
|
+
const unitBox = new BoxGeometry(1, 1, 1)
|
|
12
|
+
const unitSphere = new SphereGeometry(1, 16, 12)
|
|
13
|
+
const unitBoxEdges = new EdgesGeometry(unitBox, 0)
|
|
14
|
+
const unitSphereEdges = new EdgesGeometry(unitSphere, 0)
|
|
15
|
+
</script>
|
|
16
|
+
|
|
1
17
|
<script lang="ts">
|
|
2
18
|
import type { Pose } from '@viamrobotics/sdk'
|
|
3
19
|
import type { Entity } from 'koota'
|
|
4
20
|
|
|
5
21
|
import { T, type Props as ThrelteProps, useThrelte } from '@threlte/core'
|
|
6
22
|
import { type Snippet } from 'svelte'
|
|
7
|
-
import {
|
|
23
|
+
import { Color, DoubleSide, FrontSide, Group, Material, Mesh } from 'three'
|
|
8
24
|
|
|
9
25
|
import { asColor } from '../../buffer'
|
|
10
26
|
import { colors, darkenColor } from '../../color'
|
|
11
27
|
import { traits, useTrait } from '../../ecs'
|
|
12
|
-
import { CapsuleGeometry } from '../../three/CapsuleGeometry'
|
|
13
28
|
import { poseToObject3d } from '../../transform'
|
|
14
29
|
|
|
15
30
|
import AxesHelper from '../AxesHelper.svelte'
|
|
31
|
+
import Capsule from './Capsule.svelte'
|
|
16
32
|
|
|
17
|
-
interface Props extends ThrelteProps<Mesh> {
|
|
33
|
+
interface Props extends Omit<ThrelteProps<Mesh>, 'ref'> {
|
|
18
34
|
entity: Entity
|
|
19
35
|
color?: string
|
|
20
36
|
center?: Pose
|
|
@@ -56,6 +72,8 @@
|
|
|
56
72
|
|
|
57
73
|
const currentOpacity = $derived(opacity.current ?? 0.7)
|
|
58
74
|
|
|
75
|
+
const isCapsule = $derived(capsule.current !== undefined)
|
|
76
|
+
|
|
59
77
|
let material = $state.raw<Material>(new Material())
|
|
60
78
|
$effect(() => {
|
|
61
79
|
const isTransparent = currentOpacity < 1
|
|
@@ -69,83 +87,118 @@
|
|
|
69
87
|
})
|
|
70
88
|
|
|
71
89
|
const mesh = new Mesh()
|
|
72
|
-
|
|
90
|
+
const group = new Group()
|
|
91
|
+
|
|
92
|
+
$effect(() => {
|
|
93
|
+
const target = isCapsule ? group : mesh
|
|
73
94
|
if (center) {
|
|
74
|
-
poseToObject3d(center,
|
|
95
|
+
poseToObject3d(center, target)
|
|
75
96
|
invalidate()
|
|
76
97
|
}
|
|
77
98
|
})
|
|
78
99
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
$effect(() => {
|
|
101
|
+
if (box.current) {
|
|
102
|
+
const { x, y, z } = box.current
|
|
103
|
+
mesh.scale.set(x * 0.001, y * 0.001, z * 0.001)
|
|
104
|
+
} else if (sphere.current) {
|
|
105
|
+
mesh.scale.setScalar((sphere.current.r ?? 0) * 0.001)
|
|
106
|
+
} else {
|
|
107
|
+
mesh.scale.set(1, 1, 1)
|
|
83
108
|
}
|
|
109
|
+
invalidate()
|
|
84
110
|
})
|
|
85
|
-
|
|
86
|
-
const oncreate = (bufferGeometry: BufferGeometry) => {
|
|
87
|
-
geo = bufferGeometry
|
|
88
|
-
}
|
|
89
111
|
</script>
|
|
90
112
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<T.SphereGeometry
|
|
107
|
-
args={[r * 0.001]}
|
|
108
|
-
{oncreate}
|
|
109
|
-
/>
|
|
110
|
-
{:else if capsule.current}
|
|
111
|
-
{@const { r, l } = capsule.current ?? { r: 0, l: 0 }}
|
|
112
|
-
<T
|
|
113
|
-
is={CapsuleGeometry}
|
|
114
|
-
args={[r * 0.001, l * 0.001]}
|
|
115
|
-
{oncreate}
|
|
113
|
+
{#if isCapsule}
|
|
114
|
+
{@const { r, l } = capsule.current ?? { r: 0, l: 0 }}
|
|
115
|
+
<T
|
|
116
|
+
is={group}
|
|
117
|
+
name={entity}
|
|
118
|
+
userData.name={name}
|
|
119
|
+
renderOrder={renderOrder.current}
|
|
120
|
+
{...rest}
|
|
121
|
+
>
|
|
122
|
+
<Capsule
|
|
123
|
+
r={r * 0.001}
|
|
124
|
+
l={l * 0.001}
|
|
125
|
+
{color}
|
|
126
|
+
opacity={currentOpacity}
|
|
127
|
+
depthTest={materialProps.current?.depthTest ?? true}
|
|
116
128
|
/>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
|
|
130
|
+
{@render children?.()}
|
|
131
|
+
</T>
|
|
132
|
+
{:else}
|
|
133
|
+
<T
|
|
134
|
+
is={mesh}
|
|
135
|
+
name={entity}
|
|
136
|
+
userData.name={name}
|
|
137
|
+
renderOrder={renderOrder.current}
|
|
138
|
+
{...rest}
|
|
139
|
+
>
|
|
140
|
+
{#if box.current}
|
|
141
|
+
<T
|
|
142
|
+
is={unitBox}
|
|
143
|
+
dispose={false}
|
|
144
|
+
/>
|
|
145
|
+
<T.LineSegments
|
|
146
|
+
raycast={() => null}
|
|
147
|
+
bvh={{ enabled: false }}
|
|
148
|
+
>
|
|
149
|
+
<T
|
|
150
|
+
is={unitBoxEdges}
|
|
151
|
+
dispose={false}
|
|
152
|
+
/>
|
|
153
|
+
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
154
|
+
</T.LineSegments>
|
|
155
|
+
{:else if sphere.current}
|
|
156
|
+
<T
|
|
157
|
+
is={unitSphere}
|
|
158
|
+
dispose={false}
|
|
159
|
+
/>
|
|
160
|
+
<T.LineSegments
|
|
161
|
+
raycast={() => null}
|
|
162
|
+
bvh={{ enabled: false }}
|
|
163
|
+
>
|
|
164
|
+
<T
|
|
165
|
+
is={unitSphereEdges}
|
|
166
|
+
dispose={false}
|
|
167
|
+
/>
|
|
168
|
+
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
169
|
+
</T.LineSegments>
|
|
170
|
+
{:else if bufferGeometry.current}
|
|
171
|
+
<T is={bufferGeometry.current}>
|
|
172
|
+
{#snippet children({ ref: geo })}
|
|
173
|
+
<!--
|
|
174
|
+
TODO(mp) currently some bufferGeometries are coming in empty,
|
|
175
|
+
this is a quick fix but this should be handled upstream
|
|
176
|
+
-->
|
|
177
|
+
{#if geo.getAttribute('position').array.length > 0}
|
|
178
|
+
<T.LineSegments
|
|
179
|
+
raycast={() => null}
|
|
180
|
+
bvh={{ enabled: false }}
|
|
181
|
+
>
|
|
182
|
+
<T.EdgesGeometry args={[geo, 0]} />
|
|
183
|
+
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
184
|
+
</T.LineSegments>
|
|
185
|
+
{/if}
|
|
186
|
+
{/snippet}
|
|
187
|
+
</T>
|
|
188
|
+
{/if}
|
|
189
|
+
|
|
190
|
+
<T.MeshToonMaterial
|
|
191
|
+
{color}
|
|
192
|
+
side={bufferGeometry.current ? DoubleSide : FrontSide}
|
|
193
|
+
depthTest={materialProps.current?.depthTest ?? true}
|
|
194
|
+
oncreate={(m) => {
|
|
195
|
+
material = m
|
|
196
|
+
}}
|
|
121
197
|
/>
|
|
122
|
-
{/if}
|
|
123
|
-
|
|
124
|
-
<T.MeshToonMaterial
|
|
125
|
-
{color}
|
|
126
|
-
side={bufferGeometry.current ? DoubleSide : FrontSide}
|
|
127
|
-
depthTest={materialProps.current?.depthTest ?? true}
|
|
128
|
-
oncreate={(m) => {
|
|
129
|
-
material = m
|
|
130
|
-
}}
|
|
131
|
-
/>
|
|
132
198
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-->
|
|
137
|
-
{#if geo && geo.getAttribute('position').array.length > 0}
|
|
138
|
-
<T.LineSegments
|
|
139
|
-
raycast={() => null}
|
|
140
|
-
bvh={{ enabled: false }}
|
|
141
|
-
>
|
|
142
|
-
<T.EdgesGeometry args={[geo, 0]} />
|
|
143
|
-
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
144
|
-
</T.LineSegments>
|
|
145
|
-
{/if}
|
|
146
|
-
|
|
147
|
-
{@render children?.()}
|
|
148
|
-
</T>
|
|
199
|
+
{@render children?.()}
|
|
200
|
+
</T>
|
|
201
|
+
{/if}
|
|
149
202
|
|
|
150
203
|
{#if showAxesHelper.current}
|
|
151
204
|
<AxesHelper
|
|
@@ -14,12 +14,21 @@
|
|
|
14
14
|
renderOrder?: number
|
|
15
15
|
depthTest?: boolean
|
|
16
16
|
depthWrite?: boolean
|
|
17
|
+
color?: { r: number; g: number; b: number }
|
|
17
18
|
interactionLayers?: InteractionLayerValue[]
|
|
18
19
|
oncreate?: (positions: Float32Array, colors: Uint8Array | undefined) => void
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
let {
|
|
22
|
-
|
|
22
|
+
let {
|
|
23
|
+
data,
|
|
24
|
+
name,
|
|
25
|
+
renderOrder,
|
|
26
|
+
depthTest,
|
|
27
|
+
depthWrite,
|
|
28
|
+
color,
|
|
29
|
+
interactionLayers,
|
|
30
|
+
oncreate,
|
|
31
|
+
}: Props = $props()
|
|
23
32
|
|
|
24
33
|
const world = useWorld()
|
|
25
34
|
|
|
@@ -41,11 +50,16 @@
|
|
|
41
50
|
if (renderOrder) {
|
|
42
51
|
entityTraits.push(traits.RenderOrder(renderOrder))
|
|
43
52
|
}
|
|
53
|
+
|
|
44
54
|
if (depthTest !== undefined || depthWrite !== undefined) {
|
|
45
55
|
entityTraits.push(
|
|
46
56
|
traits.Material({ depthTest: depthTest ?? true, depthWrite: depthWrite ?? true })
|
|
47
57
|
)
|
|
48
58
|
}
|
|
59
|
+
if (color !== undefined) {
|
|
60
|
+
geometry.deleteAttribute('color')
|
|
61
|
+
entityTraits.push(traits.Color({ r: color.r, g: color.g, b: color.b }))
|
|
62
|
+
}
|
|
49
63
|
if (interactionLayers?.includes('selectTool')) {
|
|
50
64
|
entityTraits.push(traits.SelectToolInteractionLayer)
|
|
51
65
|
}
|
|
@@ -5,6 +5,11 @@ interface Props {
|
|
|
5
5
|
renderOrder?: number;
|
|
6
6
|
depthTest?: boolean;
|
|
7
7
|
depthWrite?: boolean;
|
|
8
|
+
color?: {
|
|
9
|
+
r: number;
|
|
10
|
+
g: number;
|
|
11
|
+
b: number;
|
|
12
|
+
};
|
|
8
13
|
interactionLayers?: InteractionLayerValue[];
|
|
9
14
|
oncreate?: (positions: Float32Array, colors: Uint8Array | undefined) => void;
|
|
10
15
|
}
|
|
@@ -338,7 +338,7 @@
|
|
|
338
338
|
{#if entity}
|
|
339
339
|
<div
|
|
340
340
|
id="details-panel"
|
|
341
|
-
class="border-medium bg-extralight absolute top-0 right-0 z-4 m-2 w-70 border p-2 text-xs dark:text-
|
|
341
|
+
class="border-medium bg-extralight absolute top-0 right-0 z-4 m-2 w-70 border p-2 text-xs dark:text-white"
|
|
342
342
|
use:draggable={{
|
|
343
343
|
bounds: 'body',
|
|
344
344
|
handle: dragElement,
|
|
@@ -9,14 +9,18 @@ export const provideArmKinematics = (partID) => {
|
|
|
9
9
|
const names = $derived(arms.current.map((arm) => arm.name));
|
|
10
10
|
const clients = $derived(arms.current.map((arm) => createResourceClient(ArmClient, partID, () => arm.name)));
|
|
11
11
|
const kinematicsQueries = $derived(clients.map((client) => [client.current?.name, createResourceQuery(client, 'getKinematics', () => options)]));
|
|
12
|
-
const kinematics = $derived(Object.fromEntries(kinematicsQueries.map(([name, query]) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
const kinematics = $derived(Object.fromEntries(kinematicsQueries.map(([name, query]) => {
|
|
13
|
+
const data = query.data;
|
|
14
|
+
const joints = data && ('joints' in data ? data.joints : data.kinematicsData.joints);
|
|
15
|
+
return [
|
|
16
|
+
name,
|
|
17
|
+
joints?.map((j) => ({
|
|
18
|
+
id: j.id,
|
|
19
|
+
min: j.min,
|
|
20
|
+
max: j.max,
|
|
21
|
+
})),
|
|
22
|
+
];
|
|
23
|
+
})));
|
|
20
24
|
setContext(key, {
|
|
21
25
|
get names() {
|
|
22
26
|
return names;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createRobotQuery, useRobotClient } from '@viamrobotics/svelte-sdk';
|
|
1
|
+
import { commonApi, MachineConnectionEvent, Pose } from '@viamrobotics/sdk';
|
|
2
|
+
import { createRobotQuery, useConnectionStatus, useRobotClient } from '@viamrobotics/svelte-sdk';
|
|
4
3
|
import { untrack } from 'svelte';
|
|
5
4
|
import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
|
|
6
5
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
@@ -12,10 +11,11 @@ import { useResourceByName } from './useResourceByName.svelte';
|
|
|
12
11
|
import { RefreshRates, useSettings } from './useSettings.svelte';
|
|
13
12
|
const originFrameComponentTypes = new Set(['arm', 'gantry', 'gripper', 'base']);
|
|
14
13
|
export const usePose = (name, parent) => {
|
|
14
|
+
const partID = usePartID();
|
|
15
|
+
const connectionStatus = useConnectionStatus(() => partID.current);
|
|
15
16
|
const environment = useEnvironment();
|
|
16
17
|
const logs = useLogs();
|
|
17
18
|
const settings = useSettings();
|
|
18
|
-
const partID = usePartID();
|
|
19
19
|
const robotClient = useRobotClient(() => partID.current);
|
|
20
20
|
const currentName = $derived(name());
|
|
21
21
|
const currentParent = $derived(parent());
|
|
@@ -49,8 +49,10 @@ export const usePose = (name, parent) => {
|
|
|
49
49
|
logs.add(`Error fetching pose for ${currentName}: ${query.error.message}`, 'error');
|
|
50
50
|
}
|
|
51
51
|
});
|
|
52
|
-
|
|
53
|
-
if (environment.current.viewerMode === 'monitor'
|
|
52
|
+
$effect(() => {
|
|
53
|
+
if (environment.current.viewerMode === 'monitor' &&
|
|
54
|
+
frames.current &&
|
|
55
|
+
connectionStatus.current === MachineConnectionEvent.CONNECTED) {
|
|
54
56
|
untrack(() => query.refetch());
|
|
55
57
|
}
|
|
56
58
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viamrobotics/motion-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Motion visualization with Viam",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@dimforge/rapier3d-compat": "0.18.2",
|
|
13
13
|
"@eslint/compat": "2.0.2",
|
|
14
14
|
"@eslint/js": "10.0.1",
|
|
15
|
-
"@playwright/test": "1.55.
|
|
15
|
+
"@playwright/test": "1.55.1",
|
|
16
16
|
"@sentry/sveltekit": "10.10.0",
|
|
17
17
|
"@skeletonlabs/skeleton": "3.2.0",
|
|
18
18
|
"@skeletonlabs/skeleton-svelte": "1.5.1",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
|
38
38
|
"@typescript-eslint/parser": "8.56.1",
|
|
39
39
|
"@viamrobotics/prime-core": "0.1.5",
|
|
40
|
-
"@viamrobotics/sdk": "0.
|
|
41
|
-
"@viamrobotics/svelte-sdk": "1.
|
|
40
|
+
"@viamrobotics/sdk": "0.69.0",
|
|
41
|
+
"@viamrobotics/svelte-sdk": "1.2.2",
|
|
42
42
|
"@vitest/browser": "3.2.4",
|
|
43
43
|
"@vitest/coverage-v8": "^3.2.4",
|
|
44
44
|
"@zag-js/collapsible": "1.22.1",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"svelte-virtuallists": "1.4.2",
|
|
71
71
|
"tailwindcss": "4.1.13",
|
|
72
72
|
"three": "0.183.2",
|
|
73
|
-
"threlte-uikit": "
|
|
73
|
+
"threlte-uikit": "^2.0.0",
|
|
74
74
|
"tsx": "4.20.5",
|
|
75
75
|
"type-fest": "^5.0.1",
|
|
76
76
|
"typescript": "5.9.2",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"vite": "7.3.2",
|
|
79
79
|
"vite-plugin-devtools-json": "1.0.0",
|
|
80
80
|
"vite-plugin-glsl": "^1.5.5",
|
|
81
|
-
"vite-plugin-mkcert": "1.17.
|
|
81
|
+
"vite-plugin-mkcert": "1.17.9",
|
|
82
82
|
"vitest": "3.2.4"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|