@viamrobotics/motion-tools 1.10.0 → 1.11.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/HoverUpdater.svelte.d.ts +0 -3
- package/dist/HoverUpdater.svelte.js +8 -50
- package/dist/WorldObject.svelte.d.ts +27 -0
- package/dist/WorldObject.svelte.js +8 -55
- package/dist/{draw → buf/draw}/v1/drawing_pb.d.ts +6 -0
- package/dist/{draw → buf/draw}/v1/drawing_pb.js +7 -0
- package/dist/buf/draw/v1/service_connect.d.ts +122 -0
- package/dist/buf/draw/v1/service_connect.js +126 -0
- package/dist/buf/draw/v1/service_pb.d.ts +382 -0
- package/dist/buf/draw/v1/service_pb.js +612 -0
- package/dist/components/App.svelte +0 -1
- package/dist/components/Arrows/Arrows.svelte +16 -3
- package/dist/components/FileDrop/file-dropper.d.ts +1 -1
- package/dist/components/FileDrop/snapshot-dropper.js +1 -1
- package/dist/components/FileDrop/useFileDrop.svelte.d.ts +2 -1
- package/dist/components/Frame.svelte +1 -1
- package/dist/components/Geometry.svelte +113 -71
- package/dist/components/Geometry.svelte.d.ts +6 -7
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/Snapshot.svelte +1 -1
- package/dist/components/Snapshot.svelte.d.ts +1 -1
- package/dist/components/overlay/Details.svelte +20 -0
- package/dist/components/overlay/left-pane/TreeContainer.svelte +0 -2
- package/dist/components/overlay/settings/Settings.svelte +51 -0
- package/dist/components/overlay/widgets/Camera.svelte +20 -12
- package/dist/components/xr/ArmTeleop.svelte +469 -0
- package/dist/components/xr/ArmTeleop.svelte.d.ts +10 -0
- package/dist/components/xr/CameraFeed.svelte +191 -47
- package/dist/components/xr/CameraFeed.svelte.d.ts +7 -0
- package/dist/components/xr/Controllers.svelte +45 -38
- package/dist/components/xr/Controllers.svelte.d.ts +2 -17
- package/dist/components/xr/Hands.svelte +2 -4
- package/dist/components/xr/JointLimitsWidget.svelte +209 -0
- package/dist/components/xr/JointLimitsWidget.svelte.d.ts +13 -0
- package/dist/components/xr/OriginMarker.svelte +1 -15
- package/dist/components/xr/XR.svelte +78 -5
- package/dist/components/xr/XRConfigPanel.svelte +449 -0
- package/dist/components/xr/XRConfigPanel.svelte.d.ts +11 -0
- package/dist/components/xr/XRControllerSettings.svelte +240 -0
- package/dist/components/xr/XRControllerSettings.svelte.d.ts +3 -0
- package/dist/components/xr/XRToast.svelte +215 -0
- package/dist/components/xr/XRToast.svelte.d.ts +3 -0
- package/dist/components/xr/math.d.ts +14 -0
- package/dist/components/xr/math.js +26 -0
- package/dist/components/xr/toasts.svelte.d.ts +20 -0
- package/dist/components/xr/toasts.svelte.js +32 -0
- package/dist/components/xr/useOrigin.svelte.d.ts +2 -2
- package/dist/components/xr/useOrigin.svelte.js +4 -4
- package/dist/ecs/traits.d.ts +9 -0
- package/dist/ecs/traits.js +9 -0
- package/dist/ecs/useTrait.svelte.d.ts +3 -3
- package/dist/frame.d.ts +0 -3
- package/dist/hooks/useArmKinematics.svelte.d.ts +12 -0
- package/dist/hooks/useArmKinematics.svelte.js +31 -0
- package/dist/hooks/useGeometries.svelte.js +46 -35
- package/dist/hooks/useObjectEvents.svelte.js +24 -7
- package/dist/hooks/usePartConfig.svelte.d.ts +0 -35
- package/dist/hooks/usePartConfig.svelte.js +2 -2
- package/dist/hooks/usePointcloudObjects.svelte.js +44 -63
- package/dist/hooks/usePointclouds.svelte.js +10 -6
- package/dist/hooks/usePose.svelte.js +4 -1
- package/dist/hooks/useResourceByName.svelte.d.ts +7 -0
- package/dist/hooks/useResourceByName.svelte.js +2 -2
- package/dist/hooks/useSettings.svelte.d.ts +14 -0
- package/dist/hooks/useSettings.svelte.js +10 -0
- package/dist/hooks/useWorldState.svelte.d.ts +0 -8
- package/dist/lib.d.ts +1 -3
- package/dist/lib.js +1 -3
- package/dist/snapshot.d.ts +2 -2
- package/dist/snapshot.js +2 -2
- package/dist/three/InstancedArrows/raycast.d.ts +2 -4
- package/dist/three/InstancedArrows/raycast.js +5 -5
- package/dist/transform.js +1 -0
- package/package.json +4 -5
- package/dist/assert.d.ts +0 -14
- package/dist/assert.js +0 -21
- package/dist/components/BatchedGeometry.svelte +0 -0
- package/dist/components/BatchedGeometry.svelte.d.ts +0 -26
- package/dist/components/Detections.svelte +0 -41
- package/dist/components/Detections.svelte.d.ts +0 -3
- package/dist/components/DetectionsPlane.svelte +0 -23
- package/dist/components/DetectionsPlane.svelte.d.ts +0 -21
- package/dist/components/Geometry2.svelte +0 -211
- package/dist/components/Geometry2.svelte.d.ts +0 -19
- package/dist/components/overlay/left-pane/Widgets.svelte +0 -65
- package/dist/components/overlay/left-pane/Widgets.svelte.d.ts +0 -3
- package/dist/entries.d.ts +0 -1
- package/dist/entries.js +0 -3
- package/dist/hooks/index.d.ts +0 -0
- package/dist/hooks/index.js +0 -1
- package/dist/test.d.ts +0 -1
- package/dist/test.js +0 -1
- package/dist/three/BoxHelper.d.ts +0 -50
- package/dist/three/BoxHelper.js +0 -134
- /package/dist/{common → buf/common}/v1/common_pb.d.ts +0 -0
- /package/dist/{common → buf/common}/v1/common_pb.js +0 -0
- /package/dist/{draw → buf/draw}/v1/metadata_pb.d.ts +0 -0
- /package/dist/{draw → buf/draw}/v1/metadata_pb.js +0 -0
- /package/dist/{draw → buf/draw}/v1/scene_pb.d.ts +0 -0
- /package/dist/{draw → buf/draw}/v1/scene_pb.js +0 -0
- /package/dist/{draw → buf/draw}/v1/snapshot_pb.d.ts +0 -0
- /package/dist/{draw → buf/draw}/v1/snapshot_pb.js +0 -0
- /package/dist/{draw → buf/draw}/v1/transforms_pb.d.ts +0 -0
- /package/dist/{draw → buf/draw}/v1/transforms_pb.js +0 -0
- /package/dist/components/{BentPlaneGeometry.svelte → xr/BentPlaneGeometry.svelte} +0 -0
- /package/dist/components/{BentPlaneGeometry.svelte.d.ts → xr/BentPlaneGeometry.svelte.d.ts} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ArmClient } from '@viamrobotics/sdk';
|
|
2
|
+
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
3
|
+
import { getContext, setContext } from 'svelte';
|
|
4
|
+
const key = Symbol('arm-kinematics-context');
|
|
5
|
+
export const provideArmKinematics = (partID) => {
|
|
6
|
+
const arms = useResourceNames(partID, 'arm');
|
|
7
|
+
// Kinematics are static config data, so fetch once and cache indefinitely
|
|
8
|
+
const options = { staleTime: Infinity, refetchOnMount: false, refetchInterval: false };
|
|
9
|
+
const names = $derived(arms.current.map((arm) => arm.name));
|
|
10
|
+
const clients = $derived(arms.current.map((arm) => createResourceClient(ArmClient, partID, () => arm.name)));
|
|
11
|
+
const kinematicsQueries = $derived(clients.map((client) => [client.current?.name, createResourceQuery(client, 'getKinematics', () => options)]));
|
|
12
|
+
const kinematics = $derived(Object.fromEntries(kinematicsQueries.map(([name, query]) => [
|
|
13
|
+
name,
|
|
14
|
+
query.data?.joints.map((j) => ({
|
|
15
|
+
id: j.id,
|
|
16
|
+
min: j.min,
|
|
17
|
+
max: j.max,
|
|
18
|
+
})),
|
|
19
|
+
])));
|
|
20
|
+
setContext(key, {
|
|
21
|
+
get names() {
|
|
22
|
+
return names;
|
|
23
|
+
},
|
|
24
|
+
get kinematics() {
|
|
25
|
+
return kinematics;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
export const useArmKinematics = () => {
|
|
30
|
+
return getContext(key);
|
|
31
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArmClient, CameraClient, GantryClient, GripperClient } from '@viamrobotics/sdk';
|
|
2
|
-
import { setContext, getContext } from 'svelte';
|
|
2
|
+
import { untrack, setContext, getContext } from 'svelte';
|
|
3
3
|
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
4
4
|
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
5
5
|
import { useLogs } from './useLogs.svelte';
|
|
@@ -27,8 +27,8 @@ export const provideGeometries = (partID) => {
|
|
|
27
27
|
const gripperClients = $derived(grippers.current.map((gripper) => createResourceClient(GripperClient, partID, () => gripper.name)));
|
|
28
28
|
const cameraClients = $derived(cameras.current.map((camera) => createResourceClient(CameraClient, partID, () => camera.name)));
|
|
29
29
|
const gantryClients = $derived(gantries.current.map((gantry) => createResourceClient(GantryClient, partID, () => gantry.name)));
|
|
30
|
+
const interval = $derived(refreshRates.get(RefreshRates.poses));
|
|
30
31
|
const options = $derived.by(() => {
|
|
31
|
-
const interval = refreshRates.get(RefreshRates.poses);
|
|
32
32
|
return {
|
|
33
33
|
enabled: refreshRates.get(RefreshRates.poses) !== RefetchRates.OFF &&
|
|
34
34
|
environment.current.viewerMode === 'monitor',
|
|
@@ -40,13 +40,20 @@ export const provideGeometries = (partID) => {
|
|
|
40
40
|
const cameraQueries = $derived(cameraClients.map((client) => [client.current?.name, createResourceQuery(client, 'getGeometries', () => options)]));
|
|
41
41
|
const gantryQueries = $derived(gantryClients.map((client) => [client.current?.name, createResourceQuery(client, 'getGeometries', () => options)]));
|
|
42
42
|
$effect(() => {
|
|
43
|
+
if (interval === RefetchRates.FPS_30 || interval === RefetchRates.FPS_60) {
|
|
44
|
+
return logs.add(`Fetching geometries every ${interval}ms...`);
|
|
45
|
+
}
|
|
43
46
|
for (const [name, query] of queries) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
untrack(() => {
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (query.isFetching) {
|
|
50
|
+
logs.add(`Fetching geometries for ${name}...`);
|
|
51
|
+
}
|
|
52
|
+
else if (query.error) {
|
|
53
|
+
logs.add(`Error fetching geometries from ${name}: ${query.error.message}`, 'error');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
50
57
|
}
|
|
51
58
|
});
|
|
52
59
|
const queries = $derived([...armQueries, ...gripperQueries, ...cameraQueries, ...gantryQueries]);
|
|
@@ -54,34 +61,38 @@ export const provideGeometries = (partID) => {
|
|
|
54
61
|
$effect(() => {
|
|
55
62
|
const active = {};
|
|
56
63
|
for (const [name, query] of queries) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
untrack(() => {
|
|
65
|
+
$effect(() => {
|
|
66
|
+
if (name && query.data) {
|
|
67
|
+
let index = 0;
|
|
68
|
+
for (const geometry of query.data) {
|
|
69
|
+
index += 1;
|
|
70
|
+
const resourceName = resources.current[name];
|
|
71
|
+
const label = geometry.label ? geometry.label : `${name} geometry ${index}`;
|
|
72
|
+
active[`${name}:${label}`] = true;
|
|
73
|
+
const pose = createPose(geometry.center);
|
|
74
|
+
const subtype = resourceName?.subtype;
|
|
75
|
+
const existing = entities.get(`${name}:${label}`);
|
|
76
|
+
if (existing) {
|
|
77
|
+
existing.set(traits.Pose, pose);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const entityTraits = [
|
|
81
|
+
traits.Parent(name),
|
|
82
|
+
traits.Name(label),
|
|
83
|
+
traits.Pose(pose),
|
|
84
|
+
traits.GeometriesAPI,
|
|
85
|
+
traits.Geometry(geometry),
|
|
86
|
+
];
|
|
87
|
+
if (subtype) {
|
|
88
|
+
entityTraits.push(traits.Color(subtype ? colorUtil.set(resourceColors[subtype]) : undefined));
|
|
89
|
+
}
|
|
90
|
+
const entity = world.spawn(...entityTraits);
|
|
91
|
+
entities.set(`${name}:${label}`, entity);
|
|
92
|
+
}
|
|
80
93
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
85
96
|
}
|
|
86
97
|
// Clean up non-active entities
|
|
87
98
|
for (const [label, entity] of entities) {
|
|
@@ -4,6 +4,7 @@ import { useVisibility } from './useVisibility.svelte';
|
|
|
4
4
|
import { Vector2 } from 'three';
|
|
5
5
|
import { traits } from '../ecs';
|
|
6
6
|
import { updateHoverInfo } from '../HoverUpdater.svelte';
|
|
7
|
+
import { createPose, matrixToPose, poseToMatrix } from '../transform';
|
|
7
8
|
export const useObjectEvents = (entity) => {
|
|
8
9
|
const down = new Vector2();
|
|
9
10
|
const selectedEntity = useSelectedEntity();
|
|
@@ -36,16 +37,32 @@ export const useObjectEvents = (entity) => {
|
|
|
36
37
|
event.stopPropagation();
|
|
37
38
|
if (currentEntity && currentEntity.has(traits.Hovered)) {
|
|
38
39
|
const hoverInfo = updateHoverInfo(currentEntity, event);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
index: hoverInfo.index,
|
|
40
|
+
const hoverPose = createPose(hoverInfo
|
|
41
|
+
? {
|
|
42
42
|
x: hoverInfo.x,
|
|
43
43
|
y: hoverInfo.y,
|
|
44
44
|
z: hoverInfo.z,
|
|
45
|
-
oX:
|
|
46
|
-
oY:
|
|
47
|
-
oZ:
|
|
48
|
-
theta:
|
|
45
|
+
oX: 0,
|
|
46
|
+
oY: 0,
|
|
47
|
+
oZ: 1,
|
|
48
|
+
theta: 0,
|
|
49
|
+
}
|
|
50
|
+
: undefined);
|
|
51
|
+
const worldPose = currentEntity.get(traits.WorldPose) ?? createPose();
|
|
52
|
+
const hoverPoseMatrix = poseToMatrix(hoverPose);
|
|
53
|
+
const worldPoseMatrix = poseToMatrix(worldPose);
|
|
54
|
+
const resultMatrix = worldPoseMatrix.multiply(hoverPoseMatrix);
|
|
55
|
+
const resultPose = matrixToPose(resultMatrix);
|
|
56
|
+
if (hoverInfo) {
|
|
57
|
+
currentEntity.set(traits.InstancedPose, {
|
|
58
|
+
index: hoverInfo.index,
|
|
59
|
+
x: resultPose.x,
|
|
60
|
+
y: resultPose.y,
|
|
61
|
+
z: resultPose.z,
|
|
62
|
+
oX: resultPose.oX,
|
|
63
|
+
oY: resultPose.oY,
|
|
64
|
+
oZ: resultPose.oZ,
|
|
65
|
+
theta: resultPose.theta,
|
|
49
66
|
});
|
|
50
67
|
}
|
|
51
68
|
}
|
|
@@ -28,49 +28,14 @@ interface PartConfigContext {
|
|
|
28
28
|
}
|
|
29
29
|
export declare const providePartConfig: (params: () => PartConfigParams) => void;
|
|
30
30
|
export declare const usePartConfig: () => PartConfigContext;
|
|
31
|
-
interface LocalPartConfig {
|
|
32
|
-
isDirty: () => boolean;
|
|
33
|
-
hasEditPermissions: () => boolean;
|
|
34
|
-
getLocalPartConfig: () => Struct;
|
|
35
|
-
setLocalPartConfig: (config: Struct) => void;
|
|
36
|
-
componentNameToFragmentId: () => Record<string, string>;
|
|
37
|
-
saveLocalPartConfig?: () => void;
|
|
38
|
-
resetLocalPartConfig?: () => void;
|
|
39
|
-
}
|
|
40
31
|
interface AppEmbeddedPartConfigProps {
|
|
41
32
|
isDirty: () => boolean;
|
|
42
33
|
getLocalPartConfig: () => Struct;
|
|
43
34
|
setLocalPartConfig: (config: Struct) => void;
|
|
44
35
|
getComponentToFragId: () => Record<string, string>;
|
|
45
36
|
}
|
|
46
|
-
export declare class AppEmbeddedPartConfig implements LocalPartConfig {
|
|
47
|
-
private _appEmbeddedPartConfigProps;
|
|
48
|
-
constructor(appEmbeddedPartConfigProps: AppEmbeddedPartConfigProps);
|
|
49
|
-
isDirty(): boolean;
|
|
50
|
-
getLocalPartConfig(): Struct;
|
|
51
|
-
setLocalPartConfig(config: Struct): void;
|
|
52
|
-
componentNameToFragmentId(): Record<string, string>;
|
|
53
|
-
hasEditPermissions(): boolean;
|
|
54
|
-
}
|
|
55
37
|
interface StandalonePartConfigProps {
|
|
56
38
|
viamClient: () => ViamClient | undefined;
|
|
57
39
|
partID: () => string;
|
|
58
40
|
}
|
|
59
|
-
export declare class StandalonePartConfig implements LocalPartConfig {
|
|
60
|
-
private _standalonePartConfigProps;
|
|
61
|
-
private _isDirty;
|
|
62
|
-
private _hasEditPermissions;
|
|
63
|
-
private _networkPartConfig;
|
|
64
|
-
private _localPartConfig;
|
|
65
|
-
private _partName;
|
|
66
|
-
private _componentNameToFragmentId;
|
|
67
|
-
constructor(standalonePartConfigProps: StandalonePartConfigProps);
|
|
68
|
-
getLocalPartConfig(): Struct;
|
|
69
|
-
setLocalPartConfig(config: Struct): void;
|
|
70
|
-
isDirty(): boolean;
|
|
71
|
-
hasEditPermissions(): boolean;
|
|
72
|
-
componentNameToFragmentId(): Record<string, string>;
|
|
73
|
-
saveLocalPartConfig(): Promise<void>;
|
|
74
|
-
resetLocalPartConfig(): Promise<void>;
|
|
75
|
-
}
|
|
76
41
|
export {};
|
|
@@ -218,7 +218,7 @@ export const providePartConfig = (params) => {
|
|
|
218
218
|
export const usePartConfig = () => {
|
|
219
219
|
return getContext(key);
|
|
220
220
|
};
|
|
221
|
-
|
|
221
|
+
class AppEmbeddedPartConfig {
|
|
222
222
|
_appEmbeddedPartConfigProps;
|
|
223
223
|
constructor(appEmbeddedPartConfigProps) {
|
|
224
224
|
this._appEmbeddedPartConfigProps = appEmbeddedPartConfigProps;
|
|
@@ -239,7 +239,7 @@ export class AppEmbeddedPartConfig {
|
|
|
239
239
|
return true;
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
|
-
|
|
242
|
+
class StandalonePartConfig {
|
|
243
243
|
_standalonePartConfigProps;
|
|
244
244
|
_isDirty = $state(false);
|
|
245
245
|
_hasEditPermissions = $state(false);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VisionClient } from '@viamrobotics/sdk';
|
|
2
2
|
import { createResourceClient, createResourceQuery, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
3
3
|
import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
4
4
|
import { useLogs } from './useLogs.svelte';
|
|
5
5
|
import { parsePcdInWorker } from '../lib';
|
|
6
|
-
import { getContext, setContext } from 'svelte';
|
|
6
|
+
import { getContext, setContext, untrack } from 'svelte';
|
|
7
7
|
import { traits, useWorld } from '../ecs';
|
|
8
8
|
import { createBufferGeometry, updateBufferGeometry } from '../attribute';
|
|
9
9
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
@@ -66,71 +66,50 @@ export const providePointcloudObjects = (partID) => {
|
|
|
66
66
|
]));
|
|
67
67
|
$effect(() => {
|
|
68
68
|
for (const [name, query] of queries) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const responses = [];
|
|
80
|
-
for (const [name, query] of queries) {
|
|
81
|
-
const { data } = query;
|
|
82
|
-
if (name && data) {
|
|
83
|
-
responses.push([name, data]);
|
|
84
|
-
}
|
|
69
|
+
untrack(() => {
|
|
70
|
+
$effect(() => {
|
|
71
|
+
if (query.isFetching) {
|
|
72
|
+
logs.add(`Fetching pointcloud for ${name}...`);
|
|
73
|
+
}
|
|
74
|
+
else if (query.error) {
|
|
75
|
+
logs.add(`Error fetching pointcloud from ${name}: ${query.error.message}`, 'error');
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
85
79
|
}
|
|
86
|
-
Promise.allSettled(responses.map(async ([name, pointcloudObjects]) => {
|
|
87
|
-
const pointclouds = await Promise.all(pointcloudObjects
|
|
88
|
-
.filter((value) => value !== undefined)
|
|
89
|
-
.map((value) => {
|
|
90
|
-
return parsePcdInWorker(new Uint8Array(value.pointCloud));
|
|
91
|
-
}));
|
|
92
|
-
return {
|
|
93
|
-
name,
|
|
94
|
-
pointclouds,
|
|
95
|
-
geometries: pointcloudObjects.map((value) => value.geometries),
|
|
96
|
-
};
|
|
97
|
-
})).then((results) => {
|
|
98
|
-
const fulfilledResults = [];
|
|
99
|
-
for (const result of results) {
|
|
100
|
-
if (result.status === 'fulfilled') {
|
|
101
|
-
fulfilledResults.push(result.value);
|
|
102
|
-
}
|
|
103
|
-
else if (result.status === 'rejected') {
|
|
104
|
-
logs.add(result.reason, 'error');
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
pcResults = fulfilledResults;
|
|
108
|
-
});
|
|
109
80
|
});
|
|
110
81
|
const entities = new Map();
|
|
111
82
|
$effect(() => {
|
|
112
83
|
const active = {};
|
|
113
|
-
for (const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
84
|
+
for (const [name, query] of queries) {
|
|
85
|
+
untrack(() => {
|
|
86
|
+
$effect(() => {
|
|
87
|
+
const { data } = query;
|
|
88
|
+
if (!data || data.length === 0)
|
|
89
|
+
return;
|
|
90
|
+
let index = 0;
|
|
91
|
+
for (const { geometries: geometriesInFrame, pointCloud } of data) {
|
|
92
|
+
if (pointCloud.length > 0) {
|
|
93
|
+
parsePcdInWorker(pointCloud).then(({ positions, colors }) => {
|
|
94
|
+
const poincloudLabel = `${name} pointcloud ${index + 1}`;
|
|
95
|
+
const existing = entities.get(poincloudLabel);
|
|
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
|
+
});
|
|
108
|
+
}
|
|
131
109
|
if (geometriesInFrame) {
|
|
132
|
-
|
|
133
|
-
|
|
110
|
+
let geometryIndex = 0;
|
|
111
|
+
for (const geometry of geometriesInFrame.geometries) {
|
|
112
|
+
const geometryLabel = `${name} pointcloud ${index} geometry ${geometryIndex + 1}`;
|
|
134
113
|
const pose = createPose(geometry.center);
|
|
135
114
|
active[geometryLabel] = true;
|
|
136
115
|
const existing = entities.get(geometryLabel);
|
|
@@ -152,11 +131,13 @@ export const providePointcloudObjects = (partID) => {
|
|
|
152
131
|
const entity = world.spawn(...entityTraits);
|
|
153
132
|
entities.set(geometryLabel, entity);
|
|
154
133
|
}
|
|
134
|
+
geometryIndex += 1;
|
|
155
135
|
}
|
|
156
136
|
}
|
|
137
|
+
index += 1;
|
|
157
138
|
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
139
|
+
});
|
|
140
|
+
});
|
|
160
141
|
}
|
|
161
142
|
// Clean up old entities
|
|
162
143
|
for (const [label, entity] of entities) {
|
|
@@ -65,12 +65,16 @@ export const providePointclouds = (partID) => {
|
|
|
65
65
|
const queryMap = $derived(typeSafeObjectFromEntries(queries));
|
|
66
66
|
$effect(() => {
|
|
67
67
|
for (const [name, query] of queries) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
untrack(() => {
|
|
69
|
+
$effect(() => {
|
|
70
|
+
if (query.isFetching) {
|
|
71
|
+
logs.add(`Fetching pointcloud for ${name}...`);
|
|
72
|
+
}
|
|
73
|
+
else if (query.error) {
|
|
74
|
+
logs.add(`Error fetching pointcloud from ${name}: ${query.error.message}`, 'error');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
74
78
|
}
|
|
75
79
|
});
|
|
76
80
|
const entities = new Map();
|
|
@@ -24,7 +24,7 @@ export const usePose = (name, parent) => {
|
|
|
24
24
|
const resource = $derived(currentName ? resourceByName.current[currentName] : undefined);
|
|
25
25
|
const parentResource = $derived(currentParent ? resourceByName.current[currentParent] : undefined);
|
|
26
26
|
const frames = useFrames();
|
|
27
|
-
let pose = $state(
|
|
27
|
+
let pose = $state();
|
|
28
28
|
const interval = $derived(refreshRates.get(RefreshRates.poses));
|
|
29
29
|
const resolvedParent = $derived(origingFrameComponentTypes.includes(parentResource?.subtype ?? '')
|
|
30
30
|
? `${parent()}_origin`
|
|
@@ -43,6 +43,9 @@ export const usePose = (name, parent) => {
|
|
|
43
43
|
});
|
|
44
44
|
$effect(() => addQueryToRefetch(query));
|
|
45
45
|
$effect(() => {
|
|
46
|
+
if (interval === RefetchRates.FPS_30 || interval === RefetchRates.FPS_60) {
|
|
47
|
+
return logs.add(`Fetching pose for ${currentName} every ${interval}ms...`);
|
|
48
|
+
}
|
|
46
49
|
if (query.isFetching) {
|
|
47
50
|
logs.add(`Fetching pose for ${currentName}...`);
|
|
48
51
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResourceName } from '@viamrobotics/sdk';
|
|
2
|
+
interface Context {
|
|
3
|
+
current: Record<string, ResourceName | undefined>;
|
|
4
|
+
}
|
|
5
|
+
export declare const provideResourceByName: (partID: () => string) => void;
|
|
6
|
+
export declare const useResourceByName: () => Context;
|
|
7
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const RESOURCE_BY_NAME_CONTEXT_KEY = Symbol('resource-by-name-context');
|
|
4
|
+
const createResourceByName = (partID) => {
|
|
5
5
|
const resourceNames = useResourceNames(partID);
|
|
6
6
|
const resourceByName = $derived.by(() => {
|
|
7
7
|
const results = {};
|
|
@@ -25,6 +25,20 @@ export interface Settings {
|
|
|
25
25
|
renderStats: boolean;
|
|
26
26
|
renderArmModels: 'colliders' | 'colliders+model' | 'model';
|
|
27
27
|
renderSubEntityHoverDetail: boolean;
|
|
28
|
+
xrController: {
|
|
29
|
+
left: {
|
|
30
|
+
armName?: string;
|
|
31
|
+
gripperName?: string;
|
|
32
|
+
scaleFactor: number;
|
|
33
|
+
rotationEnabled: boolean;
|
|
34
|
+
};
|
|
35
|
+
right: {
|
|
36
|
+
armName?: string;
|
|
37
|
+
gripperName?: string;
|
|
38
|
+
scaleFactor: number;
|
|
39
|
+
rotationEnabled: boolean;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
28
42
|
}
|
|
29
43
|
interface Context {
|
|
30
44
|
current: Settings;
|
|
@@ -28,6 +28,16 @@ const defaults = () => ({
|
|
|
28
28
|
renderStats: false,
|
|
29
29
|
renderArmModels: 'colliders+model',
|
|
30
30
|
renderSubEntityHoverDetail: false,
|
|
31
|
+
xrController: {
|
|
32
|
+
left: {
|
|
33
|
+
scaleFactor: 1.0,
|
|
34
|
+
rotationEnabled: true,
|
|
35
|
+
},
|
|
36
|
+
right: {
|
|
37
|
+
scaleFactor: 1.0,
|
|
38
|
+
rotationEnabled: true,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
31
41
|
});
|
|
32
42
|
export const provideSettings = () => {
|
|
33
43
|
let settings = $state(defaults());
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import { type TransformChangeEvent, type TransformWithUUID } from '@viamrobotics/sdk';
|
|
2
|
-
export type ChangeMessage = {
|
|
3
|
-
type: 'change';
|
|
4
|
-
events: TransformChangeEvent[];
|
|
5
|
-
};
|
|
6
|
-
export type TransformEvent = TransformChangeEvent & {
|
|
7
|
-
transform: TransformWithUUID;
|
|
8
|
-
};
|
|
9
1
|
export declare const provideWorldStates: () => void;
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
export { default as Geometry } from './components/Geometry.svelte';
|
|
2
1
|
export { default as AxesHelper } from './components/AxesHelper.svelte';
|
|
3
2
|
export { default as Snapshot } from './components/Snapshot.svelte';
|
|
4
|
-
export { Snapshot as SnapshotProto } from './draw/v1/snapshot_pb';
|
|
3
|
+
export { Snapshot as SnapshotProto } from './buf/draw/v1/snapshot_pb';
|
|
5
4
|
export { BatchedArrow } from './three/BatchedArrow';
|
|
6
5
|
export { CapsuleGeometry } from './three/CapsuleGeometry';
|
|
7
6
|
export { OrientationVector } from './three/OrientationVector';
|
|
8
|
-
export { WorldObject } from './WorldObject.svelte';
|
|
9
7
|
export { parsePcdInWorker } from './loaders/pcd';
|
package/dist/lib.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
// Components
|
|
2
2
|
// NOTE: These components should be pure and not use any hooks if you add a new component to export here
|
|
3
3
|
// ensure you write a corresponding unit test to assert the component works in absence of parent providers in /src/lib/__tests__/PureComponents.svelte.spec.ts
|
|
4
|
-
export { default as Geometry } from './components/Geometry.svelte';
|
|
5
4
|
export { default as AxesHelper } from './components/AxesHelper.svelte';
|
|
6
5
|
// Snapshot component (uses context, requires MotionTools parent)
|
|
7
6
|
export { default as Snapshot } from './components/Snapshot.svelte';
|
|
8
|
-
export { Snapshot as SnapshotProto } from './draw/v1/snapshot_pb';
|
|
7
|
+
export { Snapshot as SnapshotProto } from './buf/draw/v1/snapshot_pb';
|
|
9
8
|
// Classes
|
|
10
9
|
export { BatchedArrow } from './three/BatchedArrow';
|
|
11
10
|
export { CapsuleGeometry } from './three/CapsuleGeometry';
|
|
12
11
|
export { OrientationVector } from './three/OrientationVector';
|
|
13
|
-
export { WorldObject } from './WorldObject.svelte';
|
|
14
12
|
// Functions
|
|
15
13
|
export { parsePcdInWorker } from './loaders/pcd';
|
package/dist/snapshot.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { World, Entity } from 'koota';
|
|
2
|
-
import type { Snapshot } from './draw/v1/snapshot_pb';
|
|
3
|
-
import { type SceneMetadata } from './draw/v1/scene_pb';
|
|
2
|
+
import type { Snapshot } from './buf/draw/v1/snapshot_pb';
|
|
3
|
+
import { type SceneMetadata } from './buf/draw/v1/scene_pb';
|
|
4
4
|
import type { Settings } from './hooks/useSettings.svelte';
|
|
5
5
|
export declare const applySceneMetadata: (settings: Settings, metadata: SceneMetadata) => Settings;
|
|
6
6
|
export declare const spawnSnapshotEntities: (world: World, snapshot: Snapshot) => Entity[];
|
package/dist/snapshot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Vector3, Vector4 } from 'three';
|
|
2
2
|
import { NURBSCurve } from 'three/addons/curves/NURBSCurve.js';
|
|
3
|
-
import { RenderArmModels } from './draw/v1/scene_pb';
|
|
4
|
-
import {} from './draw/v1/drawing_pb';
|
|
3
|
+
import { RenderArmModels } from './buf/draw/v1/scene_pb';
|
|
4
|
+
import {} from './buf/draw/v1/drawing_pb';
|
|
5
5
|
import { traits } from './ecs';
|
|
6
6
|
import { Geometry } from '@viamrobotics/sdk';
|
|
7
7
|
import { parseMetadata } from './WorldObject.svelte';
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Raycaster, type Intersection } from 'three';
|
|
2
2
|
import type { InstancedArrows } from './InstancedArrows';
|
|
3
|
-
export declare function meshBoundsRaycast(this:
|
|
4
|
-
geometry: BufferGeometry;
|
|
5
|
-
}, raycaster: Raycaster, intersects: Intersection[]): void;
|
|
3
|
+
export declare function meshBoundsRaycast(this: InstancedArrows, raycaster: Raycaster, intersects: Intersection[]): void;
|
|
6
4
|
/**
|
|
7
5
|
* Currently unused. In the future will be used for click only (not mousemove) due to complexity.
|
|
8
6
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ray, Matrix4, Raycaster, Vector3, Box3, RawShaderMaterial } from 'three';
|
|
2
2
|
const vec3 = new Vector3();
|
|
3
3
|
const inverseMatrix = new Matrix4();
|
|
4
4
|
const localRay = new Ray();
|
|
@@ -41,10 +41,10 @@ function closestPointsRaySegment(ray, a, b, outRay, outSeg) {
|
|
|
41
41
|
return outRay.distanceToSquared(outSeg);
|
|
42
42
|
}
|
|
43
43
|
export function meshBoundsRaycast(raycaster, intersects) {
|
|
44
|
-
if (this.geometry.boundingBox === null) {
|
|
45
|
-
this.geometry.computeBoundingBox();
|
|
44
|
+
if (this.shaftMesh.geometry.boundingBox === null) {
|
|
45
|
+
this.shaftMesh.geometry.computeBoundingBox();
|
|
46
46
|
}
|
|
47
|
-
box.copy(this.geometry.boundingBox ?? box);
|
|
47
|
+
box.copy(this.shaftMesh.geometry.boundingBox ?? box);
|
|
48
48
|
if (!raycaster.ray.intersectsBox(box)) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
@@ -119,7 +119,7 @@ export function raycast(raycaster, intersects) {
|
|
|
119
119
|
distance: bestDistance,
|
|
120
120
|
point: bestPointWorld,
|
|
121
121
|
object: this.shaftMesh,
|
|
122
|
-
|
|
122
|
+
index: bestInstanceId,
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
}
|
package/dist/transform.js
CHANGED
|
@@ -8,6 +8,7 @@ const scale = new Vector3();
|
|
|
8
8
|
export const createPose = (pose) => {
|
|
9
9
|
// We should only default to the 0,0,1,0 orientation vector if the entire vector component is missing
|
|
10
10
|
const oZ = pose?.oX === undefined && pose?.oY === undefined && pose?.oZ === undefined ? 1 : (pose?.oZ ?? 0);
|
|
11
|
+
// pose expects theta in degrees
|
|
11
12
|
return {
|
|
12
13
|
x: pose?.x ?? 0,
|
|
13
14
|
y: pose?.y ?? 0,
|