@viamrobotics/motion-tools 0.8.0 → 0.9.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.
@@ -1,38 +1,36 @@
1
1
  <script lang="ts">
2
2
  import { T } from '@threlte/core'
3
- import { PerspectiveCamera, OrthographicCamera } from 'three'
4
3
  import { useSettings } from '../hooks/useSettings.svelte'
5
4
 
6
5
  let { children, ...rest } = $props()
7
6
 
8
7
  const settings = useSettings()
9
8
  const mode = $derived(settings.current.cameraMode)
10
-
11
- const perspective = new PerspectiveCamera()
12
- perspective.near = 0.01
13
- perspective.up.set(0, 0, 1)
14
-
15
- const orthographic = new OrthographicCamera()
16
- orthographic.near = -100
17
- orthographic.far = 100
18
- orthographic.up.set(0, 0, 1)
19
- orthographic.zoom = 200
20
9
  </script>
21
10
 
22
11
  {#if mode === 'perspective'}
23
- <T
24
- is={perspective}
12
+ <T.PerspectiveCamera
25
13
  makeDefault
14
+ near={0.01}
15
+ up={[0, 0, 1]}
16
+ oncreate={(ref) => {
17
+ ref.lookAt(0, 0, 0)
18
+ }}
26
19
  {...rest}
27
20
  >
28
21
  {@render children?.()}
29
- </T>
22
+ </T.PerspectiveCamera>
30
23
  {:else if mode === 'orthographic'}
31
- <T
32
- is={orthographic}
24
+ <T.OrthographicCamera
33
25
  makeDefault
26
+ near={-100}
27
+ far={100}
28
+ up={[0, 0, 1]}
29
+ oncreate={(ref) => {
30
+ ref.lookAt(0, 0, 0)
31
+ }}
34
32
  {...rest}
35
33
  >
36
34
  {@render children?.()}
37
- </T>
35
+ </T.OrthographicCamera>
38
36
  {/if}
@@ -4,18 +4,19 @@
4
4
  import KeyboardControls from './KeyboardControls.svelte'
5
5
  import Portal from './portal/Portal.svelte'
6
6
  import Button from './dashboard/Button.svelte'
7
- import { useShapes } from '../hooks/useShapes.svelte'
7
+ import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
8
8
 
9
- const shapes = useShapes()
9
+ const drawAPI = useDrawAPI()
10
10
  const transformControls = useTransformControls()
11
11
 
12
12
  let ref = $state.raw<CameraControlsRef>()
13
13
 
14
14
  $effect(() => {
15
- if (shapes.camera) {
16
- const { position, lookAt, animate } = shapes.camera
15
+ if (drawAPI.camera) {
16
+ const { position, lookAt, animate } = drawAPI.camera
17
17
  ref?.setPosition(position.x, position.y, position.z, animate)
18
18
  ref?.setLookAt(position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, animate)
19
+ drawAPI.clearCamera()
19
20
  }
20
21
  })
21
22
  </script>
@@ -23,7 +23,7 @@
23
23
  })
24
24
  </script>
25
25
 
26
- <Camera position={[0, 0, size[0] + 1]}>
26
+ <Camera position={[size[0] + 1, size[0] + 1, size[0] + 1]}>
27
27
  <TrackballControls target={center}>
28
28
  <Gizmo />
29
29
  </TrackballControls>
@@ -12,7 +12,6 @@
12
12
  let { object }: Props = $props()
13
13
 
14
14
  const settings = useSettings()
15
- $inspect(object.metadata.points)
16
15
  </script>
17
16
 
18
17
  <Frame
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">
2
2
  import { Portal } from './portal'
3
3
  import { usePointClouds } from '../hooks/usePointclouds.svelte'
4
- import { useShapes } from '../hooks/useShapes.svelte'
4
+ import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
5
5
  import Pointcloud from './Pointcloud.svelte'
6
6
 
7
7
  const points = usePointClouds()
8
- const shapes = useShapes()
8
+ const drawAPI = useDrawAPI()
9
9
  </script>
10
10
 
