@viamrobotics/motion-tools 1.15.7 → 1.16.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 (38) hide show
  1. package/dist/buf/common/v1/common_pb.d.ts +38 -0
  2. package/dist/buf/common/v1/common_pb.js +64 -0
  3. package/dist/buf/draw/v1/scene_pb.d.ts +6 -2
  4. package/dist/buf/draw/v1/scene_pb.js +9 -3
  5. package/dist/components/Entities/Geometry.svelte +1 -1
  6. package/dist/components/PCD.svelte +4 -1
  7. package/dist/components/PCD.svelte.d.ts +1 -0
  8. package/dist/components/SceneProviders.svelte +0 -2
  9. package/dist/components/{Lasso → Selection}/Debug.svelte +8 -8
  10. package/dist/components/{Lasso → Selection}/Debug.svelte.d.ts +2 -2
  11. package/dist/components/Selection/Ellipse.svelte +293 -0
  12. package/dist/components/Selection/Ellipse.svelte.d.ts +7 -0
  13. package/dist/components/{Lasso → Selection}/Lasso.svelte +31 -61
  14. package/dist/components/{Lasso → Selection}/Lasso.svelte.d.ts +1 -0
  15. package/dist/components/{Lasso → Selection}/Tool.svelte +50 -15
  16. package/dist/components/{Lasso → Selection}/traits.d.ts +11 -2
  17. package/dist/components/{Lasso → Selection}/traits.js +7 -2
  18. package/dist/components/Selection/utils.d.ts +5 -0
  19. package/dist/components/Selection/utils.js +38 -0
  20. package/dist/components/Snapshot.svelte +8 -0
  21. package/dist/components/overlay/RefreshRate.svelte +7 -6
  22. package/dist/components/overlay/RefreshRate.svelte.d.ts +1 -1
  23. package/dist/components/overlay/settings/Settings.svelte +16 -8
  24. package/dist/components/xr/OriginMarker.svelte +94 -17
  25. package/dist/hooks/useControls.svelte.d.ts +1 -0
  26. package/dist/hooks/useControls.svelte.js +4 -0
  27. package/dist/hooks/useGeometries.svelte.js +7 -9
  28. package/dist/hooks/usePointcloudObjects.svelte.js +7 -6
  29. package/dist/hooks/usePointclouds.svelte.js +7 -6
  30. package/dist/hooks/usePose.svelte.js +3 -3
  31. package/dist/hooks/useSettings.svelte.d.ts +13 -1
  32. package/dist/hooks/useSettings.svelte.js +13 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +1 -1
  35. package/package.json +1 -1
  36. package/dist/hooks/useMachineSettings.svelte.d.ts +0 -13
  37. package/dist/hooks/useMachineSettings.svelte.js +0 -58
  38. /package/dist/components/{Lasso → Selection}/Tool.svelte.d.ts +0 -0
@@ -4,20 +4,22 @@
4
4
  import { useThrelte } from '@threlte/core'
5
5
  import earcut from 'earcut'
6
6
  import { Not } from 'koota'
7
- import { Box3, Plane, Raycaster, Triangle, Vector2, Vector3 } from 'three'
7
+ import { Box3, Triangle, Vector3 } from 'three'
8
8
 
9
9
  import { createBufferGeometry } from '../../attribute'
10
10
  import { traits, useQuery, useWorld } from '../../ecs'
11
11
  import { useCameraControls } from '../../hooks/useControls.svelte'
12
12
 
13
13
  import Debug from './Debug.svelte'
14
- import * as lassoTraits from './traits'
14
+ import * as selectionTraits from './traits'
15
+ import { getTriangleBoxesFromIndices, getTriangleFromIndex, raycast } from './utils'
15
16
 
16
17
  interface Props {
18
+ active?: boolean
17
19
  debug?: boolean
18
20
  }
19
21
 
20
- let { debug = false }: Props = $props()
22
+ let { active = false, debug = false }: Props = $props()
21
23
 
22
24
  const world = useWorld()
