@viamrobotics/motion-tools 1.13.1 → 1.15.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/FrameConfigUpdater.svelte.d.ts +2 -2
- package/dist/HoverUpdater.svelte.d.ts +1 -1
- package/dist/attribute.js +11 -3
- package/dist/buffer.d.ts +56 -7
- package/dist/buffer.js +70 -12
- package/dist/color.d.ts +1 -1
- package/dist/color.js +2 -2
- package/dist/components/App.svelte +25 -21
- package/dist/components/App.svelte.d.ts +1 -1
- package/dist/components/BatchedArrows.svelte +5 -3
- package/dist/components/Camera.svelte +1 -0
- package/dist/components/CameraControls.svelte +5 -3
- package/dist/components/Entities/Arrows/ArrowGroups.svelte +6 -3
- package/dist/components/Entities/Arrows/Arrows.svelte +6 -3
- package/dist/components/Entities/Entities.svelte +9 -7
- package/dist/components/Entities/Frame.svelte +48 -48
- package/dist/components/Entities/Frame.svelte.d.ts +3 -2
- package/dist/components/Entities/GLTF.svelte +8 -5
- package/dist/components/Entities/GLTF.svelte.d.ts +2 -2
- package/dist/components/Entities/Geometry.svelte +45 -173
- package/dist/components/Entities/Geometry.svelte.d.ts +5 -14
- package/dist/components/Entities/Line.svelte +69 -19
- package/dist/components/Entities/Line.svelte.d.ts +1 -1
- package/dist/components/Entities/LineDots.svelte +1 -1
- package/dist/components/Entities/LineGeometry.svelte +1 -1
- package/dist/components/Entities/Mesh.svelte +133 -0
- package/dist/components/Entities/Mesh.svelte.d.ts +4 -0
- package/dist/components/Entities/Points.svelte +9 -6
- package/dist/components/Entities/Points.svelte.d.ts +2 -2
- package/dist/components/Entities/Pose.svelte +4 -3
- package/dist/components/Entities/hooks/useEntityEvents.svelte.d.ts +1 -1
- package/dist/components/Entities/hooks/useEntityEvents.svelte.js +2 -2
- package/dist/components/FileDrop/FileDrop.svelte +10 -6
- package/dist/components/FileDrop/file-dropper.d.ts +1 -1
- package/dist/components/FileDrop/pcd-dropper.js +1 -1
- package/dist/components/FileDrop/ply-dropper.js +1 -1
- package/dist/components/FileDrop/snapshot-dropper.js +1 -1
- package/dist/components/Focus.svelte +4 -2
- package/dist/components/KeyboardControls.svelte +4 -2
- package/dist/components/Lasso/Debug.svelte +5 -2
- package/dist/components/Lasso/Lasso.svelte +9 -6
- package/dist/components/Lasso/Tool.svelte +10 -7
- package/dist/components/MeasureTool/MeasurePoint.svelte +2 -1
- package/dist/components/MeasureTool/MeasurePoint.svelte.d.ts +1 -1
- package/dist/components/MeasureTool/MeasureTool.svelte +7 -5
- package/dist/components/PCD.svelte +4 -3
- package/dist/components/PointerMissBox.svelte +3 -2
- package/dist/components/Scene.svelte +12 -9
- package/dist/components/SceneProviders.svelte +20 -18
- package/dist/components/Selected.svelte +7 -3
- package/dist/components/Snapshot.svelte +8 -5
- package/dist/components/StaticGeometries.svelte +10 -7
- package/dist/components/hover/HoveredEntities.svelte +2 -1
- package/dist/components/hover/HoveredEntity.svelte +2 -1
- package/dist/components/hover/HoveredEntityTooltip.svelte +1 -0
- package/dist/components/hover/LinkedHoveredEntity.svelte +7 -5
- package/dist/components/overlay/AddRelationship.svelte +4 -2
- package/dist/components/overlay/Details.svelte +21 -19
- package/dist/components/overlay/FloatingPanel.svelte +40 -3
- package/dist/components/overlay/FloatingPanel.svelte.d.ts +1 -0
- package/dist/components/overlay/LiveUpdatesBanner.svelte +1 -0
- package/dist/components/overlay/Logs.svelte +4 -2
- package/dist/components/overlay/Popover.svelte +3 -2
- package/dist/components/overlay/RefreshRate.svelte +4 -2
- package/dist/components/overlay/dashboard/Button.svelte +2 -1
- package/dist/components/overlay/dashboard/Button.svelte.d.ts +1 -1
- package/dist/components/overlay/dashboard/Dashboard.svelte +3 -1
- package/dist/components/overlay/left-pane/AddFrames.svelte +4 -2
- package/dist/components/overlay/left-pane/Drawer.svelte +3 -2
- package/dist/components/overlay/left-pane/Tree.svelte +6 -12
- package/dist/components/overlay/left-pane/TreeContainer.svelte +33 -50
- package/dist/components/overlay/left-pane/TreeContainer.svelte.d.ts +1 -1
- package/dist/components/overlay/left-pane/buildTree.js +15 -0
- package/dist/components/overlay/settings/Settings.svelte +37 -10
- package/dist/components/overlay/settings/Tabs.svelte +2 -1
- package/dist/components/overlay/widgets/ArmPositions.svelte +3 -2
- package/dist/components/overlay/widgets/Camera.svelte +6 -5
- package/dist/components/weblab/WeblabActive.svelte +2 -1
- package/dist/components/xr/ArmTeleop.svelte +7 -6
- package/dist/components/xr/BentPlaneGeometry.svelte +3 -2
- package/dist/components/xr/CameraFeed.svelte +2 -0
- package/dist/components/xr/Controllers.svelte +5 -3
- package/dist/components/xr/Draggable.svelte +4 -3
- package/dist/components/xr/HandCollider.svelte +2 -1
- package/dist/components/xr/JointLimitsWidget.svelte +1 -0
- package/dist/components/xr/OriginMarker.svelte +2 -1
- package/dist/components/xr/PointDistance.svelte +3 -2
- package/dist/components/xr/XR.svelte +8 -6
- package/dist/components/xr/XRConfigPanel.svelte +4 -3
- package/dist/components/xr/XRControllerSettings.svelte +2 -1
- package/dist/components/xr/XRToast.svelte +4 -3
- package/dist/ecs/traits.d.ts +3 -20
- package/dist/ecs/traits.js +34 -7
- package/dist/ecs/useQuery.svelte.js +1 -1
- package/dist/frame.js +1 -1
- package/dist/hooks/use3DModels.svelte.js +4 -6
- package/dist/hooks/useConfigFrames.svelte.js +3 -3
- package/dist/hooks/useDrawAPI.svelte.js +9 -9
- package/dist/hooks/useFramelessComponents.svelte.js +1 -1
- package/dist/hooks/useFrames.svelte.js +18 -19
- package/dist/hooks/useGeometries.svelte.js +66 -43
- package/dist/hooks/useMouseRaycaster.svelte.d.ts +1 -1
- package/dist/hooks/useMouseRaycaster.svelte.js +1 -1
- package/dist/hooks/usePartConfig.svelte.d.ts +1 -1
- package/dist/hooks/usePartConfig.svelte.js +3 -3
- package/dist/hooks/usePointcloudObjects.svelte.js +108 -63
- package/dist/hooks/usePointclouds.svelte.js +53 -33
- package/dist/hooks/usePose.svelte.js +7 -7
- package/dist/hooks/useSelection.svelte.d.ts +1 -1
- package/dist/hooks/useWeblabs.svelte.d.ts +1 -0
- package/dist/hooks/useWeblabs.svelte.js +15 -3
- package/dist/hooks/useWorldState.svelte.js +31 -31
- package/dist/metadata.d.ts +22 -0
- package/dist/metadata.js +66 -0
- package/dist/plugins/bvh.svelte.js +2 -2
- package/dist/snapshot.d.ts +22 -2
- package/dist/snapshot.js +67 -25
- package/dist/three/BatchedArrow.d.ts +1 -1
- package/dist/three/BatchedArrow.js +1 -1
- package/dist/three/InstancedArrows/InstancedArrows.d.ts +1 -1
- package/dist/three/InstancedArrows/InstancedArrows.js +3 -3
- package/dist/three/InstancedArrows/box.js +1 -1
- package/dist/three/InstancedArrows/geometry.js +1 -1
- package/dist/three/InstancedArrows/raycast.d.ts +1 -1
- package/dist/three/InstancedArrows/raycast.js +1 -1
- package/dist/three/OBBHelper.d.ts +3 -2
- package/dist/three/OBBHelper.js +17 -5
- package/dist/three/OrientationVector.js +1 -1
- package/dist/transform.js +1 -1
- package/package.json +3 -2
- package/dist/WorldObject.svelte.d.ts +0 -27
- package/dist/WorldObject.svelte.js +0 -127
- package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte +0 -41
- package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte.d.ts +0 -6
- package/dist/hooks/useResizable.svelte.d.ts +0 -12
- package/dist/hooks/useResizable.svelte.js +0 -46
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { createQuery, $internal as internal } from 'koota';
|
|
1
2
|
import { untrack } from 'svelte';
|
|
2
|
-
import { $internal as internal, createQuery } from 'koota';
|
|
3
3
|
import { useWorld } from './useWorld';
|
|
4
4
|
export function useQuery(...parameters) {
|
|
5
5
|
const world = useWorld();
|
package/dist/frame.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// TODO: replace with types exported from the sdk when created
|
|
2
2
|
import { UuidTool } from 'uuid-tool';
|
|
3
|
-
import { createPoseFromFrame } from './transform';
|
|
4
3
|
import { createGeometryFromFrame } from './geometry';
|
|
4
|
+
import { createPoseFromFrame } from './transform';
|
|
5
5
|
export const createFrame = (geometry) => {
|
|
6
6
|
return {
|
|
7
7
|
parent: 'world',
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { isInstanceOf } from '@threlte/core';
|
|
1
2
|
import { ArmClient } from '@viamrobotics/sdk';
|
|
2
3
|
import { createResourceClient, useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
3
4
|
import { getContext, setContext } from 'svelte';
|
|
4
|
-
import { useSettings } from './useSettings.svelte';
|
|
5
|
-
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
6
5
|
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
|
|
7
|
-
import {
|
|
6
|
+
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
7
|
+
import { useSettings } from './useSettings.svelte';
|
|
8
8
|
const gltfLoader = new GLTFLoader();
|
|
9
9
|
const dracoLoader = new DRACOLoader();
|
|
10
10
|
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
|
|
@@ -57,9 +57,7 @@ export const provide3DModels = (partID) => {
|
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
$effect(() => {
|
|
60
|
-
const shouldFetchModels = settings.current.isLoaded &&
|
|
61
|
-
(settings.current.renderArmModels === 'model' ||
|
|
62
|
-
settings.current.renderArmModels === 'colliders+model');
|
|
60
|
+
const shouldFetchModels = settings.current.isLoaded && settings.current.renderArmModels.includes('model');
|
|
63
61
|
if (shouldFetchModels) {
|
|
64
62
|
fetch3DModels();
|
|
65
63
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useEnvironment } from './useEnvironment.svelte';
|
|
2
|
-
import { usePartConfig } from './usePartConfig.svelte';
|
|
3
|
-
import { createTransformFromFrame } from '../frame';
|
|
4
1
|
import { Transform } from '@viamrobotics/sdk';
|
|
5
2
|
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { createTransformFromFrame } from '../frame';
|
|
4
|
+
import { useEnvironment } from './useEnvironment.svelte';
|
|
5
|
+
import { usePartConfig } from './usePartConfig.svelte';
|
|
6
6
|
const key = Symbol('config-frames-context');
|
|
7
7
|
export const provideConfigFrames = () => {
|
|
8
8
|
const environment = useEnvironment();
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
import { useThrelte } from '@threlte/core';
|
|
2
|
+
import {} from 'koota';
|
|
1
3
|
import { getContext, setContext } from 'svelte';
|
|
2
4
|
import { Color, Vector3, Vector4 } from 'three';
|
|
3
5
|
import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
|
|
4
|
-
import { UuidTool } from 'uuid-tool';
|
|
5
6
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
7
|
+
import { UuidTool } from 'uuid-tool';
|
|
8
|
+
import { createBufferGeometry, updateBufferGeometry } from '../attribute';
|
|
9
|
+
import { STRIDE } from '../buffer';
|
|
10
|
+
import { traits, useWorld } from '../ecs';
|
|
11
|
+
import { createBox, createCapsule, createSphere } from '../geometry';
|
|
12
|
+
import { parsePlyInput } from '../ply';
|
|
6
13
|
import { createPose, createPoseFromFrame } from '../transform';
|
|
7
14
|
import { useCameraControls } from './useControls.svelte';
|
|
8
|
-
import { useWorld, traits } from '../ecs';
|
|
9
|
-
import { useThrelte } from '@threlte/core';
|
|
10
|
-
import {} from 'koota';
|
|
11
|
-
import { parsePlyInput } from '../ply';
|
|
12
|
-
import { useLogs } from './useLogs.svelte';
|
|
13
|
-
import { createBox, createCapsule, createSphere } from '../geometry';
|
|
14
15
|
import { useDrawConnectionConfig } from './useDrawConnectionConfig.svelte';
|
|
15
|
-
import {
|
|
16
|
-
import { STRIDE } from '../buffer';
|
|
16
|
+
import { useLogs } from './useLogs.svelte';
|
|
17
17
|
const colorUtil = new Color();
|
|
18
18
|
const bufferTypes = {
|
|
19
19
|
DRAW_POINTS: 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
|
-
import { usePartConfig } from './usePartConfig.svelte';
|
|
3
2
|
import { useFrames } from './useFrames.svelte';
|
|
3
|
+
import { usePartConfig } from './usePartConfig.svelte';
|
|
4
4
|
const key = Symbol('frameless-components-context');
|
|
5
5
|
export const provideFramelessComponents = () => {
|
|
6
6
|
const partConfig = usePartConfig();
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { getContext, setContext, untrack } from 'svelte';
|
|
2
1
|
import { MachineConnectionEvent, Transform } from '@viamrobotics/sdk';
|
|
3
|
-
import {
|
|
2
|
+
import { createRobotQuery, useConnectionStatus, useMachineStatus, useRobotClient, } from '@viamrobotics/svelte-sdk';
|
|
4
3
|
import {} from 'koota';
|
|
5
|
-
import {
|
|
4
|
+
import { getContext, setContext, untrack } from 'svelte';
|
|
6
5
|
import { resourceNameToColor } from '../color';
|
|
7
|
-
import { useEnvironment } from './useEnvironment.svelte';
|
|
8
|
-
import { createPose } from '../transform';
|
|
9
|
-
import { useResourceByName } from './useResourceByName.svelte';
|
|
10
6
|
import { traits, useWorld } from '../ecs';
|
|
7
|
+
import { updateGeometryTrait } from '../ecs/traits';
|
|
8
|
+
import { createPose } from '../transform';
|
|
11
9
|
import { useConfigFrames } from './useConfigFrames.svelte';
|
|
10
|
+
import { useEnvironment } from './useEnvironment.svelte';
|
|
11
|
+
import { useLogs } from './useLogs.svelte';
|
|
12
|
+
import { useResourceByName } from './useResourceByName.svelte';
|
|
12
13
|
const key = Symbol('frames-context');
|
|
13
14
|
export const provideFrames = (partID) => {
|
|
14
15
|
const configFrames = useConfigFrames();
|
|
@@ -69,15 +70,17 @@ export const provideFrames = (partID) => {
|
|
|
69
70
|
}
|
|
70
71
|
});
|
|
71
72
|
$effect.pre(() => {
|
|
72
|
-
if (current.length === 0)
|
|
73
|
-
return;
|
|
74
73
|
const currentResourcesByName = resourceByName.current;
|
|
74
|
+
const currentPartID = partID();
|
|
75
75
|
// We only want to update whenever "current" or "resourceByName.current" changes
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
77
|
+
current.length;
|
|
76
78
|
untrack(() => {
|
|
77
79
|
const active = {};
|
|
78
80
|
for (const frame of current) {
|
|
79
81
|
const name = frame.referenceFrame;
|
|
80
|
-
|
|
82
|
+
const entityKey = `${currentPartID}:${name}`;
|
|
83
|
+
active[entityKey] = true;
|
|
81
84
|
const parent = frame.poseInObserverFrame?.referenceFrame;
|
|
82
85
|
const pose = createPose(frame.poseInObserverFrame?.pose);
|
|
83
86
|
const center = frame.physicalObject?.center
|
|
@@ -85,7 +88,7 @@ export const provideFrames = (partID) => {
|
|
|
85
88
|
: undefined;
|
|
86
89
|
const resourceName = currentResourcesByName[frame.referenceFrame];
|
|
87
90
|
const color = resourceNameToColor(resourceName);
|
|
88
|
-
const existing = entities.get(
|
|
91
|
+
const existing = entities.get(entityKey);
|
|
89
92
|
if (existing) {
|
|
90
93
|
if (!parent || parent === 'world') {
|
|
91
94
|
existing.remove(traits.Parent);
|
|
@@ -102,11 +105,7 @@ export const provideFrames = (partID) => {
|
|
|
102
105
|
if (center) {
|
|
103
106
|
existing.set(traits.Center, center);
|
|
104
107
|
}
|
|
105
|
-
existing
|
|
106
|
-
if (frame.physicalObject) {
|
|
107
|
-
const geometry = traits.Geometry(frame.physicalObject);
|
|
108
|
-
existing.add(geometry);
|
|
109
|
-
}
|
|
108
|
+
updateGeometryTrait(existing, frame.physicalObject);
|
|
110
109
|
existing.set(traits.EditedPose, pose);
|
|
111
110
|
continue;
|
|
112
111
|
}
|
|
@@ -130,13 +129,13 @@ export const provideFrames = (partID) => {
|
|
|
130
129
|
entityTraits.push(traits.Geometry(frame.physicalObject));
|
|
131
130
|
}
|
|
132
131
|
const entity = world.spawn(...entityTraits);
|
|
133
|
-
entities.set(
|
|
132
|
+
entities.set(entityKey, entity);
|
|
134
133
|
}
|
|
135
134
|
// Clean up non-active entities
|
|
136
|
-
for (const [
|
|
137
|
-
if (!active[
|
|
135
|
+
for (const [entityKey, entity] of entities) {
|
|
136
|
+
if (!active[entityKey]) {
|
|
138
137
|
entity?.destroy();
|
|
139
|
-
entities.delete(
|
|
138
|
+
entities.delete(entityKey);
|
|
140
139
|
continue;
|
|
141
140
|
}
|
|
142
141
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { ArmClient, CameraClient, GantryClient, GripperClient } from '@viamrobotics/sdk';
|
|
2
|
-
import { untrack, setContext, getContext } from 'svelte';
|
|
3
|
-
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
4
2
|
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import {} from 'koota';
|
|
4
|
+
import { getContext, setContext, untrack } from 'svelte';
|
|
7
5
|
import { Color } from 'three';
|
|
8
|
-
import {
|
|
6
|
+
import { resourceColors } from '../color';
|
|
7
|
+
import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
|
|
9
8
|
import { traits, useWorld } from '../ecs';
|
|
10
|
-
import {} from '
|
|
9
|
+
import { updateGeometryTrait } from '../ecs/traits';
|
|
11
10
|
import { createPose } from '../transform';
|
|
12
|
-
import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
|
|
13
11
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
12
|
+
import { useLogs } from './useLogs.svelte';
|
|
13
|
+
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
14
|
+
import { useResourceByName } from './useResourceByName.svelte';
|
|
14
15
|
const key = Symbol('geometries-context');
|
|
15
16
|
const colorUtil = new Color();
|
|
16
17
|
export const provideGeometries = (partID) => {
|
|
@@ -39,6 +40,7 @@ export const provideGeometries = (partID) => {
|
|
|
39
40
|
const gripperQueries = $derived(gripperClients.map((client) => [client.current?.name, createResourceQuery(client, 'getGeometries', () => options)]));
|
|
40
41
|
const cameraQueries = $derived(cameraClients.map((client) => [client.current?.name, createResourceQuery(client, 'getGeometries', () => options)]));
|
|
41
42
|
const gantryQueries = $derived(gantryClients.map((client) => [client.current?.name, createResourceQuery(client, 'getGeometries', () => options)]));
|
|
43
|
+
const queries = $derived([...armQueries, ...gripperQueries, ...cameraQueries, ...gantryQueries]);
|
|
42
44
|
$effect(() => {
|
|
43
45
|
if (interval === RefetchRates.FPS_30 || interval === RefetchRates.FPS_60) {
|
|
44
46
|
return logs.add(`Fetching geometries every ${interval}ms...`);
|
|
@@ -56,49 +58,70 @@ export const provideGeometries = (partID) => {
|
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
60
|
});
|
|
59
|
-
const queries = $derived([...armQueries, ...gripperQueries, ...cameraQueries, ...gantryQueries]);
|
|
60
61
|
const entities = new Map();
|
|
62
|
+
const queryEntityKeys = new Map();
|
|
61
63
|
$effect(() => {
|
|
62
|
-
const
|
|
64
|
+
const activeQueryKeys = new Set();
|
|
65
|
+
const currentPartID = partID();
|
|
63
66
|
for (const [name, query] of queries) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
67
|
+
if (!name) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const queryKey = `${currentPartID}:${name}`;
|
|
71
|
+
activeQueryKeys.add(queryKey);
|
|
72
|
+
$effect(() => {
|
|
73
|
+
const nextKeys = new Set();
|
|
74
|
+
const resourceName = resources.current[name];
|
|
75
|
+
const subtype = resourceName?.subtype;
|
|
76
|
+
if (query.data) {
|
|
77
|
+
let index = 0;
|
|
78
|
+
for (const geometry of query.data) {
|
|
79
|
+
index += 1;
|
|
80
|
+
const label = geometry.label || `${name} geometry ${index}`;
|
|
81
|
+
const entityKey = `${currentPartID}:${name}:${label}`;
|
|
82
|
+
nextKeys.add(entityKey);
|
|
83
|
+
const center = createPose(geometry.center);
|
|
84
|
+
const existing = entities.get(entityKey);
|
|
85
|
+
if (existing) {
|
|
86
|
+
existing.set(traits.Center, center);
|
|
87
|
+
updateGeometryTrait(existing, geometry);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const entityTraits = [
|
|
91
|
+
traits.Parent(name),
|
|
92
|
+
traits.Name(label),
|
|
93
|
+
traits.Center(center),
|
|
94
|
+
traits.GeometriesAPI,
|
|
95
|
+
traits.Geometry(geometry),
|
|
96
|
+
];
|
|
97
|
+
if (subtype) {
|
|
98
|
+
entityTraits.push(traits.Color(subtype ? colorUtil.set(resourceColors[subtype]) : undefined));
|
|
92
99
|
}
|
|
100
|
+
const entity = world.spawn(...entityTraits);
|
|
101
|
+
entities.set(entityKey, entity);
|
|
93
102
|
}
|
|
94
|
-
}
|
|
103
|
+
}
|
|
104
|
+
const prevKeys = queryEntityKeys.get(queryKey) ?? new Set();
|
|
105
|
+
// Remove entities no longer present for this specific query
|
|
106
|
+
for (const key of prevKeys) {
|
|
107
|
+
if (!nextKeys.has(key)) {
|
|
108
|
+
entities.get(key)?.destroy();
|
|
109
|
+
entities.delete(key);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
queryEntityKeys.set(queryKey, nextKeys);
|
|
95
113
|
});
|
|
96
114
|
}
|
|
97
|
-
// Clean up
|
|
98
|
-
for (const [
|
|
99
|
-
if (!
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
// Clean up owners whose queries disappeared entirely
|
|
116
|
+
for (const [queryKey, keys] of queryEntityKeys) {
|
|
117
|
+
if (!activeQueryKeys.has(queryKey)) {
|
|
118
|
+
for (const key of keys) {
|
|
119
|
+
const entity = entities.get(key);
|
|
120
|
+
if (entity && world.has(entity))
|
|
121
|
+
entity.destroy();
|
|
122
|
+
entities.delete(key);
|
|
123
|
+
}
|
|
124
|
+
queryEntityKeys.delete(queryKey);
|
|
102
125
|
}
|
|
103
126
|
}
|
|
104
127
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Vector2, Raycaster, EventDispatcher } from 'three';
|
|
2
1
|
import { useThrelte } from '@threlte/core';
|
|
2
|
+
import { EventDispatcher, Raycaster, Vector2 } from 'three';
|
|
3
3
|
const pointerDown = new Vector2();
|
|
4
4
|
const pointerUp = new Vector2();
|
|
5
5
|
const pointerMove = new Vector2();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createPoseFromFrame } from '../transform';
|
|
3
|
-
import { Struct, Pose } from '@viamrobotics/sdk';
|
|
1
|
+
import { Pose, Struct } from '@viamrobotics/sdk';
|
|
4
2
|
import { createAppMutation, createAppQuery } from '@viamrobotics/svelte-sdk';
|
|
5
3
|
import { getContext, setContext } from 'svelte';
|
|
4
|
+
import { createFrame } from '../frame';
|
|
5
|
+
import { createPoseFromFrame } from '../transform';
|
|
6
6
|
const key = Symbol('part-config-context');
|
|
7
7
|
export const providePartConfig = (partID, params) => {
|
|
8
8
|
const props = $derived(params());
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { VisionClient } from '@viamrobotics/sdk';
|
|
2
2
|
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
3
|
-
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
4
|
-
import { useLogs } from './useLogs.svelte';
|
|
5
|
-
import { parsePcdInWorker } from '../lib';
|
|
6
3
|
import { getContext, setContext, untrack } from 'svelte';
|
|
7
|
-
import { traits, useWorld } from '../ecs';
|
|
8
4
|
import { createBufferGeometry, updateBufferGeometry } from '../attribute';
|
|
9
|
-
import { useEnvironment } from './useEnvironment.svelte';
|
|
10
5
|
import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
|
|
6
|
+
import { traits, useWorld } from '../ecs';
|
|
7
|
+
import { updateGeometryTrait } from '../ecs/traits';
|
|
8
|
+
import { parsePcdInWorker } from '../lib';
|
|
11
9
|
import { createPose } from '../transform';
|
|
10
|
+
import { useEnvironment } from './useEnvironment.svelte';
|
|
11
|
+
import { useLogs } from './useLogs.svelte';
|
|
12
|
+
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
12
13
|
const key = Symbol('pointcloud-object-context');
|
|
13
14
|
export const providePointcloudObjects = (partID) => {
|
|
14
15
|
const world = useWorld();
|
|
@@ -57,8 +58,8 @@ export const providePointcloudObjects = (partID) => {
|
|
|
57
58
|
const logs = useLogs();
|
|
58
59
|
const interval = $derived(refreshRates.get(RefreshRates.pointclouds));
|
|
59
60
|
const options = $derived({
|
|
60
|
-
enabled: interval !==
|
|
61
|
-
refetchInterval: (interval ===
|
|
61
|
+
enabled: interval !== RefetchRates.OFF,
|
|
62
|
+
refetchInterval: (interval === RefetchRates.MANUAL ? false : interval),
|
|
62
63
|
});
|
|
63
64
|
const queries = $derived(enabledClients.map((client) => [
|
|
64
65
|
client.current.name,
|
|
@@ -79,73 +80,117 @@ export const providePointcloudObjects = (partID) => {
|
|
|
79
80
|
}
|
|
80
81
|
});
|
|
81
82
|
const entities = new Map();
|
|
83
|
+
const queryEntityKeys = new Map();
|
|
84
|
+
const destroyEntity = (key) => {
|
|
85
|
+
const entity = entities.get(key);
|
|
86
|
+
if (entity) {
|
|
87
|
+
if (world.has(entity))
|
|
88
|
+
entity.destroy();
|
|
89
|
+
entities.delete(key);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
82
92
|
$effect(() => {
|
|
83
|
-
const
|
|
93
|
+
const currentPartID = partID();
|
|
94
|
+
const activeQueryKeys = new Set();
|
|
84
95
|
for (const [name, query] of queries) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (existing) {
|
|
97
|
-
const geometry = existing.get(traits.BufferGeometry);
|
|
98
|
-
if (geometry) {
|
|
99
|
-
updateBufferGeometry(geometry, positions, colors);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
const geometry = createBufferGeometry(positions, colors);
|
|
104
|
-
const entity = world.spawn(traits.Name(poincloudLabel), traits.BufferGeometry(geometry), traits.Points);
|
|
105
|
-
entities.set(poincloudLabel, entity);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
96
|
+
const queryKey = `${currentPartID}:${name}`;
|
|
97
|
+
activeQueryKeys.add(queryKey);
|
|
98
|
+
$effect(() => {
|
|
99
|
+
const { data } = query;
|
|
100
|
+
let disposed = false;
|
|
101
|
+
const nextKeys = new Set();
|
|
102
|
+
const reconcileRemovedKeys = () => {
|
|
103
|
+
const prevKeys = queryEntityKeys.get(queryKey) ?? new Set();
|
|
104
|
+
for (const key of prevKeys) {
|
|
105
|
+
if (!nextKeys.has(key)) {
|
|
106
|
+
destroyEntity(key);
|
|
108
107
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
}
|
|
109
|
+
queryEntityKeys.set(queryKey, new Set(nextKeys));
|
|
110
|
+
};
|
|
111
|
+
if (!data || data.length === 0) {
|
|
112
|
+
reconcileRemovedKeys();
|
|
113
|
+
return () => {
|
|
114
|
+
disposed = true;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
let index = 0;
|
|
118
|
+
for (const { geometries: geometriesInFrame, pointCloud } of data) {
|
|
119
|
+
if (pointCloud.length > 0) {
|
|
120
|
+
const pointcloudLabel = `${name} pointcloud ${index + 1}`;
|
|
121
|
+
nextKeys.add(pointcloudLabel);
|
|
122
|
+
parsePcdInWorker(pointCloud)
|
|
123
|
+
.then(({ positions, colors }) => {
|
|
124
|
+
if (disposed) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!nextKeys.has(pointcloudLabel)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const existing = entities.get(pointcloudLabel);
|
|
131
|
+
if (existing) {
|
|
132
|
+
const geometry = existing.get(traits.BufferGeometry);
|
|
133
|
+
if (geometry) {
|
|
134
|
+
updateBufferGeometry(geometry, positions, colors);
|
|
118
135
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const geometry = createBufferGeometry(positions, colors);
|
|
139
|
+
const entity = world.spawn(traits.Name(pointcloudLabel), traits.BufferGeometry(geometry), traits.Points);
|
|
140
|
+
entities.set(pointcloudLabel, entity);
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
.catch((error) => {
|
|
144
|
+
if (disposed) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
logs.add(error?.reason ?? error?.message ?? 'Failed to parse pointcloud', 'error');
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (geometriesInFrame) {
|
|
151
|
+
let geometryIndex = 0;
|
|
152
|
+
for (const geometry of geometriesInFrame.geometries) {
|
|
153
|
+
const geometryLabel = `${name} pointcloud ${index + 1} geometry ${geometryIndex + 1}`;
|
|
154
|
+
nextKeys.add(geometryLabel);
|
|
155
|
+
const center = createPose(geometry.center);
|
|
156
|
+
const existing = entities.get(geometryLabel);
|
|
157
|
+
if (existing) {
|
|
158
|
+
existing.set(traits.Center, center);
|
|
159
|
+
updateGeometryTrait(existing, geometry);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
const entityTraits = [
|
|
163
|
+
traits.Name(geometryLabel),
|
|
164
|
+
traits.Center(center),
|
|
165
|
+
traits.GeometriesAPI,
|
|
166
|
+
traits.Geometry(geometry),
|
|
167
|
+
traits.Opacity(0.2),
|
|
168
|
+
traits.Color({ r: 0, g: 1, b: 0 }),
|
|
169
|
+
];
|
|
170
|
+
if (geometriesInFrame.referenceFrame) {
|
|
171
|
+
entityTraits.push(traits.Parent(geometriesInFrame.referenceFrame));
|
|
133
172
|
}
|
|
134
|
-
|
|
173
|
+
const entity = world.spawn(...entityTraits);
|
|
174
|
+
entities.set(geometryLabel, entity);
|
|
135
175
|
}
|
|
176
|
+
geometryIndex += 1;
|
|
136
177
|
}
|
|
137
|
-
index += 1;
|
|
138
178
|
}
|
|
139
|
-
|
|
179
|
+
index += 1;
|
|
180
|
+
}
|
|
181
|
+
reconcileRemovedKeys();
|
|
182
|
+
return () => {
|
|
183
|
+
disposed = true;
|
|
184
|
+
};
|
|
140
185
|
});
|
|
141
186
|
}
|
|
142
|
-
//
|
|
143
|
-
for (const [
|
|
144
|
-
if (!
|
|
145
|
-
|
|
146
|
-
|
|
187
|
+
// cleanup queries that disappeared entirely
|
|
188
|
+
for (const [queryKey, keys] of queryEntityKeys) {
|
|
189
|
+
if (!activeQueryKeys.has(queryKey)) {
|
|
190
|
+
for (const key of keys) {
|
|
191
|
+
destroyEntity(key);
|
|
147
192
|
}
|
|
148
|
-
|
|
193
|
+
queryEntityKeys.delete(queryKey);
|
|
149
194
|
}
|
|
150
195
|
}
|
|
151
196
|
});
|