@viamrobotics/motion-tools 0.11.8 → 0.12.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 (51) hide show
  1. package/dist/WorldObject.svelte.d.ts +12 -24
  2. package/dist/WorldObject.svelte.js +1 -1
  3. package/dist/components/App.svelte +32 -25
  4. package/dist/components/Details.svelte +94 -10
  5. package/dist/components/FileDrop.svelte +5 -2
  6. package/dist/components/Geometry.svelte +86 -70
  7. package/dist/components/Geometry.svelte.d.ts +3 -3
  8. package/dist/components/Pointcloud.svelte +3 -3
  9. package/dist/components/Pointcloud.svelte.d.ts +2 -5
  10. package/dist/components/RefreshRate.svelte +11 -6
  11. package/dist/components/RefreshRate.svelte.d.ts +3 -1
  12. package/dist/components/SceneProviders.svelte +5 -1
  13. package/dist/components/StaticGeometries.svelte +2 -2
  14. package/dist/components/Tree/Settings.svelte +10 -4
  15. package/dist/components/Tree/TreeContainer.svelte +2 -0
  16. package/dist/components/Tree/Widgets.svelte +24 -0
  17. package/dist/components/Tree/Widgets.svelte.d.ts +18 -0
  18. package/dist/components/WorldObjects.svelte +9 -9
  19. package/dist/components/shared/Table.svelte +37 -0
  20. package/dist/components/shared/Table.svelte.d.ts +7 -0
  21. package/dist/components/weblab/WeblabActive.svelte +20 -0
  22. package/dist/components/weblab/WeblabActive.svelte.d.ts +8 -0
  23. package/dist/components/weblab/WeblabProvider.svelte +8 -0
  24. package/dist/components/weblab/WeblabProvider.svelte.d.ts +5 -0
  25. package/dist/components/widgets/ArmPositions.svelte +76 -0
  26. package/dist/components/widgets/ArmPositions.svelte.d.ts +3 -0
  27. package/dist/format.d.ts +1 -0
  28. package/dist/format.js +15 -0
  29. package/dist/hooks/useArmClient.svelte.d.ts +7 -0
  30. package/dist/hooks/useArmClient.svelte.js +36 -0
  31. package/dist/hooks/useArrows.svelte.d.ts +3 -0
  32. package/dist/hooks/useArrows.svelte.js +9 -0
  33. package/dist/hooks/useDrawAPI.svelte.d.ts +0 -4
  34. package/dist/hooks/useDrawAPI.svelte.js +34 -29
  35. package/dist/hooks/useFrames.svelte.js +5 -8
  36. package/dist/hooks/useGeometries.svelte.js +4 -7
  37. package/dist/hooks/useMachineSettings.svelte.d.ts +4 -0
  38. package/dist/hooks/useMachineSettings.svelte.js +8 -1
  39. package/dist/hooks/usePointclouds.svelte.js +3 -6
  40. package/dist/hooks/usePose.svelte.js +2 -2
  41. package/dist/hooks/useSettings.svelte.d.ts +1 -0
  42. package/dist/hooks/useSettings.svelte.js +1 -0
  43. package/dist/hooks/useStaticGeometries.svelte.js +1 -1
  44. package/dist/hooks/useWeblabs.svelte.d.ts +12 -0
  45. package/dist/hooks/useWeblabs.svelte.js +25 -0
  46. package/dist/hooks/useWorldState.svelte.d.ts +2 -38
  47. package/dist/three/BatchedArrow.d.ts +2 -2
  48. package/dist/three/BatchedArrow.js +11 -6
  49. package/package.json +1 -1
  50. package/dist/hooks/usePoses.svelte.d.ts +0 -12
  51. package/dist/hooks/usePoses.svelte.js +0 -63
@@ -6,7 +6,7 @@
6
6
  import { useSettings } from '../../hooks/useSettings.svelte'
7
7
  import { useResourceNames } from '@viamrobotics/svelte-sdk'
8
8
  import { usePartID } from '../../hooks/usePartID.svelte'
9
- import { useMachineSettings } from '../../hooks/useMachineSettings.svelte'
9
+ import { RefreshRates, useMachineSettings } from '../../hooks/useMachineSettings.svelte'
10
10
 
11
11
  const partID = usePartID()