23
25
  const controls = useCameraControls()
@@ -29,33 +31,14 @@
29
31
 
30
32
  const triangle = new Triangle()
31
33
  const triangleBox = new Box3()
32
- const a = new Vector3()
33
- const b = new Vector3()
34
- const c = new Vector3()
35
34
 
36
35
  let frameScheduled = false
37
36
  let drawing = false
38
37
 
39
- const raycaster = new Raycaster()
40
- const mouse = new Vector2()
41
- const plane = new Plane(new Vector3(0, 0, 1), 0)
42
- const point = new Vector3()
43
-
44
- const raycast = (event: PointerEvent) => {
45
- const element = event.target as HTMLElement
46
- const rect = element.getBoundingClientRect()
47
- mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
48
- mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
49
-
50
- raycaster.setFromCamera(mouse, camera.current)
51
- raycaster.ray.intersectPlane(plane, point)
52
- return point
53
- }
54
-
55
38
  const onpointerdown = (event: PointerEvent) => {
56
- if (!event.shiftKey) return
39
+ if (!event.shiftKey || !active) return
57
40
 
58
- const { x, y } = raycast(event)
41
+ const { x, y } = raycast(event, camera.current)
59
42
 
60
43
  drawing = true
61
44
 
@@ -65,8 +48,8 @@
65
48
  traits.RenderOrder(999),
66
49
  traits.Material({ depthTest: false }),
67
50
  traits.Color({ r: 1, g: 0, b: 0 }),
68
- lassoTraits.Box({ minX: x, minY: y, maxX: x, maxY: y }),
69
- lassoTraits.Lasso
51
+ selectionTraits.Box({ minX: x, minY: y, maxX: x, maxY: y }),
52
+ selectionTraits.Lasso
70
53
  )
71
54
 
72
55
  if (controls.current) {
@@ -75,9 +58,9 @@
75
58
  }
76
59
 
77
60
  const onpointermove = (event: PointerEvent) => {
78
- if (!drawing) return
61
+ if (!drawing || !active) return
79
62
 
80
- let lasso = world.query(lassoTraits.Lasso).at(-1)
63
+ let lasso = world.query(selectionTraits.Lasso).at(-1)
81
64
 
82
65
  if (!lasso) return
83
66
 
@@ -92,9 +75,9 @@
92
75
  requestAnimationFrame(() => {
93
76
  frameScheduled = false
94
77
 
95
- const { x, y } = raycast(event)
78
+ const { x, y } = raycast(event, camera.current)
96
79
  const positions = lasso.get(traits.LinePositions)
97
- const box = lasso.get(lassoTraits.Box)
80
+ const box = lasso.get(selectionTraits.Box)
98
81
 
99
82
  if (!positions || !box) return
100
83
 
@@ -110,22 +93,22 @@
110
93
  if (y < box.minY) box.minY = y
111
94
  else if (y > box.maxY) box.maxY = y
112
95
 
113
- lasso.set(lassoTraits.Box, box)
96
+ lasso.set(selectionTraits.Box, box)
114
97
  })
115
98
  }
116
99
 
117
100
  const onpointerleave = () => {
118
- if (!drawing) return
101
+ if (!drawing || !active) return
119
102
 
120
103
  onpointerup()
121
104
  }
122
105
 
