@viamrobotics/motion-tools 0.1.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/LICENSE +21 -0
- package/README.md +20 -0
- package/dist/WorldObject.d.ts +33 -0
- package/dist/WorldObject.js +18 -0
- package/dist/assert.d.ts +14 -0
- package/dist/assert.js +21 -0
- package/dist/color.d.ts +8 -0
- package/dist/color.js +14 -0
- package/dist/components/App.svelte +63 -0
- package/dist/components/App.svelte.d.ts +8 -0
- package/dist/components/AxesHelper.svelte +17 -0
- package/dist/components/AxesHelper.svelte.d.ts +4 -0
- package/dist/components/BentPlaneGeometry.svelte +52 -0
- package/dist/components/BentPlaneGeometry.svelte.d.ts +29 -0
- package/dist/components/Camera.svelte +45 -0
- package/dist/components/Camera.svelte.d.ts +5 -0
- package/dist/components/CameraControls.svelte +82 -0
- package/dist/components/CameraControls.svelte.d.ts +9 -0
- package/dist/components/Details.svelte +161 -0
- package/dist/components/Details.svelte.d.ts +3 -0
- package/dist/components/Detections.svelte +41 -0
- package/dist/components/Detections.svelte.d.ts +3 -0
- package/dist/components/DetectionsPlane.svelte +23 -0
- package/dist/components/DetectionsPlane.svelte.d.ts +21 -0
- package/dist/components/DomPortal.svelte +20 -0
- package/dist/components/DomPortal.svelte.d.ts +5 -0
- package/dist/components/Focus.svelte +49 -0
- package/dist/components/Focus.svelte.d.ts +3 -0
- package/dist/components/Frame.svelte +112 -0
- package/dist/components/Frame.svelte.d.ts +16 -0
- package/dist/components/Frames.svelte +54 -0
- package/dist/components/Frames.svelte.d.ts +18 -0
- package/dist/components/Pointcloud.svelte +55 -0
- package/dist/components/Pointcloud.svelte.d.ts +10 -0
- package/dist/components/Pointclouds.svelte +21 -0
- package/dist/components/Pointclouds.svelte.d.ts +18 -0
- package/dist/components/Pose.svelte +19 -0
- package/dist/components/Pose.svelte.d.ts +12 -0
- package/dist/components/RefreshRate.svelte +47 -0
- package/dist/components/RefreshRate.svelte.d.ts +8 -0
- package/dist/components/Scene.svelte +81 -0
- package/dist/components/Scene.svelte.d.ts +7 -0
- package/dist/components/SceneProviders.svelte +41 -0
- package/dist/components/SceneProviders.svelte.d.ts +9 -0
- package/dist/components/Selected.svelte +44 -0
- package/dist/components/Selected.svelte.d.ts +3 -0
- package/dist/components/Shapes.svelte +49 -0
- package/dist/components/Shapes.svelte.d.ts +18 -0
- package/dist/components/StaticGeometries.svelte +79 -0
- package/dist/components/StaticGeometries.svelte.d.ts +18 -0
- package/dist/components/Tree/Settings.svelte +54 -0
- package/dist/components/Tree/Settings.svelte.d.ts +18 -0
- package/dist/components/Tree/Tree.svelte +204 -0
- package/dist/components/Tree/Tree.svelte.d.ts +10 -0
- package/dist/components/Tree/TreeContainer.svelte +70 -0
- package/dist/components/Tree/TreeContainer.svelte.d.ts +3 -0
- package/dist/components/Tree/buildTree.d.ts +11 -0
- package/dist/components/Tree/buildTree.js +29 -0
- package/dist/components/Tree/useExpanded.svelte.d.ts +5 -0
- package/dist/components/Tree/useExpanded.svelte.js +21 -0
- package/dist/components/WorldObject.svelte +27 -0
- package/dist/components/WorldObject.svelte.d.ts +11 -0
- package/dist/components/XR.svelte +20 -0
- package/dist/components/XR.svelte.d.ts +3 -0
- package/dist/components/models/README.md +5 -0
- package/dist/components/null-states/Connection.svelte +0 -0
- package/dist/components/null-states/Connection.svelte.d.ts +26 -0
- package/dist/components/portal/Portal.svelte +25 -0
- package/dist/components/portal/Portal.svelte.d.ts +8 -0
- package/dist/components/portal/PortalTarget.svelte +18 -0
- package/dist/components/portal/PortalTarget.svelte.d.ts +6 -0
- package/dist/components/portal/index.d.ts +2 -0
- package/dist/components/portal/index.js +2 -0
- package/dist/components/portal/usePortalContext.svelte.d.ts +5 -0
- package/dist/components/portal/usePortalContext.svelte.js +8 -0
- package/dist/components/xr/CameraFeed.svelte +81 -0
- package/dist/components/xr/CameraFeed.svelte.d.ts +6 -0
- package/dist/components/xr/Controllers.svelte +71 -0
- package/dist/components/xr/Controllers.svelte.d.ts +3 -0
- package/dist/components/xr/Draggable.svelte +101 -0
- package/dist/components/xr/Draggable.svelte.d.ts +11 -0
- package/dist/components/xr/HandCollider.svelte +19 -0
- package/dist/components/xr/HandCollider.svelte.d.ts +18 -0
- package/dist/components/xr/Hands.svelte +24 -0
- package/dist/components/xr/Hands.svelte.d.ts +18 -0
- package/dist/components/xr/OriginMarker.svelte +100 -0
- package/dist/components/xr/OriginMarker.svelte.d.ts +3 -0
- package/dist/components/xr/PointDistance.svelte +52 -0
- package/dist/components/xr/PointDistance.svelte.d.ts +3 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useConnectionConfigs.svelte.d.ts +17 -0
- package/dist/hooks/useConnectionConfigs.svelte.js +40 -0
- package/dist/hooks/useControls.svelte.d.ts +7 -0
- package/dist/hooks/useControls.svelte.js +16 -0
- package/dist/hooks/useDraggable.svelte.d.ts +2 -0
- package/dist/hooks/useDraggable.svelte.js +25 -0
- package/dist/hooks/useFrames.svelte.d.ts +9 -0
- package/dist/hooks/useFrames.svelte.js +50 -0
- package/dist/hooks/useGeometries.svelte.d.ts +7 -0
- package/dist/hooks/useGeometries.svelte.js +58 -0
- package/dist/hooks/useMotionClient.svelte.d.ts +8 -0
- package/dist/hooks/useMotionClient.svelte.js +31 -0
- package/dist/hooks/useObjectEvents.svelte.d.ts +9 -0
- package/dist/hooks/useObjectEvents.svelte.js +31 -0
- package/dist/hooks/useObjects.svelte.d.ts +7 -0
- package/dist/hooks/useObjects.svelte.js +33 -0
- package/dist/hooks/usePartID.svelte.d.ts +6 -0
- package/dist/hooks/usePartID.svelte.js +14 -0
- package/dist/hooks/usePersistentUUIDs.svelte.d.ts +5 -0
- package/dist/hooks/usePersistentUUIDs.svelte.js +14 -0
- package/dist/hooks/usePointclouds.svelte.d.ts +7 -0
- package/dist/hooks/usePointclouds.svelte.js +58 -0
- package/dist/hooks/usePose.svelte.d.ts +3 -0
- package/dist/hooks/usePose.svelte.js +44 -0
- package/dist/hooks/usePoses.svelte.d.ts +12 -0
- package/dist/hooks/usePoses.svelte.js +63 -0
- package/dist/hooks/useRefreshRates.svelte.d.ts +5 -0
- package/dist/hooks/useRefreshRates.svelte.js +23 -0
- package/dist/hooks/useSelection.svelte.d.ts +40 -0
- package/dist/hooks/useSelection.svelte.js +92 -0
- package/dist/hooks/useShapes.svelte.d.ts +17 -0
- package/dist/hooks/useShapes.svelte.js +264 -0
- package/dist/hooks/useStaticGeometries.svelte.d.ts +9 -0
- package/dist/hooks/useStaticGeometries.svelte.js +37 -0
- package/dist/hooks/useVisibility.svelte.d.ts +5 -0
- package/dist/hooks/useVisibility.svelte.js +22 -0
- package/dist/hooks/xr/useAnchors.svelte.d.ts +0 -0
- package/dist/hooks/xr/useAnchors.svelte.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/keybindings.d.ts +12 -0
- package/dist/keybindings.js +12 -0
- package/dist/loaders/pcd/index.d.ts +4 -0
- package/dist/loaders/pcd/index.js +13 -0
- package/dist/loaders/pcd/worker.d.ts +1 -0
- package/dist/loaders/pcd/worker.js +26 -0
- package/dist/three/AxesHelper.d.ts +5 -0
- package/dist/three/AxesHelper.js +35 -0
- package/dist/three/BatchedArrow.d.ts +30 -0
- package/dist/three/BatchedArrow.js +126 -0
- package/dist/three/BoxHelper.d.ts +50 -0
- package/dist/three/BoxHelper.js +134 -0
- package/dist/three/CapsuleGeometry.d.ts +10 -0
- package/dist/three/CapsuleGeometry.js +17 -0
- package/dist/transform.d.ts +11 -0
- package/dist/transform.js +65 -0
- package/package.json +110 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { T, useTask } from '@threlte/core'
|
|
3
|
+
import Draggable from './Draggable.svelte'
|
|
4
|
+
import { Mesh, Vector3 } from 'three'
|
|
5
|
+
import { Text, Billboard } from '@threlte/extras'
|
|
6
|
+
|
|
7
|
+
const mesh1 = new Mesh()
|
|
8
|
+
const mesh2 = new Mesh()
|
|
9
|
+
const distance = new Vector3()
|
|
10
|
+
const midpoint = new Vector3()
|
|
11
|
+
|
|
12
|
+
const pos1 = new Vector3()
|
|
13
|
+
const pos2 = new Vector3()
|
|
14
|
+
|
|
15
|
+
let text = $state('')
|
|
16
|
+
let textPosition = $state<[number, number, number]>([0, 0, 0])
|
|
17
|
+
|
|
18
|
+
useTask(() => {
|
|
19
|
+
distance.subVectors(mesh1.getWorldPosition(pos1), mesh2.getWorldPosition(pos2))
|
|
20
|
+
midpoint.addVectors(mesh1.getWorldPosition(pos1), mesh2.getWorldPosition(pos2)).divideScalar(2)
|
|
21
|
+
textPosition = midpoint.toArray()
|
|
22
|
+
|
|
23
|
+
const x = (distance.x ?? 0).toFixed(3)
|
|
24
|
+
const y = (distance.y ?? 0).toFixed(3)
|
|
25
|
+
const z = (distance.z ?? 0).toFixed(3)
|
|
26
|
+
text = `${x},${y},${z}`
|
|
27
|
+
})
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<T.Group position={[-1, 1, 0]}>
|
|
31
|
+
<Draggable onPointerEnter={() => null}>
|
|
32
|
+
<T is={mesh1}>
|
|
33
|
+
<T.SphereGeometry args={[0.05]} />
|
|
34
|
+
<T.MeshStandardMaterial />
|
|
35
|
+
</T>
|
|
36
|
+
</Draggable>
|
|
37
|
+
</T.Group>
|
|
38
|
+
|
|
39
|
+
<T.Group position={textPosition}>
|
|
40
|
+
<Billboard>
|
|
41
|
+
<Text {text} />
|
|
42
|
+
</Billboard>
|
|
43
|
+
</T.Group>
|
|
44
|
+
|
|
45
|
+
<T.Group position={[-1.5, 1, 0]}>
|
|
46
|
+
<Draggable>
|
|
47
|
+
<T is={mesh2}>
|
|
48
|
+
<T.SphereGeometry args={[0.05]} />
|
|
49
|
+
<T.MeshStandardMaterial />
|
|
50
|
+
</T>
|
|
51
|
+
</Draggable>
|
|
52
|
+
</T.Group>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { provideConnectionConfigs, useConnectionConfigs, useActiveConnectionConfig, } from './useConnectionConfigs.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { provideConnectionConfigs, useConnectionConfigs, useActiveConnectionConfig, } from './useConnectionConfigs.svelte';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface ConnectionConfig {
|
|
2
|
+
host: string;
|
|
3
|
+
partId: string;
|
|
4
|
+
apiKeyId: string;
|
|
5
|
+
apiKeyValue: string;
|
|
6
|
+
signalingAddress: string;
|
|
7
|
+
}
|
|
8
|
+
interface Context {
|
|
9
|
+
current: ConnectionConfig[];
|
|
10
|
+
}
|
|
11
|
+
export declare const provideConnectionConfigs: () => void;
|
|
12
|
+
export declare const useConnectionConfigs: () => Context;
|
|
13
|
+
export declare const useActiveConnectionConfig: () => {
|
|
14
|
+
readonly current: ConnectionConfig | undefined;
|
|
15
|
+
set(index: number | undefined): void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { get, set } from 'idb-keyval';
|
|
2
|
+
import { PersistedState } from 'runed';
|
|
3
|
+
import { getContext, setContext } from 'svelte';
|
|
4
|
+
import { envDialConfigs } from '../../routes/lib/configs';
|
|
5
|
+
const key = Symbol('connection-config-context');
|
|
6
|
+
const activeConfig = new PersistedState('active-connection-config', 0);
|
|
7
|
+
export const provideConnectionConfigs = () => {
|
|
8
|
+
let connectionConfigs = $state([]);
|
|
9
|
+
get('connection-configs').then((response) => {
|
|
10
|
+
if (Array.isArray(response)) {
|
|
11
|
+
connectionConfigs = response;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
$effect(() => {
|
|
15
|
+
set('connection-configs', $state.snapshot(connectionConfigs));
|
|
16
|
+
});
|
|
17
|
+
const envConfigs = Object.values(envDialConfigs);
|
|
18
|
+
setContext(key, {
|
|
19
|
+
get current() {
|
|
20
|
+
return [...envConfigs, ...connectionConfigs];
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
export const useConnectionConfigs = () => {
|
|
25
|
+
return getContext(key);
|
|
26
|
+
};
|
|
27
|
+
export const useActiveConnectionConfig = () => {
|
|
28
|
+
const connectionConfigs = useConnectionConfigs();
|
|
29
|
+
return {
|
|
30
|
+
get current() {
|
|
31
|
+
if (activeConfig.current === -1) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return connectionConfigs.current.at(activeConfig.current);
|
|
35
|
+
},
|
|
36
|
+
set(index) {
|
|
37
|
+
activeConfig.current = index ?? -1;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const key = Symbol('tranform-controls-context');
|
|
3
|
+
export const provideTransformControls = () => {
|
|
4
|
+
let active = $state(false);
|
|
5
|
+
setContext(key, {
|
|
6
|
+
get active() {
|
|
7
|
+
return active;
|
|
8
|
+
},
|
|
9
|
+
setActive(value) {
|
|
10
|
+
active = value;
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
export const useTransformControls = () => {
|
|
15
|
+
return getContext(key);
|
|
16
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PersistedState } from 'runed';
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
const key = Symbol('draggables-context');
|
|
4
|
+
export const provideDraggables = () => { };
|
|
5
|
+
export const useDraggable = (name) => {
|
|
6
|
+
const down = { x: 0, y: 0 };
|
|
7
|
+
const onDragMove = () => { };
|
|
8
|
+
const onDragStart = (event) => {
|
|
9
|
+
down.x = event.clientX;
|
|
10
|
+
down.y = event.clientY;
|
|
11
|
+
};
|
|
12
|
+
const onDragEnd = (event) => {
|
|
13
|
+
translate.current.x += event.clientX - down.x;
|
|
14
|
+
translate.current.y += event.clientY - down.y;
|
|
15
|
+
};
|
|
16
|
+
const translate = new PersistedState(`${name} draggable`, { x: 0, y: 0 });
|
|
17
|
+
setContext(key, {
|
|
18
|
+
onDragStart,
|
|
19
|
+
onDragMove,
|
|
20
|
+
onDragEnd,
|
|
21
|
+
get current() {
|
|
22
|
+
return translate.current;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WorldObject } from '../WorldObject';
|
|
2
|
+
interface FramesContext {
|
|
3
|
+
current: WorldObject[];
|
|
4
|
+
error?: Error;
|
|
5
|
+
fetching: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const provideFrames: (partID: () => string) => void;
|
|
8
|
+
export declare const useFrames: () => FramesContext;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getContext, setContext, untrack } from 'svelte';
|
|
2
|
+
import { useRobotClient, createRobotQuery, useMachineStatus } from '@viamrobotics/svelte-sdk';
|
|
3
|
+
import { WorldObject } from '../WorldObject';
|
|
4
|
+
import { useRefreshRates } from './useRefreshRates.svelte';
|
|
5
|
+
import { observe } from '@threlte/core';
|
|
6
|
+
const key = Symbol('frames-context');
|
|
7
|
+
export const provideFrames = (partID) => {
|
|
8
|
+
const refreshRates = useRefreshRates();
|
|
9
|
+
if (!refreshRates.has('Frames')) {
|
|
10
|
+
refreshRates.set('Frames', 1);
|
|
11
|
+
}
|
|
12
|
+
const client = useRobotClient(partID);
|
|
13
|
+
const query = createRobotQuery(client, 'frameSystemConfig');
|
|
14
|
+
const machineStatus = useMachineStatus(partID);
|
|
15
|
+
const revision = $derived(machineStatus.current?.config.revision);
|
|
16
|
+
const shouldFetch = $derived(refreshRates.get('Frames') === 1);
|
|
17
|
+
observe.pre(() => [revision], () => {
|
|
18
|
+
if (shouldFetch) {
|
|
19
|
+
untrack(() => query.current).refetch();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const current = $derived.by(() => {
|
|
23
|
+
const objects = [];
|
|
24
|
+
if (!shouldFetch) {
|
|
25
|
+
return objects;
|
|
26
|
+
}
|
|
27
|
+
for (const { frame } of query.current.data ?? []) {
|
|
28
|
+
if (frame) {
|
|
29
|
+
objects.push(new WorldObject(frame.referenceFrame, frame.poseInObserverFrame?.pose, frame.poseInObserverFrame?.referenceFrame, frame.physicalObject?.geometryType));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return objects;
|
|
33
|
+
});
|
|
34
|
+
const error = $derived(query.current.error ?? undefined);
|
|
35
|
+
const fetching = $derived(query.current.isFetching);
|
|
36
|
+
setContext(key, {
|
|
37
|
+
get current() {
|
|
38
|
+
return current;
|
|
39
|
+
},
|
|
40
|
+
get error() {
|
|
41
|
+
return error;
|
|
42
|
+
},
|
|
43
|
+
get fetching() {
|
|
44
|
+
return fetching;
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
export const useFrames = () => {
|
|
49
|
+
return getContext(key);
|
|
50
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ArmClient, CameraClient, Geometry } from '@viamrobotics/sdk';
|
|
2
|
+
import { createQueries, queryOptions } from '@tanstack/svelte-query';
|
|
3
|
+
import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
4
|
+
import { setContext, getContext } from 'svelte';
|
|
5
|
+
import { fromStore, toStore } from 'svelte/store';
|
|
6
|
+
import { useRefreshRates } from './useRefreshRates.svelte';
|
|
7
|
+
import { WorldObject } from '../WorldObject';
|
|
8
|
+
import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
|
|
9
|
+
const key = Symbol('geometries-context');
|
|
10
|
+
export const provideGeometries = (partID) => {
|
|
11
|
+
const refreshRates = useRefreshRates();
|
|
12
|
+
const arms = useResourceNames(partID, 'arm');
|
|
13
|
+
const cameras = useResourceNames(partID, 'camera');
|
|
14
|
+
const clients = $derived([
|
|
15
|
+
...arms.current.map((arm) => createResourceClient(ArmClient, partID, () => arm.name)),
|
|
16
|
+
...cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)),
|
|
17
|
+
]);
|
|
18
|
+
if (!refreshRates.has('Geometries')) {
|
|
19
|
+
refreshRates.set('Geometries', 1000);
|
|
20
|
+
}
|
|
21
|
+
const options = $derived(clients.map((client) => {
|
|
22
|
+
const interval = refreshRates.get('Geometries');
|
|
23
|
+
return queryOptions({
|
|
24
|
+
enabled: interval !== -1 && client.current !== undefined,
|
|
25
|
+
refetchInterval: interval === 0 ? false : interval,
|
|
26
|
+
queryKey: ['partID', partID(), client.current?.name, 'getGeometries'],
|
|
27
|
+
queryFn: async () => {
|
|
28
|
+
if (!client.current) {
|
|
29
|
+
throw new Error('No client');
|
|
30
|
+
}
|
|
31
|
+
const geometries = await client.current.getGeometries();
|
|
32
|
+
return { name: client.current.name, geometries };
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}));
|
|
36
|
+
const { updateUUIDs } = usePersistentUUIDs();
|
|
37
|
+
const queries = fromStore(createQueries({ queries: toStore(() => options) }));
|
|
38
|
+
const geometries = $derived.by(() => {
|
|
39
|
+
const results = [];
|
|
40
|
+
for (const query of queries.current) {
|
|
41
|
+
if (!query.data)
|
|
42
|
+
continue;
|
|
43
|
+
for (const { center, label, geometryType } of query.data.geometries) {
|
|
44
|
+
results.push(new WorldObject(label, center, query.data.name, geometryType));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
updateUUIDs(results);
|
|
48
|
+
return results;
|
|
49
|
+
});
|
|
50
|
+
setContext(key, {
|
|
51
|
+
get current() {
|
|
52
|
+
return geometries;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export const useGeometries = () => {
|
|
57
|
+
return getContext(key);
|
|
58
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
const key = Symbol('motion-client-context');
|
|
4
|
+
export const provideMotionClient = (partID) => {
|
|
5
|
+
const motionResources = useResourceNames(partID, 'motion');
|
|
6
|
+
const motionNames = $derived(motionResources.current.map((resource) => resource.name));
|
|
7
|
+
let current = $state();
|
|
8
|
+
$effect.pre(() => {
|
|
9
|
+
if (current) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (motionNames.includes('builtin')) {
|
|
13
|
+
current = 'builtin';
|
|
14
|
+
}
|
|
15
|
+
current = motionNames[0];
|
|
16
|
+
});
|
|
17
|
+
setContext(key, {
|
|
18
|
+
get names() {
|
|
19
|
+
return motionNames;
|
|
20
|
+
},
|
|
21
|
+
get current() {
|
|
22
|
+
return current;
|
|
23
|
+
},
|
|
24
|
+
set(value) {
|
|
25
|
+
current = value;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
export const useMotionClient = () => {
|
|
30
|
+
return getContext(key);
|
|
31
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type IntersectionEvent } from '@threlte/extras';
|
|
2
|
+
export declare const useObjectEvents: (uuid: () => string) => {
|
|
3
|
+
readonly visible: boolean | undefined;
|
|
4
|
+
onpointerenter: (event: IntersectionEvent<MouseEvent>) => void;
|
|
5
|
+
onpointerleave: (event: IntersectionEvent<MouseEvent>) => void;
|
|
6
|
+
ondblclick: (event: IntersectionEvent<MouseEvent>) => void;
|
|
7
|
+
onclick: (event: IntersectionEvent<MouseEvent>) => void;
|
|
8
|
+
onpointermissed: () => void;
|
|
9
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useCursor } from '@threlte/extras';
|
|
2
|
+
import { useFocused, useSelected } from './useSelection.svelte';
|
|
3
|
+
import { useVisibility } from './useVisibility.svelte';
|
|
4
|
+
export const useObjectEvents = (uuid) => {
|
|
5
|
+
const { onPointerEnter, onPointerLeave } = useCursor();
|
|
6
|
+
const selected = useSelected();
|
|
7
|
+
const focused = useFocused();
|
|
8
|
+
const visibility = useVisibility();
|
|
9
|
+
return {
|
|
10
|
+
get visible() {
|
|
11
|
+
return visibility.get(uuid());
|
|
12
|
+
},
|
|
13
|
+
onpointerenter: (event) => {
|
|
14
|
+
event.stopPropagation();
|
|
15
|
+
onPointerEnter();
|
|
16
|
+
},
|
|
17
|
+
onpointerleave: (event) => {
|
|
18
|
+
event.stopPropagation();
|
|
19
|
+
onPointerLeave();
|
|
20
|
+
},
|
|
21
|
+
ondblclick: (event) => {
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
focused.set(uuid());
|
|
24
|
+
},
|
|
25
|
+
onclick: (event) => {
|
|
26
|
+
event.stopPropagation();
|
|
27
|
+
selected.set(uuid());
|
|
28
|
+
},
|
|
29
|
+
onpointermissed: () => selected.set(),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
import { useFrames } from './useFrames.svelte';
|
|
3
|
+
import { useGeometries } from './useGeometries.svelte';
|
|
4
|
+
import { useStaticGeometries } from './useStaticGeometries.svelte';
|
|
5
|
+
import { useShapes } from './useShapes.svelte';
|
|
6
|
+
import { usePointClouds } from './usePointclouds.svelte';
|
|
7
|
+
const key = Symbol('objects-context');
|
|
8
|
+
export const provideObjects = () => {
|
|
9
|
+
const frames = useFrames();
|
|
10
|
+
const geometries = useGeometries();
|
|
11
|
+
const statics = useStaticGeometries();
|
|
12
|
+
const shapes = useShapes();
|
|
13
|
+
const points = usePointClouds();
|
|
14
|
+
const objects = $derived([
|
|
15
|
+
...frames.current,
|
|
16
|
+
...geometries.current,
|
|
17
|
+
...points.current,
|
|
18
|
+
...shapes.meshes,
|
|
19
|
+
...shapes.models,
|
|
20
|
+
...shapes.nurbs,
|
|
21
|
+
...shapes.points,
|
|
22
|
+
...statics.current,
|
|
23
|
+
...shapes.poses,
|
|
24
|
+
]);
|
|
25
|
+
setContext(key, {
|
|
26
|
+
get current() {
|
|
27
|
+
return objects;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
export const useObjects = () => {
|
|
32
|
+
return getContext(key);
|
|
33
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const key = Symbol('part-id-context');
|
|
3
|
+
export const createPartIDContext = (partId) => {
|
|
4
|
+
const context = {
|
|
5
|
+
get current() {
|
|
6
|
+
return partId();
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
setContext(key, context);
|
|
10
|
+
return context;
|
|
11
|
+
};
|
|
12
|
+
export const usePartID = () => {
|
|
13
|
+
return getContext(key);
|
|
14
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const usePersistentUUIDs = () => {
|
|
2
|
+
const uuids = new Map();
|
|
3
|
+
const updateUUIDs = (objects) => {
|
|
4
|
+
if (uuids.size === 0) {
|
|
5
|
+
for (const object of objects) {
|
|
6
|
+
uuids.set(object.name, object.uuid);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
for (const object of objects) {
|
|
10
|
+
object.uuid = uuids.get(object.name) ?? object.uuid;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
return { uuids, updateUUIDs };
|
|
14
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { WorldObject, type PointsGeometry } from '../WorldObject';
|
|
2
|
+
interface Context {
|
|
3
|
+
current: WorldObject<PointsGeometry>[];
|
|
4
|
+
}
|
|
5
|
+
export declare const providePointclouds: (partID: () => string) => void;
|
|
6
|
+
export declare const usePointClouds: () => Context;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createQueries, queryOptions } from '@tanstack/svelte-query';
|
|
2
|
+
import { CameraClient } from '@viamrobotics/sdk';
|
|
3
|
+
import { setContext, getContext } from 'svelte';
|
|
4
|
+
import { fromStore, toStore } from 'svelte/store';
|
|
5
|
+
import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
6
|
+
import { parsePCD } from '../loaders/pcd';
|
|
7
|
+
import { useRefreshRates } from './useRefreshRates.svelte';
|
|
8
|
+
import { WorldObject } from '../WorldObject';
|
|
9
|
+
import { usePersistentUUIDs } from './usePersistentUUIDs.svelte';
|
|
10
|
+
const key = Symbol('pointcloud-context');
|
|
11
|
+
export const providePointclouds = (partID) => {
|
|
12
|
+
const refreshRates = useRefreshRates();
|
|
13
|
+
const cameras = useResourceNames(partID, 'camera');
|
|
14
|
+
if (!refreshRates.has('Pointclouds')) {
|
|
15
|
+
refreshRates.set('Pointclouds', 5000);
|
|
16
|
+
}
|
|
17
|
+
const clients = $derived(cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)));
|
|
18
|
+
const options = $derived(clients.map((cameraClient) => {
|
|
19
|
+
const name = cameraClient.current?.name ?? '';
|
|
20
|
+
const interval = refreshRates.get('Pointclouds');
|
|
21
|
+
return queryOptions({
|
|
22
|
+
enabled: interval !== -1 && cameraClient.current !== undefined,
|
|
23
|
+
refetchInterval: interval === 0 ? false : interval,
|
|
24
|
+
queryKey: ['partID', partID(), name, 'getPointCloud'],
|
|
25
|
+
queryFn: async () => {
|
|
26
|
+
if (!cameraClient.current) {
|
|
27
|
+
throw new Error('No camera client');
|
|
28
|
+
}
|
|
29
|
+
const response = await cameraClient.current.getPointCloud();
|
|
30
|
+
if (!response)
|
|
31
|
+
return null;
|
|
32
|
+
const { positions, colors } = await parsePCD(new Uint8Array(response));
|
|
33
|
+
return new WorldObject(`${name}:pointcloud`, undefined, name, { case: 'points', value: new Float32Array(positions) }, colors ? { colors: new Float32Array(colors) } : undefined);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}));
|
|
37
|
+
const { updateUUIDs } = usePersistentUUIDs();
|
|
38
|
+
const queries = fromStore(createQueries({
|
|
39
|
+
queries: toStore(() => options),
|
|
40
|
+
combine: (results) => {
|
|
41
|
+
const data = results
|
|
42
|
+
.flatMap((result) => result.data)
|
|
43
|
+
.filter((data) => data !== null && data !== undefined);
|
|
44
|
+
updateUUIDs(data);
|
|
45
|
+
return {
|
|
46
|
+
data,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
setContext(key, {
|
|
51
|
+
get current() {
|
|
52
|
+
return queries.current.data;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export const usePointClouds = () => {
|
|
57
|
+
return getContext(key);
|
|
58
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
2
|
+
import { usePartID } from './usePartID.svelte';
|
|
3
|
+
import { MotionClient } from '@viamrobotics/sdk';
|
|
4
|
+
import { createQuery, queryOptions } from '@tanstack/svelte-query';
|
|
5
|
+
import { useRefreshRates } from './useRefreshRates.svelte';
|
|
6
|
+
import { fromStore, toStore } from 'svelte/store';
|
|
7
|
+
import { useMotionClient } from './useMotionClient.svelte';
|
|
8
|
+
export const usePose = (name, parent) => {
|
|
9
|
+
const refreshRates = useRefreshRates();
|
|
10
|
+
const partID = usePartID();
|
|
11
|
+
const motionClient = useMotionClient();
|
|
12
|
+
const resources = useResourceNames(() => partID.current);
|
|
13
|
+
const resource = $derived(resources.current.find((resource) => resource.name === name()));
|
|
14
|
+
const client = createResourceClient(MotionClient, () => partID.current, () => motionClient.current ?? '');
|
|
15
|
+
const interval = refreshRates.get('Poses');
|
|
16
|
+
const options = $derived(queryOptions({
|
|
17
|
+
enabled: interval !== -1 && client.current !== undefined && resource !== undefined,
|
|
18
|
+
refetchInterval: interval === 0 ? false : interval,
|
|
19
|
+
queryKey: [
|
|
20
|
+
'partID',
|
|
21
|
+
partID.current,
|
|
22
|
+
client.current?.name,
|
|
23
|
+
'getPose',
|
|
24
|
+
resource?.name,
|
|
25
|
+
parent(),
|
|
26
|
+
],
|
|
27
|
+
queryFn: async () => {
|
|
28
|
+
if (!client.current || !resource) {
|
|
29
|
+
throw new Error('No client');
|
|
30
|
+
}
|
|
31
|
+
const pose = await client.current.getPose(resource, parent() ?? 'world', []);
|
|
32
|
+
return pose;
|
|
33
|
+
},
|
|
34
|
+
}));
|
|
35
|
+
const query = fromStore(createQuery(toStore(() => options)));
|
|
36
|
+
return {
|
|
37
|
+
get current() {
|
|
38
|
+
if (resource?.subtype === 'arm') {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
return query.current.data?.pose;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PoseInFrame, ResourceName } from '@viamrobotics/sdk';
|
|
2
|
+
type PoseWithComponent = PoseInFrame & {
|
|
3
|
+
component: ResourceName;
|
|
4
|
+
};
|
|
5
|
+
interface Context {
|
|
6
|
+
current: {
|
|
7
|
+
[k: string]: PoseWithComponent | undefined;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare const providePoses: (partID: () => string) => void;
|
|
11
|
+
export declare const usePoses: () => Context;
|
|
12
|
+
export {};
|