@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.
- package/dist/WorldObject.svelte.d.ts +12 -24
- package/dist/WorldObject.svelte.js +1 -1
- package/dist/components/App.svelte +32 -25
- package/dist/components/Details.svelte +94 -10
- package/dist/components/FileDrop.svelte +5 -2
- package/dist/components/Geometry.svelte +86 -70
- package/dist/components/Geometry.svelte.d.ts +3 -3
- package/dist/components/Pointcloud.svelte +3 -3
- package/dist/components/Pointcloud.svelte.d.ts +2 -5
- package/dist/components/RefreshRate.svelte +11 -6
- package/dist/components/RefreshRate.svelte.d.ts +3 -1
- package/dist/components/SceneProviders.svelte +5 -1
- package/dist/components/StaticGeometries.svelte +2 -2
- package/dist/components/Tree/Settings.svelte +10 -4
- package/dist/components/Tree/TreeContainer.svelte +2 -0
- package/dist/components/Tree/Widgets.svelte +24 -0
- package/dist/components/Tree/Widgets.svelte.d.ts +18 -0
- package/dist/components/WorldObjects.svelte +9 -9
- package/dist/components/shared/Table.svelte +37 -0
- package/dist/components/shared/Table.svelte.d.ts +7 -0
- package/dist/components/weblab/WeblabActive.svelte +20 -0
- package/dist/components/weblab/WeblabActive.svelte.d.ts +8 -0
- package/dist/components/weblab/WeblabProvider.svelte +8 -0
- package/dist/components/weblab/WeblabProvider.svelte.d.ts +5 -0
- package/dist/components/widgets/ArmPositions.svelte +76 -0
- package/dist/components/widgets/ArmPositions.svelte.d.ts +3 -0
- package/dist/format.d.ts +1 -0
- package/dist/format.js +15 -0
- package/dist/hooks/useArmClient.svelte.d.ts +7 -0
- package/dist/hooks/useArmClient.svelte.js +36 -0
- package/dist/hooks/useArrows.svelte.d.ts +3 -0
- package/dist/hooks/useArrows.svelte.js +9 -0
- package/dist/hooks/useDrawAPI.svelte.d.ts +0 -4
- package/dist/hooks/useDrawAPI.svelte.js +34 -29
- package/dist/hooks/useFrames.svelte.js +5 -8
- package/dist/hooks/useGeometries.svelte.js +4 -7
- package/dist/hooks/useMachineSettings.svelte.d.ts +4 -0
- package/dist/hooks/useMachineSettings.svelte.js +8 -1
- package/dist/hooks/usePointclouds.svelte.js +3 -6
- package/dist/hooks/usePose.svelte.js +2 -2
- package/dist/hooks/useSettings.svelte.d.ts +1 -0
- package/dist/hooks/useSettings.svelte.js +1 -0
- package/dist/hooks/useStaticGeometries.svelte.js +1 -1
- package/dist/hooks/useWeblabs.svelte.d.ts +12 -0
- package/dist/hooks/useWeblabs.svelte.js +25 -0
- package/dist/hooks/useWorldState.svelte.d.ts +2 -38
- package/dist/three/BatchedArrow.d.ts +2 -2
- package/dist/three/BatchedArrow.js +11 -6
- package/package.json +1 -1
- package/dist/hooks/usePoses.svelte.d.ts +0 -12
- 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
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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,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,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>
|
package/dist/format.d.ts
ADDED
|
@@ -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,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,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
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
83
|
+
geometry.geometryType.case = 'box';
|
|
84
|
+
geometry.geometryType.value = data.box;
|
|
77
85
|
}
|
|
78
86
|
else if ('sphere' in data) {
|
|
79
|
-
geometry =
|
|
87
|
+
geometry.geometryType.case = 'sphere';
|
|
88
|
+
geometry.geometryType.value = data.sphere;
|
|
80
89
|
}
|
|
81
90
|
else if ('capsule' in data) {
|
|
82
|
-
geometry =
|
|
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
|
-
|
|
192
|
-
|
|
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
|
-
|
|
226
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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(
|
|
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
|
|
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 :
|
|
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);
|
|
@@ -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(
|
|
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);
|