123
106
  const onpointerup = () => {
124
- if (!drawing) return
107
+ if (!drawing || !active) return
125
108
 
126
109
  drawing = false
127
110
 
128
- let lasso = world.query(lassoTraits.Lasso).at(-1)
111
+ let lasso = world.query(selectionTraits.Lasso).at(-1)
129
112
 
130
113
  if (!lasso) return
131
114
 
@@ -149,31 +132,15 @@
149
132
 
150
133
  const indices = earcut(positions, undefined, 3)
151
134
  if (debug) {
152
- lasso.add(lassoTraits.Indices(new Uint16Array(indices)))
135
+ lasso.add(selectionTraits.Indices(new Uint16Array(indices)))
153
136
  }
154
137
 
155
- const getTriangleFromIndex = (i: number, triangle: Triangle) => {
156
- const stride = 3
157
- const ia = indices[i + 0] * stride
158
- const ib = indices[i + 1] * stride
159
- const ic = indices[i + 2] * stride
160
- a.set(positions[ia + 0], positions[ia + 1], positions[ia + 2])
161
- b.set(positions[ib + 0], positions[ib + 1], positions[ib + 2])
162
- c.set(positions[ic + 0], positions[ic + 1], positions[ic + 2])
163
- triangle.set(a, b, c)
164
- }
165
-
166
- const boxes: lassoTraits.AABB[] = []
167
- for (let i = 0, l = indices.length; i < l; i += 3) {
168
- getTriangleFromIndex(i, triangle)
169
- box3.setFromPoints([triangle.a, triangle.b, triangle.c])
170
- boxes.push({ minX: box3.min.x, minY: box3.min.y, maxX: box3.max.x, maxY: box3.max.y })
171
- }
138
+ const boxes: selectionTraits.AABB[] = getTriangleBoxesFromIndices(indices, positions)
172
139
  if (debug) {
173
- lasso.add(lassoTraits.Boxes(boxes))
140
+ lasso.add(selectionTraits.Boxes(boxes))
174
141
  }
175
142
 
176
- const lassoBox = lasso.get(lassoTraits.Box)
143
+ const lassoBox = lasso.get(selectionTraits.Box)
177
144
 
178
145
  if (!lassoBox) return
179
146
 
@@ -183,7 +150,10 @@
183
150
 
184
151
  const enclosedPoints: number[] = []
185
152
 
186
- for (const pointsEntity of world.query(traits.Points, Not(lassoTraits.LassoEnclosedPoints))) {
153
+ for (const pointsEntity of world.query(
154
+ traits.Points,
155
+ Not(selectionTraits.SelectionEnclosedPoints)
156
+ )) {
187
157
  const geometry = pointsEntity.get(traits.BufferGeometry)
188
158
 
189
159
  if (!geometry) return
@@ -208,7 +178,7 @@
208
178
  triangleBox.set(min, max)
209
179
 
210
180
  if (triangleBox.containsPoint(point)) {
211
- getTriangleFromIndex(i, triangle)
181
+ getTriangleFromIndex(i, indices, positions, triangle)
212
182
 
213
183
  if (triangle.containsPoint(point)) {
214
184
  enclosedPoints.push(point.x, point.y, point.z)
@@ -230,8 +200,8 @@
230
200
  traits.Material({ depthTest: false }),
231
201
  traits.Points,
232
202
  traits.Removable,
233
- lassoTraits.LassoEnclosedPoints,
234
- lassoTraits.PointsCapturedBy(lasso)
203
+ selectionTraits.SelectionEnclosedPoints,
204
+ selectionTraits.PointsCapturedBy(lasso)
235
205
  )
236
206
  }
237
207
 
@@ -265,7 +235,7 @@
265
235
  }
266
236
  })
267
237
 
268
- const lassos = useQuery(lassoTraits.Lasso)
238
+ const lassos = useQuery(selectionTraits.Lasso)
269
239
 