12
12
  const cameras = useResourceNames(() => partID.current, 'camera')
@@ -22,9 +22,15 @@
22
22
  <div class="flex h-100 flex-col gap-2 overflow-scroll p-3">
23
23
  <h3 class="text-sm"><strong>Machine connection</strong></h3>
24
24
 
25
- <RefreshRate name="Geometries" />
26
- <RefreshRate name="Poses" />
27
- <RefreshRate name="Pointclouds" />
25
+ <RefreshRate
26
+ id={RefreshRates.poses}
27
+ label="Poses"
28
+ allowLive
29
+ />
30
+ <RefreshRate
31
+ id={RefreshRates.pointclouds}
32
+ label="Pointclouds"
33
+ />
28
34
  <div>
29
35
  <div>Enabled pointcloud cameras</div>
30
36
  {#each cameras.current as camera (camera)}
@@ -10,6 +10,7 @@
10
10
  import Logs from './Logs.svelte'
11
11
  import { useDraggable } from '../../hooks/useDraggable.svelte'
12
12
  import { useWorldStates } from '../../hooks/useWorldState.svelte'
13
+ import Widgets from './Widgets.svelte'
13
14
 
14
15
  const { ...rest } = $props()
15
16
 
@@ -55,4 +56,5 @@
55
56
 
56
57
  <Logs />
57
58
  <Settings />
59
+ <Widgets />
58
60
  </div>
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import { Switch } from '@viamrobotics/prime-core'
3
+ import Drawer from './Drawer.svelte'
4
+ import { useSettings } from '../../hooks/useSettings.svelte'
5
+
6
+ const settings = useSettings()
7
+ </script>
8
+
9
+ <Drawer
10
+ name="Widgets"
11
+ defaultOpen
12
+ >
13
+ <div class="flex h-24 flex-col gap-2 overflow-scroll p-3">
14
+ <div class="flex items-center justify-between gap-4 py-2">
15
+ Arm positions
16
+ <Switch
17
+ bind:on={settings.current.enableArmPositionsWidget}
18
+ on:change={(event) => {
19
+ settings.current.enableArmPositionsWidget = event.detail
20
+ }}
21
+ />
22
+ </div>
23
+ </div>
24
+ </Drawer>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Widgets: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Widgets = InstanceType<typeof Widgets>;
18
+ export default Widgets;
@@ -5,13 +5,14 @@
5
5
  import { useGeometries } from '../hooks/useGeometries.svelte'
6
6
  import { usePointClouds } from '../hooks/usePointclouds.svelte'
7
7
  import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
8
+ import { useWorldStates } from '../hooks/useWorldState.svelte'
9
+ import { useArrows } from '../hooks/useArrows.svelte'
8
10
  import Pose from './Pose.svelte'
9
11
  import Frame from './Frame.svelte'
10
12
  import Line from './Line.svelte'
11
13
  import Pointcloud from './Pointcloud.svelte'
12
14
  import Model from './WorldObject.svelte'
13
15
  import Label from './Label.svelte'
14
- import { useWorldStates } from '../hooks/useWorldState.svelte'
15
16
  import WorldState from './WorldState.svelte'
16
17
 
17
18
  const points = usePointClouds()
@@ -19,6 +20,7 @@
19
20
  const frames = useFrames()
20
21
  const geometries = useGeometries()
21
22
  const worldStates = useWorldStates()
23
+ const batchedArrow = useArrows()
22
24
  </script>
23
25
 
24
26
  {#each frames.current as object (object.uuid)}
@@ -78,14 +80,12 @@
78
80
  </Portal>
79
81
  {/each}
80
82
 
81
- {#if drawAPI.poses.length > 0}
82
- <T
83
- name={drawAPI.object3ds.batchedArrow.object3d.name}
84
- is={drawAPI.object3ds.batchedArrow.object3d}
85
- dispose={false}
86
- bvh={{ enabled: false }}
87
- />
88
- {/if}
83
+ <T
84
+ name={batchedArrow.object3d.name}
85
+ is={batchedArrow.object3d}
86
+ dispose={false}
87
+ bvh={{ enabled: false }}
88
+ />
89
89
 
90
90
  {#each drawAPI.meshes as object (object.uuid)}
91
91
  <Portal id={object.referenceFrame}>
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte'
3
+
4
+ interface Props {
5
+ children?: Snippet
6
+ }
7
+
8
+ const { children }: Props = $props()
9
+ </script>
10
+
11
+ <table class="motion-tools-table">
12
+ {@render children?.()}
13
+ </table>
14
+
15
+ <style>
16
+ @reference "../../../app.css";
17
+
18
+ .motion-tools-table {
19
+ @apply w-full table-auto;
20
+ }
21
+ .motion-tools-table :global(thead) {
22
+ @apply border-light bg-light border;
23
+ }
24
+ .motion-tools-table :global(thead th) {
25
+ @apply border-light text-subtle-1 border px-2.5 py-1 text-xs font-normal whitespace-nowrap;
26
+ }
27
+ .motion-tools-table :global(thead th abbr) {
28
+ @apply text-disabled;
29
+ }
30
+
31
+ .motion-tools-table :global(tbody) {
32
+ @apply border-light border;
33
+ }
34
+ .motion-tools-table :global(tbody th) {
35
+ @apply border-light font-roboto-mono text-default h-[40px] gap-2 border px-1.5 text-center text-xs font-normal;
36
+ }
37
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ children?: Snippet;
4
+ }
5
+ declare const Table: import("svelte").Component<Props, {}, "">;
6
+ type Table = ReturnType<typeof Table>;
7
+ export default Table;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { useWeblabs } from '../../hooks/useWeblabs.svelte'
3
+ import type { Snippet } from 'svelte'
4
+
5
+ interface Props {
6
+ experiment: string
7
+ children: Snippet
8
+ }
9
+ let { experiment, children }: Props = $props()
10
+
11
+ const { weblab } = useWeblabs()
12
+
13
+ $effect.pre(() => {
14
+ weblab.load([experiment])
15
+ })
16
+ </script>
17
+
18
+ {#if weblab.isActive(experiment)}
19
+ {@render children()}
20
+ {/if}
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ experiment: string;
4
+ children: Snippet;
5
+ }
6
+ declare const WeblabActive: import("svelte").Component<Props, {}, "">;
7
+ type WeblabActive = ReturnType<typeof WeblabActive>;
8
+ export default WeblabActive;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ import { provideWeblabs } from '../../hooks/useWeblabs.svelte'
3
+
4
+ let { children } = $props()
5
+ provideWeblabs()
6
+ </script>
7
+
8
+ {@render children()}
@@ -0,0 +1,5 @@
1
+ declare const WeblabProvider: import("svelte").Component<{
2
+ children: any;
3
+ }, {}, "">;
4
+ type WeblabProvider = ReturnType<typeof WeblabProvider>;
5
+ export default WeblabProvider;
@@ -0,0 +1,76 @@
1
+ <script lang="ts">
2
+ import { formatNumeric } from '../../format'
3
+ import Table from '../shared/Table.svelte'
4
+ import { useDraggable } from '../../hooks/useDraggable.svelte'
5
+ import { useArmClient } from '../../hooks/useArmClient.svelte'
6
+ import { Icon, Label, Select } from '@viamrobotics/prime-core'
7
+
8
+ const { ...rest } = $props()
9
+
10
+ const draggable = useDraggable('arm-current-positions')
11
+ const armClient = useArmClient()
12
+
13
+ let selectedArm = $state(armClient.names[0])
14
+
15
+ const positions = $derived(armClient.currentPositions[selectedArm])
16
+ </script>
17
+
18
+ <div
19
+ class="bg-extralight border-medium absolute top-0 left-0 z-1000 m-2 overflow-y-auto border text-xs"
20
+ style:transform="translate({draggable.current.x}px, {draggable.current.y}px)"
21
+ {...rest}
22
+ >
23
+ <div class="flex min-w-0 flex-col">
24
+ <div class="flex w-full items-center justify-between">
25
+ <div class="border-medium flex w-full items-center gap-1 border-b p-2">
26
+ <button
27
+ onmousedown={draggable.onDragStart}
28
+ onmouseup={draggable.onDragEnd}
29
+ >
30
+ <Icon name="drag" />
31
+ </button>
32
+ <h3>Arm positions</h3>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="flex flex-col gap-2 p-2">
37
+ <Label>
38
+ Select arm
39
+ <Select
40
+ slot="input"
41
+ value={selectedArm}
42
+ name="arm"
43
+ on:change={(event) => {
44
+ selectedArm = (event.target as HTMLSelectElement).value
45
+ }}
46
+ >
47
+ {#each armClient.names as name (name)}
48
+ <option value={name}>{name}</option>
49
+ {/each}
50
+ </Select>
51
+ </Label>
52
+ <Table>
53
+ <thead>
54
+ <tr>
55
+ <th> Joint </th>
56
+ <th>Position (degrees)</th>
57
+ </tr>
58
+ </thead>
59
+ <tbody>
60
+ {#if positions}
61
+ {#each positions as position, index ([position, index])}
62
+ <tr>
63
+ <th> {index} </th>
64
+ <th> {formatNumeric(position)} </th>
65
+ </tr>
66
+ {/each}
67
+ {:else}
68
+ <tr>
69
+ <th colspan="2"> No positions </th>
70
+ </tr>
71
+ {/if}
72
+ </tbody>
73
+ </Table>
74
+ </div>
75
+ </div>
76
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const ArmPositions: import("svelte").Component<Record<string, any>, {}, "">;
2
+ type ArmPositions = ReturnType<typeof ArmPositions>;
3
+ export default ArmPositions;
@@ -0,0 +1 @@
1
+ export declare const formatNumeric: (value?: number, decimals?: number) => string;
package/dist/format.js ADDED
@@ -0,0 +1,15 @@
1
+ export const formatNumeric = (value, decimals = 2) => {
2
+ if (value === undefined) {
3
+ return '––';
4
+ }
5
+ if (isNaN(value)) {
6
+ return 'NaN';
7
+ }
8
+ if (value === Number.POSITIVE_INFINITY) {
9
+ return '+∞';
10
+ }
11
+ if (value === Number.NEGATIVE_INFINITY) {
12
+ return '-∞';
13
+ }
14
+ return value.toFixed(decimals);
15
+ };
@@ -0,0 +1,7 @@
1
+ interface Context {
2
+ names: string[];
3
+ currentPositions: Record<string, number[] | undefined>;
4
+ }
5
+ export declare const provideArmClient: (partID: () => string) => void;
6
+ export declare const useArmClient: () => Context;
7
+ export {};
@@ -0,0 +1,36 @@
1
+ import { ArmClient, ArmJointPositions } from '@viamrobotics/sdk';
2
+ import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
3
+ import { getContext, setContext } from 'svelte';
4
+ const key = Symbol('arm-client-context');
5
+ export const provideArmClient = (partID) => {
6
+ const arms = useResourceNames(partID, 'arm');
7
+ const clients = $state({});
8
+ const options = { refetchInterval: 500 };
9
+ const jointPositionsQueries = $state({});
10
+ const names = $derived(arms.current.map((arm) => arm.name));
11
+ const currentPositions = $derived(Object.fromEntries(Object.entries(jointPositionsQueries).map(([name, query]) => [name, query.data?.values])));
12
+ $effect(() => {
13
+ for (const arm of arms.current) {
14
+ const client = createResourceClient(ArmClient, partID, () => arm.name);
15
+ if (client.current && !clients[arm.name])
16
+ clients[arm.name] = { current: client.current };
17
+ }
18
+ });
19
+ $effect(() => {
20
+ for (const client of Object.values(clients)) {
21
+ const query = createResourceQuery(client, 'getJointPositions', options);
22
+ jointPositionsQueries[client.current.name] = query.current;
23
+ }
24
+ });
25
+ setContext(key, {
26
+ get names() {
27
+ return names;
28
+ },
29
+ get currentPositions() {
30
+ return currentPositions;
31
+ },
32
+ });
33
+ };
34
+ export const useArmClient = () => {
35
+ return getContext(key);
36
+ };
@@ -0,0 +1,3 @@
1
+ import { BatchedArrow } from '../lib';
2
+ export declare const provideArrows: () => void;
3
+ export declare const useArrows: () => BatchedArrow;
@@ -0,0 +1,9 @@
1
+ import { BatchedArrow } from '../lib';
2
+ import { getContext, setContext } from 'svelte';
3
+ const key = Symbol('arrow-context');
4
+ export const provideArrows = () => {
5
+ setContext(key, new BatchedArrow());
6
+ };
7
+ export const useArrows = () => {
8
+ return getContext(key);
9
+ };
@@ -1,5 +1,4 @@
1
1
  import { Vector3 } from 'three';
2
- import { BatchedArrow } from '../three/BatchedArrow';
3
2
  import { WorldObject, type PointsGeometry } from '../WorldObject.svelte';
4
3
  type ConnectionStatus = 'connecting' | 'open' | 'closed';
5
4
  interface Context {
@@ -11,9 +10,6 @@ interface Context {
11
10
  nurbs: WorldObject[];
12
11
  models: WorldObject[];
13
12
  connectionStatus: ConnectionStatus;
14
- object3ds: {
15
- batchedArrow: BatchedArrow;
16
- };
17
13
  camera: {
18
14
  position: Vector3;
19
15
  lookAt: Vector3;
@@ -3,8 +3,8 @@ import { Color, Vector3, Vector4 } from 'three';
3
3
  import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
4
4
  import { parsePcdInWorker } from '../loaders/pcd';
5
5
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
6
- import { BatchedArrow } from '../three/BatchedArrow';
7
6
  import { WorldObject } from '../WorldObject.svelte';
7
+ import { useArrows } from './useArrows.svelte';
8
8
  const key = Symbol('draw-api-context-key');
9
9
  const tryParse = (json) => {
10
10
  try {
@@ -49,13 +49,16 @@ export const provideDrawAPI = () => {
49
49
  const color = new Color();
50
50
  const direction = new Vector3();
51
51
  const origin = new Vector3();
52
- const vec3 = new Vector3();
53
52
  const loader = new GLTFLoader();
53
+ const batchedArrow = useArrows();
54
54
  const drawPCD = async (buffer) => {
55
55
  const { positions, colors } = await parsePcdInWorker(new Uint8Array(buffer));
56
56
  points.push(new WorldObject(`points ${++pointsIndex}`, undefined, undefined, {
57
- case: 'points',
58
- value: positions,
57
+ center: undefined,
58
+ geometryType: {
59
+ case: 'points',
60
+ value: positions,
61
+ },
59
62
  }, colors ? { colors } : undefined));
60
63
  };
61
64
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -65,24 +68,28 @@ export const provideDrawAPI = () => {
65
68
  result.pose = data.center;
66
69
  return;
67
70
  }
68
- let geometry;
71
+ const geometry = {
72
+ label: data.label,
73
+ center: undefined,
74
+ geometryType: {
75
+ case: undefined,
76
+ },
77
+ };
69
78
  if ('mesh' in data) {
70
- geometry = {
71
- case: 'mesh',
72
- value: { contentType: '', mesh: data.mesh.mesh },
73
- };
79
+ geometry.geometryType.case = 'mesh';
80
+ geometry.geometryType.value = data.mesh;
74
81
  }
75
82
  else if ('box' in data) {
76
- geometry = { case: 'box', value: data.box };
83
+ geometry.geometryType.case = 'box';
84
+ geometry.geometryType.value = data.box;
77
85
  }
78
86
  else if ('sphere' in data) {
79
- geometry = { case: 'sphere', value: data.sphere };
87
+ geometry.geometryType.case = 'sphere';
88
+ geometry.geometryType.value = data.sphere;
80
89
  }
81
90
  else if ('capsule' in data) {
82
- geometry = { case: 'capsule', value: data.capsule };
83
- }
84
- else {
85
- geometry = { case: undefined, value: undefined };
91
+ geometry.geometryType.case = 'capsule';
92
+ geometry.geometryType.value = data.capsule;
86
93
  }
87
94
  const object = new WorldObject(data.label ?? ++geometryIndex, data.center, parent, geometry, {
88
95
  color,
@@ -97,10 +104,9 @@ export const provideDrawAPI = () => {
97
104
  }
98
105
  const controlPoints = data.ControlPts.map((point) => new Vector4(point.x / 1000, point.y / 1000, point.z / 1000));
99
106
  const curve = new NURBSCurve(data.Degree, data.Knots, controlPoints);
100
- const object = new WorldObject(data.name, data.pose, data.parent, { case: 'line', value: new Float32Array() }, { color, points: curve.getPoints(200) });
107
+ const object = new WorldObject(data.name, data.pose, data.parent, { center: undefined, geometryType: { case: 'line', value: new Float32Array() } }, { color, points: curve.getPoints(200) });
101
108
  nurbs.push(object);
102
109
  };
103
- const batchedArrow = new BatchedArrow();
104
110
  const drawPoses = async (reader) => {
105
111
  // Read counts
106
112
  const nPoints = reader.read();
@@ -120,12 +126,8 @@ export const provideDrawAPI = () => {
120
126
  for (let i = 0, j = 0, l = nextPoses.length; i < l; i += 6, j += 3) {
121
127
  origin.set(nextPoses[i], nextPoses[i + 1], nextPoses[i + 2]).multiplyScalar(0.001);
122
128
  direction.set(nextPoses[i + 3], nextPoses[i + 4], nextPoses[i + 5]);
123
- if (arrowHeadAtPose === 1) {
124
- // Compute the base position so the arrow ends at the origin
125
- origin.sub(vec3.copy(direction).multiplyScalar(length));
126
- }
127
129
  color.set(colors[j], colors[j + 1], colors[j + 2]);
128
- const arrowId = batchedArrow.addArrow(direction, origin, length, color);
130
+ const arrowId = batchedArrow.addArrow(direction, origin, length, color, arrowHeadAtPose === 1);
129
131
  poses.push(new WorldObject(`pose ${++poseIndex}`, undefined, undefined, undefined, {
130
132
  getBoundingBoxAt(box3) {
131
133
  return batchedArrow.getBoundingBoxAt(arrowId, box3);
@@ -188,8 +190,11 @@ export const provideDrawAPI = () => {
188
190
  color: new Color(r, g, b).convertLinearToSRGB(),
189
191
  };
190
192
  points.push(new WorldObject(label, undefined, undefined, {
191
- case: 'points',
192
- value: positions,
193
+ center: undefined,
194
+ geometryType: {
195
+ case: 'points',
196
+ value: positions,
197
+ },
193
198
  }, metadata));
194
199
  };
195
200
  const drawLine = async (reader) => {
@@ -222,8 +227,11 @@ export const provideDrawAPI = () => {
222
227
  points.push(new Vector3(positions[i], positions[i + 1], positions[i + 2]));
223
228
  }
224
229
  lines.push(new WorldObject(label, undefined, undefined, {
225
- case: 'line',
226
- value: positions,
230
+ center: undefined,
231
+ geometryType: {
232
+ case: 'line',
233
+ value: positions,
234
+ },
227
235
  }, {
228
236
  points,
229
237
  color: lineR === -1 ? undefined : new Color().setRGB(lineR, lineG, lineB),
@@ -400,9 +408,6 @@ export const provideDrawAPI = () => {
400
408
  get connectionStatus() {
401
409
  return connectionStatus;
402
410
  },
403
- object3ds: {
404
- batchedArrow,
405
- },
406
411
  get camera() {
407
412
  return camera;
408
413
  },
@@ -24,14 +24,11 @@ export const provideFrames = (partID) => {
24
24
  }
25
25
  const resourceName = resourceNames.current.find((item) => item.name === frame.referenceFrame);
26
26
  const frameName = frame.referenceFrame ? frame.referenceFrame : 'Unnamed frame';
27
- objects.push(new WorldObject(frameName, frame.poseInObserverFrame?.pose, frame.poseInObserverFrame?.referenceFrame));
28
- if (frame.physicalObject?.geometryType) {
29
- objects.push(new WorldObject(`${frameName} ${frame.physicalObject.geometryType.case}`, frame.physicalObject.center, frameName, frame.physicalObject.geometryType, resourceName
30
- ? {
31
- color: resourceColors[resourceName.subtype],
32
- }
33
- : undefined));
34
- }
27
+ objects.push(new WorldObject(frameName, frame.poseInObserverFrame?.pose, frame.poseInObserverFrame?.referenceFrame, frame.physicalObject, resourceName
28
+ ? {
29
+ color: resourceColors[resourceName.subtype],
30
+ }
31
+ : undefined));
35
32
  }
36
33
  return objects;
37
34
  });
@@ -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 { useMachineSettings } from './useMachineSettings.svelte';
6
+ import { useMachineSettings, RefreshRates } from './useMachineSettings.svelte';
7
7
  import { WorldObject } from '../WorldObject.svelte';
8
8
  import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
9
9
  import { useLogs } from './useLogs.svelte';
@@ -20,11 +20,8 @@ export const provideGeometries = (partID) => {
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)));
22
22
  const clients = $derived([...armClients, ...gripperClients, ...cameraClients]);
23
- if (!refreshRates.has('Geometries')) {
24
- refreshRates.set('Geometries', 1000);
25
- }
26
23
  const options = $derived.by(() => {
27
- const interval = refreshRates.get('Geometries');
24
+ const interval = refreshRates.get(RefreshRates.poses);
28
25
  const results = [];
29
26
  for (const client of clients) {
30
27
  const options = queryOptions({
@@ -51,9 +48,9 @@ export const provideGeometries = (partID) => {
51
48
  for (const query of queries.current) {
52
49
  if (!query.data)
53
50
  continue;
54
- for (const { center, label, geometryType } of query.data.geometries) {
51
+ for (const geometry of query.data.geometries) {
55
52
  const resourceName = resourceNames.current.find((item) => item.name === query.data.name);
56
- const worldObject = new WorldObject(label ? label : 'Unnamed geometry', center, query.data.name, geometryType, resourceName
53
+ const worldObject = new WorldObject(geometry.label ? geometry.label : `${query.data.name} geometry`, undefined, query.data.name, geometry, resourceName
57
54
  ? { color: resourceColors[resourceName.subtype] }
58
55
  : undefined);
59
56
  results.push(worldObject);
@@ -1,4 +1,8 @@
1
1
  import { SvelteMap } from 'svelte/reactivity';
2
+ export declare const RefreshRates: {
3
+ readonly poses: "poses";
4
+ readonly pointclouds: "pointclouds";
5
+ };
2
6
  type Context = {
3
7
  refreshRates: SvelteMap<string, number>;
4
8
  disabledCameras: SvelteMap<string, boolean>;
@@ -4,6 +4,10 @@ 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
+ export const RefreshRates = {
8
+ poses: 'poses',
9
+ pointclouds: 'pointclouds',
10
+ };
7
11
  const setFromEntries = (map, entries) => {
8
12
  if (entries) {
9
13
  for (const [key, value] of entries) {
@@ -12,7 +16,10 @@ const setFromEntries = (map, entries) => {
12
16
  }
13
17
  };
14
18
  export const provideMachineSettings = () => {
15
- const refreshRates = new SvelteMap();
19
+ const refreshRates = new SvelteMap([
20
+ [RefreshRates.poses, 1000],
21
+ [RefreshRates.pointclouds, -1],
22
+ ]);
16
23
  const disabledCameras = new SvelteMap();
17
24
  get(refreshRatesKey).then((entries) => {
18
25
  setFromEntries(refreshRates, entries);
@@ -4,7 +4,7 @@ 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 { useMachineSettings } from './useMachineSettings.svelte';
7
+ import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
8
8
  import { WorldObject } from '../WorldObject.svelte';
9
9
  import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
10
10
  import { useLogs } from './useLogs.svelte';
@@ -13,12 +13,9 @@ export const providePointclouds = (partID) => {
13
13
  const logs = useLogs();
14
14
  const { refreshRates, disabledCameras } = useMachineSettings();
15
15
  const cameras = useResourceNames(partID, 'camera');
16
- if (!refreshRates.has('Pointclouds')) {
17
- refreshRates.set('Pointclouds', -1);
18
- }
19
16
  const clients = $derived(cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)));
20
17
  const options = $derived.by(() => {
21
- const interval = refreshRates.get('Pointclouds');
18
+ const interval = refreshRates.get(RefreshRates.pointclouds);
22
19
  const results = [];
23
20
  for (const cameraClient of clients) {
24
21
  const name = cameraClient.current?.name ?? '';
@@ -37,7 +34,7 @@ export const providePointclouds = (partID) => {
37
34
  if (!response)
38
35
  return null;
39
36
  const { positions, colors } = await parsePcdInWorker(new Uint8Array(response));
40
- return new WorldObject(`${name}:pointcloud`, undefined, name, { case: 'points', value: positions }, colors ? { colors } : undefined);
37
+ return new WorldObject(`${name}:pointcloud`, undefined, name, { center: undefined, geometryType: { case: 'points', value: positions } }, colors ? { colors } : undefined);
41
38
  },
42
39
  });
43
40
  results.push(options);