@viamrobotics/motion-tools 1.3.2 → 1.3.4
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/{Arrows.svelte → Arrows/ArrowGroups.svelte} +8 -26
- package/dist/components/Arrows/ArrowGroups.svelte.d.ts +3 -0
- package/dist/components/Arrows/Arrows.svelte +38 -0
- package/dist/components/Arrows/Arrows.svelte.d.ts +9 -0
- package/dist/components/Details.svelte +39 -7
- package/dist/components/Geometry2.svelte +1 -0
- package/dist/components/KeyboardControls.svelte +28 -1
- package/dist/components/Scene.svelte +7 -5
- package/dist/components/Tree/Settings.svelte +3 -3
- package/dist/components/Tree/Tree.svelte +10 -7
- package/dist/hooks/useMachineSettings.svelte.d.ts +1 -1
- package/dist/hooks/useMachineSettings.svelte.js +9 -6
- package/dist/hooks/useObjectEvents.svelte.js +35 -27
- package/dist/hooks/usePointcloudObjects.svelte.js +10 -5
- package/dist/hooks/usePose.svelte.js +3 -2
- package/dist/loaders/pcd/worker.js +6 -1
- package/package.json +1 -1
- package/dist/components/Arrows.svelte.d.ts +0 -3
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { InstancedArrows } from '../three/InstancedArrows/InstancedArrows'
|
|
5
|
-
import { traits, useWorld } from '../ecs'
|
|
2
|
+
import { InstancedArrows } from '../../three/InstancedArrows/InstancedArrows'
|
|
3
|
+
import { traits, useWorld } from '../../ecs'
|
|
6
4
|
import type { Entity } from 'koota'
|
|
7
|
-
import { STRIDE } from '
|
|
8
|
-
import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
|
|
5
|
+
import { STRIDE } from '../../buffer'
|
|
9
6
|
import { SvelteMap } from 'svelte/reactivity'
|
|
10
7
|
import { Color } from 'three'
|
|
11
|
-
import
|
|
8
|
+
import Arrows from './Arrows.svelte'
|
|
12
9
|
|
|
13
10
|
const world = useWorld()
|
|
14
11
|
|
|
@@ -59,23 +56,8 @@
|
|
|
59
56
|
</script>
|
|
60
57
|
|
|
61
58
|
{#each map as [entity, arrows] (entity)}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
name={entity}
|
|
67
|
-
>
|
|
68
|
-
<T
|
|
69
|
-
is={arrows.headMesh}
|
|
70
|
-
bvh={{ enabled: false }}
|
|
71
|
-
raycast={() => null}
|
|
72
|
-
/>
|
|
73
|
-
<T
|
|
74
|
-
is={arrows.shaftMesh}
|
|
75
|
-
bvh={{ enabled: false }}
|
|
76
|
-
raycast={meshBoundsRaycast}
|
|
77
|
-
{...events}
|
|
78
|
-
/>
|
|
79
|
-
</T>
|
|
80
|
-
</Portal>
|
|
59
|
+
<Arrows
|
|
60
|
+
{entity}
|
|
61
|
+
{arrows}
|
|
62
|
+
/>
|
|
81
63
|
{/each}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { T } from '@threlte/core'
|
|
3
|
+
import { Portal } from '@threlte/extras'
|
|
4
|
+
import type { Entity } from 'koota'
|
|
5
|
+
import { traits } from '../../ecs'
|
|
6
|
+
import { useObjectEvents } from '../../hooks/useObjectEvents.svelte'
|
|
7
|
+
import type { InstancedArrows } from '../../three/InstancedArrows/InstancedArrows'
|
|
8
|
+
import { meshBoundsRaycast } from '../../three/InstancedArrows/raycast'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
entity: Entity
|
|
12
|
+
arrows: InstancedArrows
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { entity, arrows }: Props = $props()
|
|
16
|
+
|
|
17
|
+
const events = useObjectEvents(() => entity)
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Portal id={entity.get(traits.Parent)}>
|
|
21
|
+
<T
|
|
22
|
+
is={arrows}
|
|
23
|
+
name={entity}
|
|
24
|
+
>
|
|
25
|
+
<T
|
|
26
|
+
is={arrows.headMesh}
|
|
27
|
+
bvh={{ enabled: false }}
|
|
28
|
+
raycast={() => null}
|
|
29
|
+
visible={events.visible}
|
|
30
|
+
/>
|
|
31
|
+
<T
|
|
32
|
+
is={arrows.shaftMesh}
|
|
33
|
+
bvh={{ enabled: false }}
|
|
34
|
+
raycast={meshBoundsRaycast}
|
|
35
|
+
{...events}
|
|
36
|
+
/>
|
|
37
|
+
</T>
|
|
38
|
+
</Portal>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Entity } from 'koota';
|
|
2
|
+
import type { InstancedArrows } from '../../three/InstancedArrows/InstancedArrows';
|
|
3
|
+
interface Props {
|
|
4
|
+
entity: Entity;
|
|
5
|
+
arrows: InstancedArrows;
|
|
6
|
+
}
|
|
7
|
+
declare const Arrows: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Arrows = ReturnType<typeof Arrows>;
|
|
9
|
+
export default Arrows;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { draggable } from '@neodrag/svelte'
|
|
15
15
|
import { Check, Copy } from 'lucide-svelte'
|
|
16
16
|
import { useTask } from '@threlte/core'
|
|
17
|
-
import { Button, Icon, Select, Input } from '@viamrobotics/prime-core'
|
|
17
|
+
import { Button, Icon, Select, Input, Tooltip } from '@viamrobotics/prime-core'
|
|
18
18
|
import {
|
|
19
19
|
useSelectedEntity,
|
|
20
20
|
useFocusedEntity,
|
|
@@ -28,14 +28,13 @@
|
|
|
28
28
|
import { traits, useTrait } from '../ecs'
|
|
29
29
|
import { useResourceByName } from '../hooks/useResourceByName.svelte'
|
|
30
30
|
import { PersistedState } from 'runed'
|
|
31
|
+
import { useCameraControls } from '../hooks/useControls.svelte'
|
|
31
32
|
|
|
32
33
|
const { ...rest } = $props()
|
|
33
34
|
|
|
34
|
-
const dragPosition = new PersistedState<Vector2Like
|
|
35
|
-
'details-drag-position',
|
|
36
|
-
undefined
|
|
37
|
-
)
|
|
35
|
+
const dragPosition = new PersistedState<Vector2Like>('details-drag-position', { x: 0, y: 0 })
|
|
38
36
|
|
|
37
|
+
const controls = useCameraControls()
|
|
39
38
|
const resourceByName = useResourceByName()
|
|
40
39
|
const frames = useFrames()
|
|
41
40
|
const partConfig = usePartConfig()
|
|
@@ -247,13 +246,46 @@
|
|
|
247
246
|
{...rest}
|
|
248
247
|
>
|
|
249
248
|
<div class="flex items-center justify-between gap-2 pb-2">
|
|
250
|
-
<div class="flex items-center gap-1">
|
|
249
|
+
<div class="flex w-[90%] items-center gap-1">
|
|
251
250
|
<button bind:this={dragElement}>
|
|
252
251
|
<Icon name="drag" />
|
|
253
252
|
</button>
|
|
254
|
-
<strong>{name.current}</strong>
|
|
253
|
+
<strong class="overflow-hidden text-nowrap text-ellipsis">{name.current}</strong>
|
|
255
254
|
<span class="text-subtle-2">{resourceName?.subtype}</span>
|
|
256
255
|
</div>
|
|
256
|
+
|
|
257
|
+
{#if object3d}
|
|
258
|
+
<Tooltip
|
|
259
|
+
let:tooltipID
|
|
260
|
+
location="bottom"
|
|
261
|
+
>
|
|
262
|
+
<button
|
|
263
|
+
class="text-subtle-2"
|
|
264
|
+
aria-describedby={tooltipID}
|
|
265
|
+
onclick={() => {
|
|
266
|
+
const padding = 0.4
|
|
267
|
+
|
|
268
|
+
if (!controls.current) return
|
|
269
|
+
|
|
270
|
+
const { azimuthAngle, polarAngle } = controls.current
|
|
271
|
+
|
|
272
|
+
controls.current.fitToBox(object3d, true, {
|
|
273
|
+
paddingTop: padding,
|
|
274
|
+
paddingBottom: padding,
|
|
275
|
+
paddingLeft: padding,
|
|
276
|
+
paddingRight: padding,
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
// Preserve previous rotation
|
|
280
|
+
controls.current?.rotateAzimuthTo(azimuthAngle, true)
|
|
281
|
+
controls.current?.rotatePolarTo(polarAngle, true)
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
<Icon name="image-filter-center-focus" />
|
|
285
|
+
</button>
|
|
286
|
+
<p slot="description">Zoom to object</p>
|
|
287
|
+
</Tooltip>
|
|
288
|
+
{/if}
|
|
257
289
|
</div>
|
|
258
290
|
|
|
259
291
|
<div class="border-medium -mx-2 w-[100%+0.5rem] border-b"></div>
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
import { useTask } from '@threlte/core'
|
|
4
4
|
import type { CameraControlsRef } from '@threlte/extras'
|
|
5
5
|
import { PressedKeys } from 'runed'
|
|
6
|
-
import { useFocusedEntity } from '../hooks/useSelection.svelte'
|
|
6
|
+
import { useFocusedEntity, useSelectedEntity } from '../hooks/useSelection.svelte'
|
|
7
7
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
8
|
+
import { useVisibility } from '../hooks/useVisibility.svelte'
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
10
11
|
cameraControls: CameraControlsRef
|
|
@@ -13,7 +14,12 @@
|
|
|
13
14
|
let { cameraControls }: Props = $props()
|
|
14
15
|
|
|
15
16
|
const focusedEntity = useFocusedEntity()
|
|
17
|
+
const selectedEntity = useSelectedEntity()
|
|
18
|
+
|
|
19
|
+
const entity = $derived(focusedEntity.current ?? selectedEntity.current)
|
|
20
|
+
|
|
16
21
|
const settings = useSettings()
|
|
22
|
+
const visibility = useVisibility()
|
|
17
23
|
|
|
18
24
|
const keys = new PressedKeys()
|
|
19
25
|
const meta = $derived(keys.has('meta'))
|
|
@@ -28,6 +34,7 @@
|
|
|
28
34
|
const down = $derived(keys.has('arrowdown'))
|
|
29
35
|
const right = $derived(keys.has('arrowright'))
|
|
30
36
|
const any = $derived(w || s || a || d || r || f || up || left || down || right)
|
|
37
|
+
|
|
31
38
|
const { start, stop } = useTask(
|
|
32
39
|
(delta) => {
|
|
33
40
|
const dt = delta * 1000
|
|
@@ -117,4 +124,24 @@
|
|
|
117
124
|
keys.onKeys('x', () => {
|
|
118
125
|
settings.current.enableXR = !settings.current.enableXR
|
|
119
126
|
})
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Handler for any keybindings that need to access the event object
|
|
130
|
+
*/
|
|
131
|
+
const onkeydown = (event: KeyboardEvent) => {
|
|
132
|
+
const key = event.key.toLowerCase()
|
|
133
|
+
|
|
134
|
+
if (key === 'h') {
|
|
135
|
+
if (!entity) return
|
|
136
|
+
|
|
137
|
+
event.stopImmediatePropagation()
|
|
138
|
+
|
|
139
|
+
const visible = visibility.get(entity) ?? true
|
|
140
|
+
|
|
141
|
+
visibility.set(entity, !visible)
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
}
|
|
120
145
|
</script>
|
|
146
|
+
|
|
147
|
+
<svelte:window {onkeydown} />
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import MeasureTool from './MeasureTool.svelte'
|
|
18
18
|
import PointerMissBox from './PointerMissBox.svelte'
|
|
19
19
|
import BatchedArrows from './BatchedArrows.svelte'
|
|
20
|
-
import Arrows from './Arrows.svelte'
|
|
20
|
+
import Arrows from './Arrows/ArrowGroups.svelte'
|
|
21
21
|
|
|
22
22
|
interface Props {
|
|
23
23
|
children?: Snippet
|
|
@@ -30,17 +30,19 @@
|
|
|
30
30
|
const origin = useOrigin()
|
|
31
31
|
|
|
32
32
|
const { raycaster, enabled } = interactivity({
|
|
33
|
-
filter: (
|
|
34
|
-
const
|
|
35
|
-
return
|
|
33
|
+
filter: (intersections) => {
|
|
34
|
+
const match = intersections.find((intersection) => {
|
|
35
|
+
return intersection.object.visible === undefined || intersection.object.visible === true
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
return
|
|
38
|
+
return match ? [match] : []
|
|
39
39
|
},
|
|
40
40
|
})
|
|
41
|
+
|
|
41
42
|
$effect(() => {
|
|
42
43
|
enabled.set(!settings.current.enableMeasure)
|
|
43
44
|
})
|
|
45
|
+
|
|
44
46
|
raycaster.firstHitOnly = true
|
|
45
47
|
raycaster.params.Points.threshold = 0.005
|
|
46
48
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
const cameras = useResourceNames(() => partID.current, 'camera')
|
|
19
19
|
const visionServices = useResourceNames(() => partID.current, 'vision')
|
|
20
20
|
const settings = useSettings()
|
|
21
|
-
const { disabledCameras,
|
|
21
|
+
const { disabledCameras, disabledVisionServices } = useMachineSettings()
|
|
22
22
|
const geometries = useGeometries()
|
|
23
23
|
const pointclouds = usePointClouds()
|
|
24
24
|
const { refetchPoses } = useRefetchPoses()
|
|
@@ -81,9 +81,9 @@
|
|
|
81
81
|
<div class="flex items-center justify-between gap-4 py-2">
|
|
82
82
|
{visionService.name}
|
|
83
83
|
<Switch
|
|
84
|
-
on={
|
|
84
|
+
on={disabledVisionServices.get(visionService.name) !== true}
|
|
85
85
|
on:change={(event) => {
|
|
86
|
-
|
|
86
|
+
disabledVisionServices.set(visionService.name, !event.detail)
|
|
87
87
|
}}
|
|
88
88
|
/>
|
|
89
89
|
</div>
|
|
@@ -92,11 +92,14 @@
|
|
|
92
92
|
{@const { children = [] } = node}
|
|
93
93
|
<div
|
|
94
94
|
{...api.getBranchProps(nodeProps)}
|
|
95
|
-
class={
|
|
96
|
-
'
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
class={[
|
|
96
|
+
'w-full',
|
|
97
|
+
{
|
|
98
|
+
'text-disabled': !isVisible,
|
|
99
|
+
'bg-medium': selected,
|
|
100
|
+
sticky: true,
|
|
101
|
+
},
|
|
102
|
+
]}
|
|
100
103
|
>
|
|
101
104
|
<div {...api.getBranchControlProps(nodeProps)}>
|
|
102
105
|
<span
|
|
@@ -106,7 +109,7 @@
|
|
|
106
109
|
<ChevronRight size={14} />
|
|
107
110
|
</span>
|
|
108
111
|
<span
|
|
109
|
-
class="flex items-center"
|
|
112
|
+
class="flex items-center overflow-hidden text-ellipsis"
|
|
110
113
|
{...api.getBranchTextProps(nodeProps)}
|
|
111
114
|
>
|
|
112
115
|
{node.entity.get(traits.Name)}
|
|
@@ -151,7 +154,7 @@
|
|
|
151
154
|
class={{ 'flex justify-between': true, 'text-disabled': !isVisible, 'bg-medium': selected }}
|
|
152
155
|
{...api.getItemProps(nodeProps)}
|
|
153
156
|
>
|
|
154
|
-
<span class="flex items-center gap-1.5">
|
|
157
|
+
<span class="flex items-center gap-1.5 overflow-hidden text-nowrap text-ellipsis">
|
|
155
158
|
{node.entity.get(traits.Name)}
|
|
156
159
|
</span>
|
|
157
160
|
|
|
@@ -6,7 +6,7 @@ export declare const RefreshRates: {
|
|
|
6
6
|
type Context = {
|
|
7
7
|
refreshRates: SvelteMap<string, number>;
|
|
8
8
|
disabledCameras: SvelteMap<string, boolean>;
|
|
9
|
-
|
|
9
|
+
disabledVisionServices: SvelteMap<string, boolean>;
|
|
10
10
|
};
|
|
11
11
|
export declare const provideMachineSettings: () => void;
|
|
12
12
|
export declare const useMachineSettings: () => Context;
|
|
@@ -4,7 +4,7 @@ import { SvelteMap } from 'svelte/reactivity';
|
|
|
4
4
|
const key = Symbol('polling-rate-context');
|
|
5
5
|
const refreshRatesKey = 'polling-rate';
|
|
6
6
|
const disabledCamerasKey = 'disabled-cameras';
|
|
7
|
-
const
|
|
7
|
+
const disabledVisionServicesKey = 'disabled-vision-services-object-pointcloud';
|
|
8
8
|
export const RefreshRates = {
|
|
9
9
|
poses: 'poses',
|
|
10
10
|
pointclouds: 'pointclouds',
|
|
@@ -22,15 +22,15 @@ export const provideMachineSettings = () => {
|
|
|
22
22
|
[RefreshRates.pointclouds, -1],
|
|
23
23
|
]);
|
|
24
24
|
const disabledCameras = new SvelteMap();
|
|
25
|
-
const
|
|
25
|
+
const disabledVisionServices = new SvelteMap();
|
|
26
26
|
get(refreshRatesKey).then((entries) => {
|
|
27
27
|
setFromEntries(refreshRates, entries);
|
|
28
28
|
});
|
|
29
29
|
get(disabledCamerasKey).then((entries) => {
|
|
30
30
|
setFromEntries(disabledCameras, entries);
|
|
31
31
|
});
|
|
32
|
-
get(
|
|
33
|
-
setFromEntries(
|
|
32
|
+
get(disabledVisionServicesKey).then((entries) => {
|
|
33
|
+
setFromEntries(disabledVisionServices, entries);
|
|
34
34
|
});
|
|
35
35
|
$effect(() => {
|
|
36
36
|
set(refreshRatesKey, [...refreshRates.entries()]);
|
|
@@ -38,6 +38,9 @@ export const provideMachineSettings = () => {
|
|
|
38
38
|
$effect(() => {
|
|
39
39
|
set(disabledCamerasKey, [...disabledCameras.entries()]);
|
|
40
40
|
});
|
|
41
|
+
$effect(() => {
|
|
42
|
+
set(disabledVisionServicesKey, [...disabledVisionServices.entries()]);
|
|
43
|
+
});
|
|
41
44
|
setContext(key, {
|
|
42
45
|
get refreshRates() {
|
|
43
46
|
return refreshRates;
|
|
@@ -45,8 +48,8 @@ export const provideMachineSettings = () => {
|
|
|
45
48
|
get disabledCameras() {
|
|
46
49
|
return disabledCameras;
|
|
47
50
|
},
|
|
48
|
-
get
|
|
49
|
-
return
|
|
51
|
+
get disabledVisionServices() {
|
|
52
|
+
return disabledVisionServices;
|
|
50
53
|
},
|
|
51
54
|
});
|
|
52
55
|
};
|
|
@@ -3,39 +3,47 @@ import { useFocusedEntity, useSelectedEntity } from './useSelection.svelte';
|
|
|
3
3
|
import { useVisibility } from './useVisibility.svelte';
|
|
4
4
|
import { Vector2 } from 'three';
|
|
5
5
|
export const useObjectEvents = (entity) => {
|
|
6
|
+
const down = new Vector2();
|
|
6
7
|
const selectedEntity = useSelectedEntity();
|
|
7
8
|
const focusedEntity = useFocusedEntity();
|
|
8
9
|
const visibility = useVisibility();
|
|
9
|
-
const down = new Vector2();
|
|
10
|
-
const currentEntity = $derived(entity());
|
|
11
10
|
const cursor = useCursor();
|
|
11
|
+
const currentEntity = $derived(entity());
|
|
12
|
+
const visible = $derived(currentEntity ? (visibility.get(currentEntity) ?? true) : true);
|
|
13
|
+
const onpointerenter = (event) => {
|
|
14
|
+
event.stopPropagation();
|
|
15
|
+
cursor.onPointerEnter();
|
|
16
|
+
};
|
|
17
|
+
const onpointerleave = (event) => {
|
|
18
|
+
event.stopPropagation();
|
|
19
|
+
cursor.onPointerLeave();
|
|
20
|
+
};
|
|
21
|
+
const ondblclick = (event) => {
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
focusedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
24
|
+
};
|
|
25
|
+
const onpointerdown = (event) => {
|
|
26
|
+
down.copy(event.pointer);
|
|
27
|
+
};
|
|
28
|
+
const onclick = (event) => {
|
|
29
|
+
event.stopPropagation();
|
|
30
|
+
if (down.distanceToSquared(event.pointer) < 0.1) {
|
|
31
|
+
selectedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
$effect(() => {
|
|
35
|
+
if (!visible) {
|
|
36
|
+
cursor.onPointerLeave();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
12
39
|
return {
|
|
13
40
|
get visible() {
|
|
14
|
-
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
return visibility.get(currentEntity) ?? true;
|
|
18
|
-
},
|
|
19
|
-
onpointerenter: (event) => {
|
|
20
|
-
event.stopPropagation();
|
|
21
|
-
cursor.onPointerEnter();
|
|
22
|
-
},
|
|
23
|
-
onpointerleave: (event) => {
|
|
24
|
-
event.stopPropagation();
|
|
25
|
-
cursor.onPointerLeave();
|
|
26
|
-
},
|
|
27
|
-
ondblclick: (event) => {
|
|
28
|
-
event.stopPropagation();
|
|
29
|
-
focusedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
30
|
-
},
|
|
31
|
-
onpointerdown: (event) => {
|
|
32
|
-
down.copy(event.pointer);
|
|
33
|
-
},
|
|
34
|
-
onclick: (event) => {
|
|
35
|
-
event.stopPropagation();
|
|
36
|
-
if (down.distanceToSquared(event.pointer) < 0.1) {
|
|
37
|
-
selectedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
38
|
-
}
|
|
41
|
+
return visible;
|
|
39
42
|
},
|
|
43
|
+
onpointerenter,
|
|
44
|
+
onpointerleave,
|
|
45
|
+
ondblclick,
|
|
46
|
+
onpointerdown,
|
|
47
|
+
onclick,
|
|
40
48
|
};
|
|
41
49
|
};
|
|
@@ -13,7 +13,7 @@ const key = Symbol('pointcloud-object-context');
|
|
|
13
13
|
export const providePointcloudObjects = (partID) => {
|
|
14
14
|
const world = useWorld();
|
|
15
15
|
const environment = useEnvironment();
|
|
16
|
-
const { refreshRates,
|
|
16
|
+
const { refreshRates, disabledVisionServices } = useMachineSettings();
|
|
17
17
|
const services = useResourceNames(partID, 'vision');
|
|
18
18
|
const clients = $derived(services.current.map((service) => createResourceClient(VisionClient, partID, () => service.name)));
|
|
19
19
|
const propQueries = $derived(clients.map((client) => [
|
|
@@ -31,7 +31,8 @@ export const providePointcloudObjects = (partID) => {
|
|
|
31
31
|
if (environment.current.viewerMode === 'monitor' &&
|
|
32
32
|
fetchedPropQueries &&
|
|
33
33
|
client.current?.name &&
|
|
34
|
-
interval !== RefetchRates.OFF
|
|
34
|
+
interval !== RefetchRates.OFF &&
|
|
35
|
+
disabledVisionServices.get(client.current?.name) !== true) {
|
|
35
36
|
results.push(client);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
@@ -47,8 +48,8 @@ export const providePointcloudObjects = (partID) => {
|
|
|
47
48
|
$effect(() => {
|
|
48
49
|
for (const [name, query] of propQueries) {
|
|
49
50
|
if (name && query.data?.objectPointCloudsSupported === false) {
|
|
50
|
-
if (
|
|
51
|
-
|
|
51
|
+
if (disabledVisionServices.get(name) === undefined) {
|
|
52
|
+
disabledVisionServices.set(name, true);
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -83,7 +84,11 @@ export const providePointcloudObjects = (partID) => {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
Promise.allSettled(responses.map(async ([name, pointcloudObjects]) => {
|
|
86
|
-
const pointclouds = await Promise.all(pointcloudObjects
|
|
87
|
+
const pointclouds = await Promise.all(pointcloudObjects
|
|
88
|
+
.filter((value) => value !== undefined)
|
|
89
|
+
.map((value) => {
|
|
90
|
+
return parsePcdInWorker(new Uint8Array(value.pointCloud));
|
|
91
|
+
}));
|
|
87
92
|
return {
|
|
88
93
|
name,
|
|
89
94
|
pointclouds,
|
|
@@ -10,6 +10,7 @@ import { RefetchRates } from '../components/RefreshRate.svelte';
|
|
|
10
10
|
import { useLogs } from './useLogs.svelte';
|
|
11
11
|
import { useResourceByName } from './useResourceByName.svelte';
|
|
12
12
|
import { useRefetchPoses } from './useRefetchPoses';
|
|
13
|
+
const origingFrameComponentTypes = ['arm', 'gantry', 'gripper'];
|
|
13
14
|
export const usePose = (name, parent) => {
|
|
14
15
|
const environment = useEnvironment();
|
|
15
16
|
const logs = useLogs();
|
|
@@ -25,10 +26,10 @@ export const usePose = (name, parent) => {
|
|
|
25
26
|
const frames = useFrames();
|
|
26
27
|
let pose = $state(undefined);
|
|
27
28
|
const interval = $derived(refreshRates.get(RefreshRates.poses));
|
|
28
|
-
const resolvedParent = $derived(parentResource?.subtype
|
|
29
|
+
const resolvedParent = $derived(origingFrameComponentTypes.includes(parentResource?.subtype ?? '')
|
|
29
30
|
? `${parent()}_origin`
|
|
30
31
|
: parent());
|
|
31
|
-
const resolvedName = $derived(resource?.subtype
|
|
32
|
+
const resolvedName = $derived(origingFrameComponentTypes.includes(resource?.subtype ?? '')
|
|
32
33
|
? `${currentName}_origin`
|
|
33
34
|
: currentName);
|
|
34
35
|
const query = createRobotQuery(robotClient, 'getPose', () => [resolvedName, resolvedParent ?? 'world', []], () => ({
|
|
@@ -9,7 +9,12 @@ self.onmessage = async (event) => {
|
|
|
9
9
|
try {
|
|
10
10
|
const pcd = loader.parse(data.buffer);
|
|
11
11
|
if (pcd.geometry) {
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Positions is _usually_ defined. However, we have experienced parsing PCDs from Viam APIs that
|
|
14
|
+
* result in the Three.js parser not attaching this attribute, throwing errors downstream.
|
|
15
|
+
*/
|
|
16
|
+
const positions = pcd.geometry.attributes.position?.array ??
|
|
17
|
+
new Float32Array(0);
|
|
13
18
|
const colors = pcd.geometry.attributes.color?.array ?? null;
|
|
14
19
|
postMessage({ positions, colors, id }, colors ? [positions.buffer, colors.buffer] : [positions.buffer]);
|
|
15
20
|
}
|
package/package.json
CHANGED