11
11
  {#each points.current as object (object.uuid)}
@@ -14,7 +14,7 @@
14
14
  </Portal>
15
15
  {/each}
16
16
 
17
- {#each shapes.points as object (object.uuid)}
17
+ {#each drawAPI.points as object (object.uuid)}
18
18
  <Portal id={object.referenceFrame}>
19
19
  <Pointcloud {object} />
20
20
  </Portal>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { Select } from '@viamrobotics/prime-core'
3
- import { useRefreshRates } from '../hooks/useRefreshRates.svelte'
3
+ import { useMachineSettings } from '../hooks/useMachineSettings.svelte'
4
4
  import type { Snippet } from 'svelte'
5
5
 
6
6
  interface Props {
@@ -10,8 +10,8 @@
10
10
 
11
11
  let { name, children }: Props = $props()
12
12
 
13
- const pollingRates = useRefreshRates()
14
- const rate = $derived(pollingRates.get(name))
13
+ const { refreshRates } = useMachineSettings()
14
+ const rate = $derived(refreshRates.get(name))
15
15
  </script>
16
16
 
17
17
  <label class="flex flex-col gap-1">
@@ -20,7 +20,7 @@
20
20
  onchange={(event: InputEvent) => {
21
21
  if (event.target instanceof HTMLSelectElement) {
22
22
  const { value } = event.target
23
- pollingRates.set(name, Number.parseInt(value, 10))
23
+ refreshRates.set(name, Number.parseInt(value, 10))
24
24
  }
25
25
  }}
26
26
  value={String(rate ?? '')}
@@ -6,8 +6,8 @@
6
6
  import { provideSelection } from '../hooks/useSelection.svelte'
7
7
  import { provideStaticGeometries } from '../hooks/useStaticGeometries.svelte'
8
8
  import { provideVisibility } from '../hooks/useVisibility.svelte'
9
- import { provideShapes } from '../hooks/useShapes.svelte'
10
- import { provideRefreshRates } from '../hooks/useRefreshRates.svelte'
9
+ import { provideDrawAPI } from '../hooks/useDrawAPI.svelte'
10
+ import { provideMachineSettings } from '../hooks/useMachineSettings.svelte'
11
11
  import { provideTransformControls } from '../hooks/useControls.svelte'
12
12
  import type { Snippet } from 'svelte'
13
13
  import { provideObjects } from '../hooks/useObjects.svelte'
@@ -27,12 +27,12 @@
27
27
  provideSettings()
28
28
  provideTransformControls()
29
29
  provideVisibility()
30
- provideRefreshRates()
30
+ provideMachineSettings()
31
31
  provideLogs()
32
32
 
33
33
  provideOrigin()
34
34
  provideStaticGeometries()
35
- provideShapes()
35
+ provideDrawAPI()
36
36
 
37
37
  provideFrames(() => partID.current)
38
38
  provideGeometries(() => partID.current)
@@ -1,21 +1,21 @@
1
1
  <script lang="ts">
2
2
  import { T } from '@threlte/core'
3
3
  import { Portal, PortalTarget } from './portal'
4
- import { useShapes } from '../hooks/useShapes.svelte'
4
+ import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
5
5
  import WorldObject from './WorldObject.svelte'
6
6
  import Frame from './Frame.svelte'
7
7
  import Line from './Line.svelte'
8
8
 
9
- const shapes = useShapes()
9
+ const drawAPI = useDrawAPI()
10
10
  </script>
11
11
 
12
12
  <T
13
- name={shapes.object3ds.batchedArrow.object3d.name}
14
- is={shapes.object3ds.batchedArrow.object3d}
13
+ name={drawAPI.object3ds.batchedArrow.object3d.name}
14
+ is={drawAPI.object3ds.batchedArrow.object3d}
15
15
  dispose={false}
16
16
  />
17
17
 
18
- {#each shapes.meshes as object (object.uuid)}
18
+ {#each drawAPI.meshes as object (object.uuid)}
19
19
  <Portal id={object.referenceFrame}>
20
20
  <Frame
21
21
  uuid={object.uuid}
@@ -29,7 +29,7 @@
29
29
  </Portal>
30
30
  {/each}
31
31
 
32
- {#each shapes.nurbs as object (object.uuid)}
32
+ {#each drawAPI.nurbs as object (object.uuid)}
33
33
  <Portal id={object.referenceFrame}>
34
34
  <Frame
35
35
  uuid={object.uuid}
@@ -43,12 +43,12 @@
43
43
  </Portal>
44
44
  {/each}
45
45
 
46
- {#each shapes.models as object (object.uuid)}
46
+ {#each drawAPI.models as object (object.uuid)}
47
47
  <WorldObject {object}>
48
48
  <PortalTarget id={object.name} />
49
49
  </WorldObject>
50
50
  {/each}
51
51
 
52
- {#each shapes.lines as object (object.uuid)}
52
+ {#each drawAPI.lines as object (object.uuid)}
53
53
  <Line {object} />
54
54
  {/each}
@@ -4,8 +4,14 @@
4
4
  import { useMotionClient } from '../../hooks/useMotionClient.svelte'
5
5
  import Drawer from './Drawer.svelte'
6
6
  import { useSettings } from '../../hooks/useSettings.svelte'
7
+ import { useResourceNames } from '@viamrobotics/svelte-sdk'
8
+ import { usePartID } from '../../hooks/usePartID.svelte'
9
+ import { useMachineSettings } from '../../hooks/useMachineSettings.svelte'
7
10
 
11
+ const partID = usePartID()
12
+ const cameras = useResourceNames(() => partID.current, 'camera')
8
13
  const settings = useSettings()
14
+ const { disabledCameras } = useMachineSettings()
9
15
  const motionClient = useMotionClient()
10
16
  </script>
11
17
 
@@ -14,20 +20,30 @@
14
20
  defaultOpen
15
21
  >
16
22
  <div class="flex h-100 flex-col gap-2 overflow-scroll p-3">
17
- <h3 class="text-base"><strong>Refresh rates</strong></h3>
23
+ <h3 class="text-sm"><strong>Machine connection</strong></h3>
18
24
 
19
- <RefreshRate name="Frames">
20
- <option value="0">Do not fetch</option>
21
- <option value="1">Fetch on reconfigure</option>
22
- </RefreshRate>
23
- <RefreshRate name="Pointclouds" />
24
25
  <RefreshRate name="Geometries" />
25
26
  <RefreshRate name="Poses" />
26
-
27
- <h3 class="text-base"><strong>Motion</strong></h3>
27
+ <RefreshRate name="Pointclouds" />
28
+ <div>
29
+ <div>Enabled pointcloud cameras</div>
30
+ {#each cameras.current as camera (camera)}
31
+ <div class="flex items-center justify-between gap-4 py-2">
32
+ {camera.name}
33
+ <Switch
34
+ on={disabledCameras.get(camera.name) !== true}
35
+ on:change={(event) => {
36
+ disabledCameras.set(camera.name, !event.detail)
37
+ }}
38
+ />
39
+ </div>
40
+ {:else}
41
+ No cameras detected
42
+ {/each}
43
+ </div>
28
44
 
29
45
  <label class="flex flex-col gap-1">
30
- Client
46
+ Motion client
31
47
  <Select
32
48
  onchange={(event: InputEvent) => {
33
49
  if (event.target instanceof HTMLSelectElement) {
@@ -42,7 +58,7 @@
42
58
  </Select>
43
59
  </label>
44
60
 
45
- <h3 class="text-base"><strong>Pointclouds</strong></h3>
61
+ <h3 class="pt-2 text-sm"><strong>Pointclouds</strong></h3>
46
62
  <div class="flex flex-col gap-2.5">
47
63
  <label class="flex items-center justify-between gap-2">
48
64
  Default point size
@@ -68,7 +84,7 @@
68
84
  </label>
69
85
  </div>
70
86
 
71
- <h3 class="text-base"><strong>Grid</strong></h3>
87
+ <h3 class="pt-2 text-sm"><strong>Grid</strong></h3>
72
88
  <div class="flex flex-col gap-2.5">
73
89
  <label class="flex items-center justify-between gap-2">
74
90
  Enabled <Switch bind:on={settings.current.grid} />
@@ -108,7 +124,7 @@
108
124
  </label>
109
125
  </div>
110
126
 
111
- <h3 class="text-base"><strong>Lines</strong></h3>
127
+ <h3 class="pt-2 text-sm"><strong>Lines</strong></h3>
112
128
  <div class="flex flex-col gap-2.5">
113
129
  <label class="flex items-center justify-between gap-2">
114
130
  Thickness
@@ -133,7 +149,7 @@
133
149
  </label>
134
150
  </div>
135
151
 
136
- <h3 class="text-base"><strong>Misc</strong></h3>
152
+ <h3 class="pt-2 text-sm"><strong>Misc</strong></h3>
137
153
  <div class="flex flex-col gap-2.5">
138
154
  <label class="flex items-center justify-between gap-2">
139
155
  Render stats <Switch bind:on={settings.current.renderStats} />
@@ -18,7 +18,8 @@ interface Context {
18
18
  lookAt: Vector3;
19
19
  animate: boolean;
20
20
  } | undefined;
21
+ clearCamera: () => void;
21
22
  }
22
- export declare const provideShapes: () => void;
23
- export declare const useShapes: () => Context;
23
+ export declare const provideDrawAPI: () => void;
24
+ export declare const useDrawAPI: () => Context;
24
25
  export {};
@@ -5,7 +5,7 @@ import { parsePcdInWorker } from '../loaders/pcd';
5
5
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
6
6
  import { BatchedArrow } from '../three/BatchedArrow';
7
7
  import { WorldObject } from '../WorldObject';
8
- const key = Symbol('websocket-context-key');
8
+ const key = Symbol('draw-api-context-key');
9
9
  const tryParse = (json) => {
10
10
  try {
11
11
  return JSON.parse(json);
@@ -31,7 +31,7 @@ class Float32Reader {
31
31
  return result;
32
32
  }
33
33
  }
34
- export const provideShapes = () => {
34
+ export const provideDrawAPI = () => {
35
35
  let pointsIndex = 0;
36
36
  let geometryIndex = 0;
37
37
  let poseIndex = 0;
@@ -44,7 +44,7 @@ export const provideShapes = () => {
44
44
  const poses = $state([]);
45
45
  const nurbs = $state([]);
46
46
  const models = $state([]);
47
- let camera = $state();
47
+ let camera = $state.raw();
48
48
  let connectionStatus = $state('connecting');
49
49
  const color = new Color();
50
50
  const direction = new Vector3();
@@ -174,7 +174,7 @@ export const provideShapes = () => {
174
174
  : {
175
175
  color: new Color(r, g, b).convertLinearToSRGB(),
176
176
  };
177
- points.push(new WorldObject(label ?? `points ${++pointsIndex}`, undefined, undefined, {
177
+ points.push(new WorldObject(label, undefined, undefined, {
178
178
  case: 'points',
179
179
  value: positions,
180
180
  }, metadata));
@@ -386,8 +386,11 @@ export const provideShapes = () => {
386
386
  get camera() {
387
387
  return camera;
388
388
  },
389
+ clearCamera: () => {
390
+ camera = undefined;
391
+ },
389
392
  });
390
393
  };
391
- export const useShapes = () => {
394
+ export const useDrawAPI = () => {
392
395
  return getContext(key);
393
396
  };
@@ -1,7 +1,6 @@
1
1
  import { getContext, setContext, untrack } from 'svelte';
2
2
  import { useRobotClient, createRobotQuery, useMachineStatus, useResourceNames, } from '@viamrobotics/svelte-sdk';
3
3
  import { WorldObject } from '../WorldObject';
4
- import { useRefreshRates } from './useRefreshRates.svelte';
5
4
  import { observe } from '@threlte/core';
6
5
  import { useLogs } from './useLogs.svelte';
7
6
  import { resourceColors } from '../color';
@@ -11,24 +10,14 @@ export const provideFrames = (partID) => {
11
10
  const client = useRobotClient(partID);
12
11
  const machineStatus = useMachineStatus(partID);
13
12
  const logs = useLogs();
14
- const refreshRates = useRefreshRates();
15
- if (!refreshRates.has('Frames')) {
16
- refreshRates.set('Frames', 1);
17
- }
18
13
  const query = createRobotQuery(client, 'frameSystemConfig');
19
14
  const revision = $derived(machineStatus.current?.config.revision);
20
- const shouldFetch = $derived(refreshRates.get('Frames') === 1);
21
15
  observe.pre(() => [revision], () => {
22
- if (shouldFetch) {
23
- untrack(() => query.current).refetch();
24
- logs.add('Fetching frames...');
25
- }
16
+ untrack(() => query.current).refetch();
17
+ logs.add('Fetching frames...');
26
18
  });
27
19
  const current = $derived.by(() => {
28
20
  const objects = [];
29
- if (!shouldFetch) {
30
- return objects;
31
- }
32
21
  for (const { frame } of query.current.data ?? []) {
33
22
  if (frame === undefined) {
34
23
  continue;
@@ -3,7 +3,7 @@ import { createQueries, queryOptions } from '@tanstack/svelte-query';
3
3
  import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
4
4
  import { setContext, getContext } from 'svelte';
5
5
  import { fromStore, toStore } from 'svelte/store';
6
- import { useRefreshRates } from './useRefreshRates.svelte';
6
+ import { useMachineSettings } from './useMachineSettings.svelte';
7
7
  import { WorldObject } from '../WorldObject';
8
8
  import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
9
9
  import { useLogs } from './useLogs.svelte';
@@ -15,7 +15,7 @@ export const provideGeometries = (partID) => {
15
15
  const cameras = useResourceNames(partID, 'camera');
16
16
  const grippers = useResourceNames(partID, 'gripper');
17
17
  const logs = useLogs();
18
- const refreshRates = useRefreshRates();
18
+ const { refreshRates } = useMachineSettings();
19
19
  const armClients = $derived(arms.current.map((arm) => createResourceClient(ArmClient, partID, () => arm.name)));
20
20
  const gripperClients = $derived(grippers.current.map((gripper) => createResourceClient(GripperClient, partID, () => gripper.name)));
21
21
  const cameraClients = $derived(cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)));
@@ -23,22 +23,27 @@ export const provideGeometries = (partID) => {
23
23
  if (!refreshRates.has('Geometries')) {
24
24
  refreshRates.set('Geometries', 1000);
25
25
  }
26
- const options = $derived(clients.map((client) => {
26
+ const options = $derived.by(() => {
27
27
  const interval = refreshRates.get('Geometries');
28
- return queryOptions({
29
- enabled: interval !== -1 && client.current !== undefined,
30
- refetchInterval: interval === 0 ? false : interval,
31
- queryKey: ['partID', partID(), client.current?.name, 'getGeometries'],
32
- queryFn: async () => {
33
- if (!client.current) {
34
- throw new Error('No client');
35
- }
36
- logs.add(`Fetching geometries for ${client.current.name}...`);
37
- const geometries = await client.current.getGeometries();
38
- return { name: client.current.name, geometries };
39
- },
40
- });
41
- }));
28
+ const results = [];
29
+ for (const client of clients) {
30
+ const options = queryOptions({
31
+ enabled: interval !== -1 && client.current !== undefined,
32
+ refetchInterval: interval === 0 ? false : interval,
33
+ queryKey: ['partID', partID(), client.current?.name, 'getGeometries'],
34
+ queryFn: async () => {
35
+ if (!client.current) {
36
+ throw new Error('No client');
37
+ }
38
+ logs.add(`Fetching geometries for ${client.current.name}...`);
39
+ const geometries = await client.current.getGeometries();
40
+ return { name: client.current.name, geometries };
41
+ },
42
+ });
43
+ results.push(options);
44
+ }
45
+ return results;
46
+ });
42
47
  const { updateUUIDs } = usePersistentUUIDs();
43
48
  const queries = fromStore(createQueries({ queries: toStore(() => options) }));
44
49
  const geometries = $derived.by(() => {
@@ -0,0 +1,8 @@
1
+ import { SvelteMap } from 'svelte/reactivity';
2
+ type Context = {
3
+ refreshRates: SvelteMap<string, number>;
4
+ disabledCameras: SvelteMap<string, boolean>;
5
+ };
6
+ export declare const provideMachineSettings: () => void;
7
+ export declare const useMachineSettings: () => Context;
8
+ export {};
@@ -0,0 +1,40 @@
1
+ import { get, set } from 'idb-keyval';
2
+ import { getContext, setContext } from 'svelte';
3
+ import { SvelteMap } from 'svelte/reactivity';
4
+ const key = Symbol('polling-rate-context');
5
+ const refreshRatesKey = 'polling-rate';
6
+ const disabledCamerasKey = 'disabled-cameras';
7
+ const setFromEntries = (map, entries) => {
8
+ if (entries) {
9
+ for (const [key, value] of entries) {
10
+ map.set(key, value);
11
+ }
12
+ }
13
+ };
14
+ export const provideMachineSettings = () => {
15
+ const refreshRates = new SvelteMap();
16
+ const disabledCameras = new SvelteMap();
17
+ get(refreshRatesKey).then((entries) => {
18
+ setFromEntries(refreshRates, entries);
19
+ });
20
+ get(disabledCamerasKey).then((entries) => {
21
+ setFromEntries(disabledCameras, entries);
22
+ });
23
+ $effect(() => {
24
+ set(refreshRatesKey, [...refreshRates.entries()]);
25
+ });
26
+ $effect(() => {
27
+ set(disabledCamerasKey, [...disabledCameras.entries()]);
28
+ });
29
+ setContext(key, {
30
+ get refreshRates() {
31
+ return refreshRates;
32
+ },
33
+ get disabledCameras() {
34
+ return disabledCameras;
35
+ },
36
+ });
37
+ };
38
+ export const useMachineSettings = () => {
39
+ return getContext(key);
40
+ };
@@ -2,26 +2,26 @@ import { getContext, setContext } from 'svelte';
2
2
  import { useFrames } from './useFrames.svelte';
3
3
  import { useGeometries } from './useGeometries.svelte';
4
4
  import { useStaticGeometries } from './useStaticGeometries.svelte';
5
- import { useShapes } from './useShapes.svelte';
5
+ import { useDrawAPI } from './useDrawAPI.svelte';
6
6
  import { usePointClouds } from './usePointclouds.svelte';
7
7
  const key = Symbol('objects-context');
8
8
  export const provideObjects = () => {
9
9
  const frames = useFrames();
10
10
  const geometries = useGeometries();
11
11
  const statics = useStaticGeometries();
12
- const shapes = useShapes();
12
+ const drawAPI = useDrawAPI();
13
13
  const points = usePointClouds();
14
14
  const objects = $derived([
15
15
  ...frames.current,
16
16
  ...geometries.current,
17
17
  ...points.current,
18
- ...shapes.meshes,
19
- ...shapes.models,
20
- ...shapes.nurbs,
21
- ...shapes.points,
22
- ...shapes.lines,
23
18
  ...statics.current,
24
- ...shapes.poses,
19
+ ...drawAPI.meshes,
20
+ ...drawAPI.models,
21
+ ...drawAPI.nurbs,
22
+ ...drawAPI.points,
23
+ ...drawAPI.lines,
24
+ ...drawAPI.poses,
25
25
  ]);
26
26
  setContext(key, {
27
27
  get current() {
@@ -4,39 +4,46 @@ import { setContext, getContext } from 'svelte';
4
4
  import { fromStore, toStore } from 'svelte/store';
5
5
  import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
6
6
  import { parsePcdInWorker } from '../loaders/pcd';
7
- import { useRefreshRates } from './useRefreshRates.svelte';
7
+ import { useMachineSettings } from './useMachineSettings.svelte';
8
8
  import { WorldObject } from '../WorldObject';
9
9
  import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
10
10
  import { useLogs } from './useLogs.svelte';
11
11
  const key = Symbol('pointcloud-context');
12
12
  export const providePointclouds = (partID) => {
13
13
  const logs = useLogs();
14
- const refreshRates = useRefreshRates();
14
+ const { refreshRates, disabledCameras } = useMachineSettings();
15
15
  const cameras = useResourceNames(partID, 'camera');
16
16
  if (!refreshRates.has('Pointclouds')) {
17
17
  refreshRates.set('Pointclouds', -1);
18
18
  }
19
19
  const clients = $derived(cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)));
20
- const options = $derived(clients.map((cameraClient) => {
21
- const name = cameraClient.current?.name ?? '';
20
+ const options = $derived.by(() => {
22
21
  const interval = refreshRates.get('Pointclouds');
23
- return queryOptions({
24
- enabled: interval !== -1 && cameraClient.current !== undefined,
25
- refetchInterval: interval === 0 ? false : interval,
26
- queryKey: ['partID', partID(), name, 'getPointCloud'],
27
- queryFn: async () => {
28
- if (!cameraClient.current) {
29
- throw new Error('No camera client');
30
- }
31
- logs.add(`Fetching pointcloud for ${cameraClient.current.name}`);
32
- const response = await cameraClient.current.getPointCloud();
33
- if (!response)
34
- return null;
35
- const { positions, colors } = await parsePcdInWorker(new Uint8Array(response));
36
- return new WorldObject(`${name}:pointcloud`, undefined, name, { case: 'points', value: positions }, colors ? { colors } : undefined);
37
- },
38
- });
39
- }));
22
+ const results = [];
23
+ for (const cameraClient of clients) {
24
+ const name = cameraClient.current?.name ?? '';
25
+ const options = queryOptions({
26
+ enabled: interval !== -1 &&
27
+ cameraClient.current !== undefined &&
28
+ disabledCameras.get(name) !== true,
29
+ refetchInterval: interval === 0 ? false : interval,
30
+ queryKey: ['partID', partID(), name, 'getPointCloud'],
31
+ queryFn: async () => {
32
+ if (!cameraClient.current) {
33
+ throw new Error('No camera client');
34
+ }
35
+ logs.add(`Fetching pointcloud for ${cameraClient.current.name}`);
36
+ const response = await cameraClient.current.getPointCloud();
37
+ if (!response)
38
+ return null;
39
+ const { positions, colors } = await parsePcdInWorker(new Uint8Array(response));
40
+ return new WorldObject(`${name}:pointcloud`, undefined, name, { case: 'points', value: positions }, colors ? { colors } : undefined);
41
+ },
42
+ });
43
+ results.push(options);
44
+ }
45
+ return results;
46
+ });
40
47
  const { updateUUIDs } = usePersistentUUIDs();
41
48
  const queries = fromStore(createQueries({
42
49
  queries: toStore(() => options),
@@ -2,17 +2,17 @@ import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk
2
2
  import { usePartID } from './usePartID.svelte';
3
3
  import { MotionClient } from '@viamrobotics/sdk';
4
4
  import { createQuery, queryOptions } from '@tanstack/svelte-query';
5
- import { useRefreshRates } from './useRefreshRates.svelte';
5
+ import { useMachineSettings } from './useMachineSettings.svelte';
6
6
  import { fromStore, toStore } from 'svelte/store';
7
7
  import { useMotionClient } from './useMotionClient.svelte';
8
8
  export const usePose = (name, parent) => {
9
- const refreshRates = useRefreshRates();
9
+ const { refreshRates } = useMachineSettings();
10
10
  const partID = usePartID();
11
11
  const motionClient = useMotionClient();
12
12
  const resources = useResourceNames(() => partID.current);
13
13
  const resource = $derived(resources.current.find((resource) => resource.name === name()));
14
14
  const client = createResourceClient(MotionClient, () => partID.current, () => motionClient.current ?? '');
15
- const interval = refreshRates.get('Poses');
15
+ const interval = $derived(refreshRates.get('Poses'));
16
16
  const options = $derived(queryOptions({
17
17
  enabled: interval !== -1 && client.current !== undefined && resource !== undefined,
18
18
  refetchInterval: interval === 0 ? false : interval,
@@ -3,10 +3,10 @@ import { MotionClient, PoseInFrame, ResourceName } from '@viamrobotics/sdk';
3
3
  import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
4
4
  import { getContext, setContext } from 'svelte';
5
5
  import { fromStore, toStore } from 'svelte/store';
6
- import { useRefreshRates } from './useRefreshRates.svelte';
6
+ import { useMachineSettings } from './useMachineSettings.svelte';
7
7
  const key = Symbol('poses-context');
8
8
  export const providePoses = (partID) => {
9
- const refreshRates = useRefreshRates();
9
+ const { refreshRates } = useMachineSettings();
10
10
  const resources = useResourceNames(partID);
11
11
  const components = $derived(resources.current.filter(({ type }) => type === 'component'));
12
12
  const motionResources = useResourceNames(partID, 'motion');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,5 +0,0 @@
1
- import { SvelteMap } from 'svelte/reactivity';
2
- type Context = SvelteMap<string, number>;
3
- export declare const provideRefreshRates: () => SvelteMap<string, number>;
4
- export declare const useRefreshRates: () => Context;
5
- export {};
@@ -1,23 +0,0 @@
1
- import { get, set } from 'idb-keyval';
2
- import { getContext, setContext } from 'svelte';
3
- import { SvelteMap } from 'svelte/reactivity';
4
- const key = Symbol('polling-rate-context');
5
- const idbKey = 'polling-rate';
6
- export const provideRefreshRates = () => {
7
- const map = new SvelteMap();
8
- get(idbKey).then((entries) => {
9
- if (entries) {
10
- for (const [key, value] of entries) {
11
- map.set(key, value);
12
- }
13
- }
14
- });
15
- $effect(() => {
16
- set(idbKey, [...map.entries()]);
17
- });
18
- setContext(key, map);
19
- return map;
20
- };
21
- export const useRefreshRates = () => {
22
- return getContext(key);
23
- };