270
240
  $effect(() => {
271
241
  if (!controls.current) return
@@ -288,7 +258,7 @@
288
258
  // On unmount, destroy all lasso related entities
289
259
  $effect(() => {
290
260
  return () => {
291
- for (const entity of world.query(lassoTraits.LassoEnclosedPoints)) {
261
+ for (const entity of world.query(selectionTraits.SelectionEnclosedPoints)) {
292
262
  if (world.has(entity)) {
293
263
  entity.destroy()
294
264
  }
@@ -299,6 +269,6 @@
299
269
 
300
270
  {#if debug}
301
271
  {#each lassos.current as lasso (lasso)}
302
- <Debug {lasso} />
272
+ <Debug selection={lasso} />
303
273
  {/each}
304
274
  {/if}
@@ -1,4 +1,5 @@
1
1
  interface Props {
2
+ active?: boolean;
2
3
  debug?: boolean;
3
4
  }
4
5
  declare const Lasso: import("svelte").Component<Props, {}, "">;
@@ -13,8 +13,11 @@
13
13
  import { createBinaryPCD } from '../../pcd'
14
14
 
15
15
  import FloatingPanel from '../overlay/FloatingPanel.svelte'
16
+ import Popover from '../overlay/Popover.svelte'
17
+ import ToggleGroup from '../overlay/ToggleGroup.svelte'
18
+ import Ellipse from './Ellipse.svelte'
16
19
  import Lasso from './Lasso.svelte'
17
- import * as lassoTraits from './traits'
20
+ import * as selectionTraits from './traits'
18
21
 
19
22
  interface Props {
20
23
  /** Whether to auto-enable lasso mode when the component mounts */
@@ -24,15 +27,18 @@
24
27
  onSelection: (pcd: Blob) => void
25
28
  }
26
29
 
30
+ type SelectionType = 'lasso' | 'ellipse'
31
+
27
32
  let { enabled = false, onSelection }: Props = $props()
28
33
 
29
34
  const { dom } = useThrelte()
30
35
  const world = useWorld()
31
36
  const settings = useSettings()
32
- const isLassoMode = $derived(settings.current.interactionMode === 'lasso')
37
+ const isSelectionMode = $derived(settings.current.interactionMode === 'select')
38
+ let selectionType = $state<SelectionType>('lasso')
33
39
 
34
40
  const onCommitClick = () => {
35
- const entities = world.query(lassoTraits.LassoEnclosedPoints)
41
+ const entities = world.query(selectionTraits.SelectionEnclosedPoints)
36
42
 
37
43
  const geometries: BufferGeometry[] = []
38
44
  for (const entity of entities) {
@@ -58,14 +64,14 @@
58
64
  }
59
65
 
60
66
  $effect(() => {
61
- if (isLassoMode) {
67
+ if (isSelectionMode) {
62
68
  settings.current.cameraMode = 'orthographic'
63
69
  }
64
70
  })
65
71
 
66
72
  $effect(() => {
67
73
  if (enabled) {
68
- settings.current.interactionMode = 'lasso'
74
+ settings.current.interactionMode = 'select'
69
75
  }
70
76
  })
71
77
 
@@ -74,19 +80,48 @@
74
80
 
75
81
  <Portal id="dashboard">
76
82
  <fieldset>
77
- <DashboardButton
78
- active={isLassoMode}
79
- icon="selection-drag"
80
- description="{isLassoMode ? 'Disable' : 'Enable'} lasso selection"
81
- onclick={() => {
82
- settings.current.interactionMode = isLassoMode ? 'navigate' : 'lasso'
83
- }}
84
- />
83
+ <div class="flex">
84
+ <DashboardButton
85
+ active={isSelectionMode}
86
+ icon="selection-drag"
87
+ description="{isSelectionMode ? 'Disable' : 'Enable'} selection"
88
+ onclick={() => {
89
+ settings.current.interactionMode = isSelectionMode ? 'navigate' : 'select'
90
+ }}
91
+ />
92
+ <Popover>
93
+ {#snippet trigger(triggerProps)}
94
+ <DashboardButton
95
+ {...triggerProps}
96
+ active={isSelectionMode}
97
+ class="border-l-0"
98
+ icon="filter-sliders"
99
+ description="Selection settings"
100
+ />
101
+ {/snippet}
102
+
103
+ <div class="border-medium m-2 border bg-white p-2 text-xs">
104
+ <div class="flex items-center gap-2">
105
+ Selection type
106
+ <ToggleGroup
107
+ options={[
108
+ { label: 'Lasso', selected: selectionType === 'lasso' },
109
+ { label: 'Ellipse', selected: selectionType === 'ellipse' },
110
+ ]}
111
+ onSelect={(details) => {
112
+ selectionType = details.includes('Lasso') ? 'lasso' : 'ellipse'
113
+ }}
114
+ />
115
+ </div>
116
+ </div>
117
+ </Popover>
118
+ </div>
85
119
  </fieldset>
86
120
  </Portal>
87
121
 
88
- {#if isLassoMode && rect.height > 0 && rect.width > 0}
89
- <Lasso />
122
+ {#if isSelectionMode && rect.height > 0 && rect.width > 0}
123
+ <Ellipse active={selectionType === 'ellipse'} />
124
+ <Lasso active={selectionType === 'lasso'} />
90
125
 
91
126
  <Portal id="dom">
92
127
  <FloatingPanel
@@ -1,8 +1,9 @@
1
1
  export declare const Lasso: import("koota").Trait<() => boolean>;
2
- export declare const LassoEnclosedPoints: import("koota").Trait<() => boolean>;
2
+ export declare const Ellipse: import("koota").Trait<() => boolean>;
3
+ export declare const SelectionEnclosedPoints: import("koota").Trait<() => boolean>;
3
4
  /**
4
5
  * Captured points are removable, so we want to also destroy
5
- * the source lasso every time a user deletes one.
6
+ * the source selection every time a user deletes one.
6
7
  */
7
8
  export declare const PointsCapturedBy: import("koota").Relation<import("koota").Trait<Record<string, never>>>;
8
9
  export interface AABB {
@@ -11,11 +12,19 @@ export interface AABB {
11
12
  maxX: number;
12
13
  maxY: number;
13
14
  }
15
+ export interface Point {
16
+ x: number;
17
+ y: number;
18
+ }
14
19
  export declare const Box: import("koota").Trait<{
15
20
  minX: number;
16
21
  minY: number;
17
22
  maxX: number;
18
23
  maxY: number;
19
24
  }>;
25
+ export declare const StartPoint: import("koota").Trait<{
26
+ x: number;
27
+ y: number;
28
+ }>;
20
29
  export declare const Indices: import("koota").Trait<() => Uint16Array<ArrayBuffer>>;
21
30
  export declare const Boxes: import("koota").Trait<() => AABB[]>;
@@ -1,9 +1,10 @@
1
1
  import { relation, trait } from 'koota';
2
2
  export const Lasso = trait(() => true);
3
- export const LassoEnclosedPoints = trait(() => true);
3
+ export const Ellipse = trait(() => true);
4
+ export const SelectionEnclosedPoints = trait(() => true);
4
5
  /**
5
6
  * Captured points are removable, so we want to also destroy
6
- * the source lasso every time a user deletes one.
7
+ * the source selection every time a user deletes one.
7
8
  */
8
9
  export const PointsCapturedBy = relation({ autoDestroy: 'target' });
9
10
  export const Box = trait({
@@ -12,5 +13,9 @@ export const Box = trait({
12
13
  maxX: 0,
13
14
  maxY: 0,
14
15
  });
16
+ export const StartPoint = trait({
17
+ x: 0,
18
+ y: 0,
19
+ });
15
20
  export const Indices = trait(() => new Uint16Array());
16
21
  export const Boxes = trait(() => []);
@@ -0,0 +1,5 @@
1
+ import { Camera, Triangle, Vector3 } from 'three';
2
+ import type * as selectionTraits from './traits';
3
+ export declare const raycast: (event: PointerEvent, camera: Camera) => Vector3;
4
+ export declare const getTriangleFromIndex: (i: number, indices: number[], positions: Float32Array, outTriangle: Triangle) => void;
5
+ export declare const getTriangleBoxesFromIndices: (indices: number[], positions: Float32Array) => selectionTraits.AABB[];
@@ -0,0 +1,38 @@
1
+ import { Box3, Camera, Plane, Raycaster, Triangle, Vector2, Vector3 } from 'three';
2
+ const raycaster = new Raycaster();
3
+ const mouse = new Vector2();
4
+ const plane = new Plane(new Vector3(0, 0, 1), 0);
5
+ const point = new Vector3();
6
+ const triangle = new Triangle();
7
+ const box3 = new Box3();
8
+ const a = new Vector3();
9
+ const b = new Vector3();
10
+ const c = new Vector3();
11
+ export const raycast = (event, camera) => {
12
+ const element = event.target;
13
+ const rect = element.getBoundingClientRect();
14
+ mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
15
+ mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
16
+ raycaster.setFromCamera(mouse, camera);
17
+ raycaster.ray.intersectPlane(plane, point);
18
+ return point;
19
+ };
20
+ export const getTriangleFromIndex = (i, indices, positions, outTriangle) => {
21
+ const stride = 3;
22
+ const ia = indices[i + 0] * stride;
23
+ const ib = indices[i + 1] * stride;
24
+ const ic = indices[i + 2] * stride;
25
+ a.set(positions[ia + 0], positions[ia + 1], positions[ia + 2]);
26
+ b.set(positions[ib + 0], positions[ib + 1], positions[ib + 2]);
27
+ c.set(positions[ic + 0], positions[ic + 1], positions[ic + 2]);
28
+ outTriangle.set(a, b, c);
29
+ };
30
+ export const getTriangleBoxesFromIndices = (indices, positions) => {
31
+ const boxes = [];
32
+ for (let i = 0, l = indices.length; i < l; i += 3) {
33
+ getTriangleFromIndex(i, indices, positions, triangle);
34
+ box3.setFromPoints([triangle.a, triangle.b, triangle.c]);
35
+ boxes.push({ minX: box3.min.x, minY: box3.min.y, maxX: box3.max.x, maxY: box3.max.y });
36
+ }
37
+ return boxes;
38
+ };
@@ -66,6 +66,14 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
66
66
  position: [x * 0.001, y * 0.001, z * 0.001],
67
67
  lookAt: [lx * 0.001, ly * 0.001, lz * 0.001],
68
68
  })
69
+
70
+ if (sceneCamera.cameraType.case === 'orthographicCamera') {
71
+ const orthographicCamera = sceneCamera.cameraType.value as { zoom?: number }
72
+ const zoom = orthographicCamera.zoom
73
+ if (zoom !== undefined) {
74
+ cameraControls.setZoom(zoom)
75
+ }
76
+ }
69
77
  }
70
78
  })
71
79
 
@@ -20,10 +20,10 @@
20
20
 
21
21
  import { IconButton, Select } from '@viamrobotics/prime-core'
22
22
 
23
- import { useMachineSettings } from '../../hooks/useMachineSettings.svelte'
23
+ import { useSettings } from '../../hooks/useSettings.svelte'
24
24
 
25
25
  interface Props {
26
- id: string
26
+ id: 'poses' | 'pointclouds' | 'vision'
27
27
  label: string
28
28
  allowLive?: boolean
29
29
  onManualRefetch: () => void
@@ -32,8 +32,9 @@
32
32
 
33
33
  let { id, label, allowLive = false, onManualRefetch, children }: Props = $props()
34
34
 
35
- const { refreshRates } = useMachineSettings()
36
- const rate = $derived(refreshRates.get(id) ?? RefetchRates.MANUAL)
35
+ const settings = useSettings()
36
+ const { refreshRates } = $derived(settings.current)
37
+ const rate = $derived(refreshRates[id] ?? RefetchRates.MANUAL)
37
38
  </script>
38
39
 
39
40
  <label class="flex flex-col gap-1">
@@ -48,7 +49,7 @@
48
49
  onchange={(event: InputEvent) => {
49
50
  if (event.target instanceof HTMLSelectElement) {
50
51
  const { value } = event.target
51
- refreshRates.set(id, Number.parseInt(value, 10))
52
+ refreshRates[id] = Number.parseInt(value, 10)
52
53
  }
53
54
  }}
54
55
  value={String(rate)}
@@ -87,7 +88,7 @@
87
88
  variant="secondary"
88
89
  cx="border-light border"
89
90
  onclick={() => {
90
- refreshRates.set(id, RefetchRates.MANUAL)
91
+ refreshRates[id] = RefetchRates.MANUAL
91
92
  }}
92
93
  />
93
94
  {/if}
@@ -11,7 +11,7 @@ export declare const RefetchRates: {
11
11
  };
12
12
  import type { Snippet } from 'svelte';
13
13
  interface Props {
14
- id: string;
14
+ id: 'poses' | 'pointclouds' | 'vision';
15
15
  label: string;
16
16
  allowLive?: boolean;
17
17
  onManualRefetch: () => void;
@@ -9,11 +9,11 @@
9
9
  import DashboardButton from '../dashboard/Button.svelte'
10
10
  import XRControllerSettings from '../../xr/XRControllerSettings.svelte'
11
11
  import { useGeometries } from '../../../hooks/useGeometries.svelte'
12
- import { RefreshRates, useMachineSettings } from '../../../hooks/useMachineSettings.svelte'
13
12
  import { usePartID } from '../../../hooks/usePartID.svelte'
13
+ import { usePointcloudObjects } from '../../../hooks/usePointcloudObjects.svelte'
14
14
  import { usePointClouds } from '../../../hooks/usePointclouds.svelte'
15
15
  import { useRefetchPoses } from '../../../hooks/useRefetchPoses'
16
- import { useSettings } from '../../../hooks/useSettings.svelte'
16
+ import { RefreshRates, useSettings } from '../../../hooks/useSettings.svelte'
17
17
  import { useWeblabs, WEBLABS_EXPERIMENTS } from '../../../hooks/useWeblabs.svelte'
18
18
 
19
19
  import FloatingPanel from '../FloatingPanel.svelte'
@@ -26,9 +26,10 @@
26
26
  const cameras = useResourceNames(() => partID.current, 'camera')
27
27
  const visionServices = useResourceNames(() => partID.current, 'vision')
28
28
  const settings = useSettings()
29
- const { disabledCameras, disabledVisionServices } = useMachineSettings()
29
+ const { disabledCameras, disabledVisionServices } = $derived(settings.current)
30
30
  const geometries = useGeometries()
31
31
  const pointclouds = usePointClouds()
32
+ const pointcloudObjects = usePointcloudObjects()
32
33
  const { refetchPoses } = useRefetchPoses()
33
34
  const weblabs = useWeblabs()
34
35
  const knownWeblabs = Object.keys(WEBLABS_EXPERIMENTS)
@@ -87,11 +88,18 @@
87
88
  />
88
89
  <RefreshRate
89
90
  id={RefreshRates.pointclouds}
90
- label="Pointclouds"
91
+ label="Pointclouds from cameras"
91
92
  onManualRefetch={() => {
92
93
  pointclouds.refetch()
93
94
  }}
94
95
  />
96
+ <RefreshRate
97
+ id={RefreshRates.vision}
98
+ label="Vision service pointcloud segments and objects"
99
+ onManualRefetch={() => {
100
+ pointcloudObjects.refetch()
101
+ }}
102
+ />
95
103
  </div>
96
104
  {/snippet}
97
105
 
@@ -126,9 +134,9 @@
126
134
  <div class="flex items-center justify-between py-0.5 text-xs">
127
135
  {camera.name}
128
136
  <Switch
129
- on={disabledCameras.get(camera.name) !== true}
137
+ on={disabledCameras[camera.name] !== true}
130
138
  on:change={(event) => {
131
- disabledCameras.set(camera.name, !event.detail)
139
+ disabledCameras[camera.name] = !event.detail
132
140
  }}
133
141
  />
134
142
  </div>
@@ -146,9 +154,9 @@
146
154
  <div class="flex items-center justify-between py-0.5">
147
155
  {visionService.name}
148
156
  <Switch
149
- on={disabledVisionServices.get(visionService.name) !== true}
157
+ on={disabledVisionServices[visionService.name] !== true}
150
158
  on:change={(event) => {
151
- disabledVisionServices.set(visionService.name, !event.detail)
159
+ disabledVisionServices[visionService.name] = !event.detail
152
160
  }}
153
161
  />
154
162
  </div>