@viamrobotics/motion-tools 1.12.3 → 1.13.1
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.js +1 -1
- package/dist/WorldObject.svelte.js +26 -13
- package/dist/buf/draw/v1/service_connect.d.ts +14 -25
- package/dist/buf/draw/v1/service_connect.js +14 -25
- package/dist/buf/draw/v1/service_pb.d.ts +61 -76
- package/dist/buf/draw/v1/service_pb.js +58 -111
- package/dist/color.js +3 -3
- package/dist/components/App.svelte +5 -6
- package/dist/components/Camera.svelte +1 -7
- package/dist/components/Camera.svelte.d.ts +0 -1
- package/dist/components/CameraControls.svelte +2 -2
- package/dist/components/{Arrows → Entities/Arrows}/ArrowGroups.svelte +3 -3
- package/dist/components/{Arrows → Entities/Arrows}/Arrows.svelte +6 -6
- package/dist/components/{Arrows → Entities/Arrows}/Arrows.svelte.d.ts +1 -1
- package/dist/components/{Entities.svelte → Entities/Entities.svelte} +5 -1
- package/dist/components/{Frame.svelte → Entities/Frame.svelte} +8 -8
- package/dist/components/{GLTF.svelte → Entities/GLTF.svelte} +5 -5
- package/dist/components/{Geometry.svelte → Entities/Geometry.svelte} +48 -53
- package/dist/components/{Label.svelte → Entities/Label.svelte} +1 -1
- package/dist/components/{Line.svelte → Entities/Line.svelte} +2 -2
- package/dist/components/{Points.svelte → Entities/Points.svelte} +5 -5
- package/dist/components/{Pose.svelte → Entities/Pose.svelte} +3 -3
- package/dist/{hooks/useObjectEvents.svelte.d.ts → components/Entities/hooks/useEntityEvents.svelte.d.ts} +1 -1
- package/dist/{hooks/useObjectEvents.svelte.js → components/Entities/hooks/useEntityEvents.svelte.js} +6 -6
- package/dist/components/FileDrop/file-names.js +6 -3
- package/dist/components/FileDrop/snapshot-dropper.js +8 -4
- package/dist/components/FileDrop/useFileDrop.svelte.js +9 -6
- package/dist/components/Lasso/Lasso.svelte +4 -4
- package/dist/components/PCD.svelte +14 -6
- package/dist/components/PCD.svelte.d.ts +2 -0
- package/dist/components/Scene.svelte +1 -3
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/Selected.svelte +9 -9
- package/dist/components/StaticGeometries.svelte +6 -3
- package/dist/components/overlay/AddRelationship.svelte +1 -1
- package/dist/components/overlay/Details.svelte +3 -3
- package/dist/components/overlay/FloatingPanel.svelte +3 -0
- package/dist/components/overlay/FloatingPanel.svelte.d.ts +1 -0
- package/dist/components/overlay/LiveUpdatesBanner.svelte +4 -6
- package/dist/components/overlay/Logs.svelte +75 -0
- package/dist/components/overlay/left-pane/TreeContainer.svelte +0 -3
- package/dist/components/overlay/settings/Settings.svelte +11 -13
- package/dist/components/overlay/widgets/Camera.svelte +11 -9
- package/dist/components/xr/ArmTeleop.svelte +33 -33
- package/dist/components/xr/CameraFeed.svelte +21 -23
- package/dist/components/xr/JointLimitsWidget.svelte +19 -5
- package/dist/components/xr/XRConfigPanel.svelte +17 -16
- package/dist/components/xr/XRControllerSettings.svelte +5 -4
- package/dist/components/xr/XRToast.svelte +11 -6
- package/dist/ecs/relations.d.ts +1 -0
- package/dist/ecs/relations.js +1 -0
- package/dist/ecs/useQuery.svelte.js +3 -3
- package/dist/format.js +1 -1
- package/dist/hooks/use3DModels.svelte.js +35 -36
- package/dist/hooks/useConfigFrames.svelte.d.ts +9 -0
- package/dist/hooks/useConfigFrames.svelte.js +87 -0
- package/dist/hooks/useDrawAPI.svelte.js +1 -1
- package/dist/hooks/useFramelessComponents.svelte.js +1 -1
- package/dist/hooks/useFrames.svelte.d.ts +1 -6
- package/dist/hooks/useFrames.svelte.js +93 -192
- package/dist/hooks/useGeometries.svelte.js +1 -1
- package/dist/hooks/useLinked.svelte.js +5 -4
- package/dist/hooks/usePartConfig.svelte.js +17 -18
- package/dist/hooks/usePointcloudObjects.svelte.js +4 -4
- package/dist/hooks/usePointclouds.svelte.js +2 -4
- package/dist/hooks/usePose.svelte.js +3 -7
- package/dist/hooks/useResizable.svelte.js +4 -3
- package/dist/hooks/useSettings.svelte.js +2 -2
- package/dist/hooks/useVisibility.svelte.js +0 -12
- package/dist/hooks/useWeblabs.svelte.js +3 -2
- package/dist/hooks/useWorldState.svelte.js +6 -3
- package/dist/loaders/pcd/index.js +2 -1
- package/dist/loaders/pcd/worker.inline.d.ts +1 -1
- package/dist/loaders/pcd/worker.inline.js +1 -1
- package/dist/loaders/pcd/worker.js +1 -1
- package/dist/snapshot.js +7 -5
- package/dist/three/InstancedArrows/InstancedArrows.js +1 -1
- package/dist/three/InstancedArrows/box.js +1 -1
- package/dist/three/InstancedArrows/raycast.js +12 -12
- package/package.json +19 -11
- package/dist/components/overlay/left-pane/Logs.svelte +0 -52
- /package/dist/components/{Arrows → Entities/Arrows}/ArrowGroups.svelte.d.ts +0 -0
- /package/dist/components/{Entities.svelte.d.ts → Entities/Entities.svelte.d.ts} +0 -0
- /package/dist/components/{Frame.svelte.d.ts → Entities/Frame.svelte.d.ts} +0 -0
- /package/dist/components/{GLTF.svelte.d.ts → Entities/GLTF.svelte.d.ts} +0 -0
- /package/dist/components/{Geometry.svelte.d.ts → Entities/Geometry.svelte.d.ts} +0 -0
- /package/dist/components/{Label.svelte.d.ts → Entities/Label.svelte.d.ts} +0 -0
- /package/dist/components/{Line.svelte.d.ts → Entities/Line.svelte.d.ts} +0 -0
- /package/dist/components/{LineDots.svelte → Entities/LineDots.svelte} +0 -0
- /package/dist/components/{LineDots.svelte.d.ts → Entities/LineDots.svelte.d.ts} +0 -0
- /package/dist/components/{LineGeometry.svelte → Entities/LineGeometry.svelte} +0 -0
- /package/dist/components/{LineGeometry.svelte.d.ts → Entities/LineGeometry.svelte.d.ts} +0 -0
- /package/dist/components/{Points.svelte.d.ts → Entities/Points.svelte.d.ts} +0 -0
- /package/dist/components/{Pose.svelte.d.ts → Entities/Pose.svelte.d.ts} +0 -0
- /package/dist/components/overlay/{left-pane/Logs.svelte.d.ts → Logs.svelte.d.ts} +0 -0
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { Transform } from '@viamrobotics/sdk';
|
|
2
|
-
interface FrameTransform {
|
|
3
|
-
type: 'machine' | 'config' | 'fragment';
|
|
4
|
-
transform: Transform;
|
|
5
|
-
}
|
|
6
2
|
interface FramesContext {
|
|
7
|
-
current:
|
|
8
|
-
getParentFrameOptions: (componentName: string) => string[];
|
|
3
|
+
current: Transform[];
|
|
9
4
|
}
|
|
10
5
|
export declare const provideFrames: (partID: () => string) => void;
|
|
11
6
|
export declare const useFrames: () => FramesContext;
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { getContext, setContext, untrack } from 'svelte';
|
|
2
|
-
import { Transform } from '@viamrobotics/sdk';
|
|
3
|
-
import { useRobotClient, createRobotQuery, useMachineStatus } from '@viamrobotics/svelte-sdk';
|
|
2
|
+
import { MachineConnectionEvent, Transform } from '@viamrobotics/sdk';
|
|
3
|
+
import { useRobotClient, createRobotQuery, useMachineStatus, useConnectionStatus, } from '@viamrobotics/svelte-sdk';
|
|
4
|
+
import {} from 'koota';
|
|
4
5
|
import { useLogs } from './useLogs.svelte';
|
|
5
6
|
import { resourceNameToColor } from '../color';
|
|
6
|
-
import { createTransformFromFrame } from '../frame';
|
|
7
|
-
import { usePartConfig } from './usePartConfig.svelte';
|
|
8
7
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
9
8
|
import { createPose } from '../transform';
|
|
10
9
|
import { useResourceByName } from './useResourceByName.svelte';
|
|
11
10
|
import { traits, useWorld } from '../ecs';
|
|
11
|
+
import { useConfigFrames } from './useConfigFrames.svelte';
|
|
12
12
|
const key = Symbol('frames-context');
|
|
13
13
|
export const provideFrames = (partID) => {
|
|
14
|
+
const configFrames = useConfigFrames();
|
|
14
15
|
const environment = useEnvironment();
|
|
15
16
|
const world = useWorld();
|
|
16
17
|
const resourceByName = useResourceByName();
|
|
17
18
|
const client = useRobotClient(partID);
|
|
19
|
+
const connectionStatus = useConnectionStatus(partID);
|
|
18
20
|
const machineStatus = useMachineStatus(partID);
|
|
19
21
|
const logs = useLogs();
|
|
22
|
+
const isEditMode = $derived(environment.current.viewerMode === 'edit');
|
|
20
23
|
const query = createRobotQuery(client, 'frameSystemConfig', () => ({
|
|
21
|
-
enabled: partID() !== '' &&
|
|
24
|
+
enabled: partID() !== '' && !isEditMode,
|
|
22
25
|
}));
|
|
23
26
|
const revision = $derived(machineStatus.current?.config?.revision);
|
|
24
|
-
const partConfig = usePartConfig();
|
|
25
27
|
$effect(() => {
|
|
26
28
|
if (query.isFetching) {
|
|
27
29
|
logs.add('Fetching frames...');
|
|
@@ -30,218 +32,117 @@ export const provideFrames = (partID) => {
|
|
|
30
32
|
logs.add(`Frames: ${query.error.message}`, 'error');
|
|
31
33
|
}
|
|
32
34
|
});
|
|
33
|
-
$
|
|
34
|
-
if (partConfig.isDirty) {
|
|
35
|
-
environment.current.viewerMode = 'edit';
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
environment.current.viewerMode = 'monitor';
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
const machineFrames = $derived.by(() => {
|
|
35
|
+
const frames = $derived.by(() => {
|
|
42
36
|
const frames = {};
|
|
43
37
|
for (const { frame } of query.data ?? []) {
|
|
44
38
|
if (frame === undefined) {
|
|
45
39
|
continue;
|
|
46
40
|
}
|
|
47
|
-
frames[frame.referenceFrame] =
|
|
48
|
-
type: 'machine',
|
|
49
|
-
transform: frame,
|
|
50
|
-
};
|
|
41
|
+
frames[frame.referenceFrame] = frame;
|
|
51
42
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const results = {};
|
|
57
|
-
const unsetResults = [];
|
|
58
|
-
for (const { name, frame } of components ?? []) {
|
|
59
|
-
if (!frame) {
|
|
60
|
-
unsetResults.push(name);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
results[name] = {
|
|
64
|
-
type: 'config',
|
|
65
|
-
transform: createTransformFromFrame(name, frame),
|
|
43
|
+
if (isEditMode || connectionStatus.current === MachineConnectionEvent.DISCONNECTED) {
|
|
44
|
+
const mergedFrames = {
|
|
45
|
+
...frames,
|
|
46
|
+
...configFrames.current,
|
|
66
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Remove frames that have just been deleted locally for optimistic updates,
|
|
50
|
+
* or frames that have been removed by fragment overrides
|
|
51
|
+
*/
|
|
52
|
+
for (const name of configFrames.unsetFrames) {
|
|
53
|
+
delete mergedFrames[name];
|
|
54
|
+
}
|
|
55
|
+
return mergedFrames;
|
|
67
56
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const unsetResults = [];
|
|
75
|
-
// deal with fragment defined components
|
|
76
|
-
for (const fragmentComponentName of fragmentDefinedComponents || []) {
|
|
77
|
-
const fragmentId = partConfig.componentNameToFragmentId[fragmentComponentName];
|
|
78
|
-
const fragmentMod = fragmentMods?.find((mod) => mod.fragment_id === fragmentId);
|
|
79
|
-
if (!fragmentMod) {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
const setComponentModIndex = fragmentMod.mods.findLastIndex((mod) => mod['$set']?.[`components.${fragmentComponentName}.frame`] !== undefined);
|
|
83
|
-
const unsetComponentModIndex = fragmentMod.mods.findLastIndex((mod) => mod['$unset']?.[`components.${fragmentComponentName}.frame`] !== undefined);
|
|
84
|
-
if (setComponentModIndex < unsetComponentModIndex) {
|
|
85
|
-
unsetResults.push(fragmentComponentName);
|
|
86
|
-
}
|
|
87
|
-
else if (unsetComponentModIndex < setComponentModIndex) {
|
|
88
|
-
const frameData = fragmentMod.mods[setComponentModIndex]['$set'][`components.${fragmentComponentName}.frame`];
|
|
89
|
-
results[fragmentComponentName] = {
|
|
90
|
-
type: 'fragment',
|
|
91
|
-
transform: createTransformFromFrame(fragmentComponentName, frameData),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return [results, unsetResults];
|
|
96
|
-
});
|
|
97
|
-
const frames = $derived.by(() => {
|
|
98
|
-
const result = {
|
|
99
|
-
...machineFrames,
|
|
100
|
-
...configFrames,
|
|
101
|
-
...fragmentFrames,
|
|
102
|
-
};
|
|
103
|
-
// Remove frames that have just been deleted locally for optimistic updates
|
|
104
|
-
for (const name of configUnsetFrameNames) {
|
|
105
|
-
delete result[name];
|
|
106
|
-
}
|
|
107
|
-
// Remove frames that have been removed by fragment overrides
|
|
108
|
-
for (const name of fragmentUnsetFrameNames) {
|
|
109
|
-
delete result[name];
|
|
110
|
-
}
|
|
111
|
-
return result;
|
|
57
|
+
/**
|
|
58
|
+
* If we're not in edit mode and we have a robot connection,
|
|
59
|
+
* we only use frames reported by the machine
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
return frames;
|
|
112
63
|
});
|
|
113
64
|
const current = $derived(Object.values(frames));
|
|
114
65
|
const entities = new Map();
|
|
115
66
|
$effect.pre(() => {
|
|
116
67
|
if (revision) {
|
|
117
|
-
untrack(
|
|
118
|
-
await query.refetch();
|
|
119
|
-
for (const [name, machineFrame] of Object.entries(machineFrames)) {
|
|
120
|
-
if (machineFrame === undefined) {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
const existing = entities.get(name);
|
|
124
|
-
if (existing) {
|
|
125
|
-
const pose = createPose(machineFrame.transform.poseInObserverFrame?.pose);
|
|
126
|
-
existing.set(traits.Pose, pose);
|
|
127
|
-
if (environment.current.viewerMode === 'monitor') {
|
|
128
|
-
// if we are in monitor mode, we want the network pose to overwrite any leftover edited poses
|
|
129
|
-
existing.set(traits.EditedPose, pose);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
$effect.pre(() => {
|
|
137
|
-
for (const [name, configFrame] of Object.entries(configFrames)) {
|
|
138
|
-
if (configFrame === undefined) {
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
const existing = entities.get(name);
|
|
142
|
-
if (existing) {
|
|
143
|
-
const pose = createPose(configFrame.transform.poseInObserverFrame?.pose);
|
|
144
|
-
existing.set(traits.EditedPose, pose);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
$effect.pre(() => {
|
|
149
|
-
for (const [name, fragmentFrame] of Object.entries(fragmentFrames)) {
|
|
150
|
-
if (fragmentFrame === undefined) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
const existing = entities.get(name);
|
|
154
|
-
if (existing) {
|
|
155
|
-
const pose = createPose(fragmentFrame.transform.poseInObserverFrame?.pose);
|
|
156
|
-
existing.set(traits.EditedPose, pose);
|
|
157
|
-
}
|
|
68
|
+
untrack(() => query.refetch());
|
|
158
69
|
}
|
|
159
70
|
});
|
|
160
71
|
$effect.pre(() => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
72
|
+
if (current.length === 0)
|
|
73
|
+
return;
|
|
74
|
+
const currentResourcesByName = resourceByName.current;
|
|
75
|
+
// We only want to update whenever "current" or "resourceByName.current" changes
|
|
76
|
+
untrack(() => {
|
|
77
|
+
const active = {};
|
|
78
|
+
for (const frame of current) {
|
|
79
|
+
const name = frame.referenceFrame;
|
|
80
|
+
active[name] = true;
|
|
81
|
+
const parent = frame.poseInObserverFrame?.referenceFrame;
|
|
82
|
+
const pose = createPose(frame.poseInObserverFrame?.pose);
|
|
83
|
+
const center = frame.physicalObject?.center
|
|
84
|
+
? createPose(frame.physicalObject.center)
|
|
85
|
+
: undefined;
|
|
86
|
+
const resourceName = currentResourcesByName[frame.referenceFrame];
|
|
87
|
+
const color = resourceNameToColor(resourceName);
|
|
88
|
+
const existing = entities.get(name);
|
|
89
|
+
if (existing) {
|
|
90
|
+
if (!parent || parent === 'world') {
|
|
91
|
+
existing.remove(traits.Parent);
|
|
92
|
+
}
|
|
93
|
+
else if (parent && existing.has(traits.Parent)) {
|
|
94
|
+
existing.set(traits.Parent, parent);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
existing.add(traits.Parent(parent));
|
|
98
|
+
}
|
|
99
|
+
if (color) {
|
|
100
|
+
existing.set(traits.Color, color);
|
|
101
|
+
}
|
|
102
|
+
if (center) {
|
|
103
|
+
existing.set(traits.Center, center);
|
|
104
|
+
}
|
|
105
|
+
existing.remove(traits.Box, traits.Sphere, traits.BufferGeometry, traits.Capsule);
|
|
106
|
+
if (frame.physicalObject) {
|
|
107
|
+
const geometry = traits.Geometry(frame.physicalObject);
|
|
108
|
+
existing.add(geometry);
|
|
109
|
+
}
|
|
110
|
+
existing.set(traits.EditedPose, pose);
|
|
111
|
+
continue;
|
|
180
112
|
}
|
|
181
|
-
|
|
182
|
-
|
|
113
|
+
const entityTraits = [
|
|
114
|
+
traits.Name(name),
|
|
115
|
+
traits.Pose(pose),
|
|
116
|
+
traits.EditedPose(pose),
|
|
117
|
+
traits.FramesAPI,
|
|
118
|
+
traits.ShowAxesHelper,
|
|
119
|
+
];
|
|
120
|
+
if (parent && parent !== 'world') {
|
|
121
|
+
entityTraits.push(traits.Parent(parent));
|
|
183
122
|
}
|
|
184
123
|
if (color) {
|
|
185
|
-
|
|
124
|
+
entityTraits.push(traits.Color(color));
|
|
186
125
|
}
|
|
187
126
|
if (center) {
|
|
188
|
-
|
|
127
|
+
entityTraits.push(traits.Center(center));
|
|
189
128
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const geometry = traits.Geometry(frame.transform.physicalObject);
|
|
193
|
-
existing.add(geometry);
|
|
129
|
+
if (frame.physicalObject) {
|
|
130
|
+
entityTraits.push(traits.Geometry(frame.physicalObject));
|
|
194
131
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (parent && parent !== 'world') {
|
|
205
|
-
entityTraits.push(traits.Parent(parent));
|
|
206
|
-
}
|
|
207
|
-
if (color) {
|
|
208
|
-
entityTraits.push(traits.Color(color));
|
|
209
|
-
}
|
|
210
|
-
if (center) {
|
|
211
|
-
entityTraits.push(traits.Center(center));
|
|
212
|
-
}
|
|
213
|
-
if (frame.transform.physicalObject) {
|
|
214
|
-
entityTraits.push(traits.Geometry(frame.transform.physicalObject));
|
|
215
|
-
}
|
|
216
|
-
const entity = world.spawn(...entityTraits);
|
|
217
|
-
entities.set(name, entity);
|
|
218
|
-
}
|
|
219
|
-
// Clean up non-active entities
|
|
220
|
-
for (const [name, entity] of entities) {
|
|
221
|
-
if (!frames[name]) {
|
|
222
|
-
entity?.destroy();
|
|
223
|
-
entities.delete(name);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
const getParentFrameOptions = (componentName) => {
|
|
228
|
-
const validFrames = new Set(current.map((frame) => frame.transform.referenceFrame));
|
|
229
|
-
validFrames.add('world');
|
|
230
|
-
const frameNameQueue = [componentName];
|
|
231
|
-
while (frameNameQueue.length > 0) {
|
|
232
|
-
const frameName = frameNameQueue.shift();
|
|
233
|
-
if (frameName) {
|
|
234
|
-
validFrames.delete(frameName);
|
|
235
|
-
const frames = current.filter((frame) => frame.transform.poseInObserverFrame?.referenceFrame === frameName);
|
|
236
|
-
for (const frame of frames) {
|
|
237
|
-
frameNameQueue.push(frame.transform.referenceFrame);
|
|
132
|
+
const entity = world.spawn(...entityTraits);
|
|
133
|
+
entities.set(name, entity);
|
|
134
|
+
}
|
|
135
|
+
// Clean up non-active entities
|
|
136
|
+
for (const [name, entity] of entities) {
|
|
137
|
+
if (!active[name]) {
|
|
138
|
+
entity?.destroy();
|
|
139
|
+
entities.delete(name);
|
|
140
|
+
continue;
|
|
238
141
|
}
|
|
239
142
|
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
};
|
|
143
|
+
});
|
|
144
|
+
});
|
|
243
145
|
setContext(key, {
|
|
244
|
-
getParentFrameOptions,
|
|
245
146
|
get current() {
|
|
246
147
|
return current;
|
|
247
148
|
},
|
|
@@ -68,7 +68,7 @@ export const provideGeometries = (partID) => {
|
|
|
68
68
|
for (const geometry of query.data) {
|
|
69
69
|
index += 1;
|
|
70
70
|
const resourceName = resources.current[name];
|
|
71
|
-
const label = geometry.label
|
|
71
|
+
const label = geometry.label || `${name} geometry ${index}`;
|
|
72
72
|
active[`${name}:${label}`] = true;
|
|
73
73
|
const pose = createPose(geometry.center);
|
|
74
74
|
const subtype = resourceName?.subtype;
|
|
@@ -18,11 +18,12 @@ export const provideLinkedEntities = () => {
|
|
|
18
18
|
linkedEntities = linkedEntities.filter((e) => e !== target);
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
|
+
const unsub = () => {
|
|
22
|
+
unsubAdd();
|
|
23
|
+
unsubRemove();
|
|
24
|
+
};
|
|
21
25
|
$effect(() => {
|
|
22
|
-
return
|
|
23
|
-
unsubAdd();
|
|
24
|
-
unsubRemove();
|
|
25
|
-
};
|
|
26
|
+
return unsub;
|
|
26
27
|
});
|
|
27
28
|
setContext(linkedKey, {
|
|
28
29
|
get current() {
|
|
@@ -79,16 +79,16 @@ export const providePartConfig = (partID, params) => {
|
|
|
79
79
|
const existingFrameIndex = fragmentMod.mods.findLastIndex(
|
|
80
80
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
81
|
(mod) => mod?.['$set']?.[modSetPath] !== undefined);
|
|
82
|
-
if (existingFrameIndex
|
|
82
|
+
if (existingFrameIndex === -1) {
|
|
83
|
+
fragmentMod.mods.push(frame);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
83
86
|
const existingGeometry = fragmentMod.mods[existingFrameIndex]['$set']?.[modSetPath].geometry;
|
|
84
87
|
if (existingGeometry && !frameGeometry) {
|
|
85
88
|
frame['$set'][modSetPath].geometry = existingGeometry;
|
|
86
89
|
}
|
|
87
90
|
fragmentMod.mods[existingFrameIndex] = frame;
|
|
88
91
|
}
|
|
89
|
-
else {
|
|
90
|
-
fragmentMod.mods.push(frame);
|
|
91
|
-
}
|
|
92
92
|
config.set(newConfig);
|
|
93
93
|
};
|
|
94
94
|
const updatePartFrame = (componentName, referenceFrame, pose, geometry) => {
|
|
@@ -126,12 +126,11 @@ export const providePartConfig = (partID, params) => {
|
|
|
126
126
|
};
|
|
127
127
|
const deletePartFrame = (componentName) => {
|
|
128
128
|
const newConfig = getCurrent();
|
|
129
|
-
const component = newConfig?.components?.find((
|
|
130
|
-
if (
|
|
131
|
-
|
|
129
|
+
const component = newConfig?.components?.find(({ name }) => name === componentName);
|
|
130
|
+
if (component) {
|
|
131
|
+
delete component.frame;
|
|
132
|
+
config.set(newConfig);
|
|
132
133
|
}
|
|
133
|
-
delete component.frame;
|
|
134
|
-
config.set(newConfig);
|
|
135
134
|
};
|
|
136
135
|
const deleteFragmentFrame = (fragmentId, componentName) => {
|
|
137
136
|
const newConfig = getCurrent();
|
|
@@ -168,29 +167,29 @@ export const providePartConfig = (partID, params) => {
|
|
|
168
167
|
},
|
|
169
168
|
updateFrame: (componentName, referenceFrame, framePosition, frameGeometry) => {
|
|
170
169
|
const fragmentId = config.componentNameToFragmentId[componentName];
|
|
171
|
-
if (fragmentId
|
|
172
|
-
|
|
170
|
+
if (fragmentId === undefined) {
|
|
171
|
+
updatePartFrame(componentName, referenceFrame, framePosition, frameGeometry);
|
|
173
172
|
}
|
|
174
173
|
else {
|
|
175
|
-
|
|
174
|
+
updateFragmentFrame(fragmentId, componentName, referenceFrame, framePosition, frameGeometry);
|
|
176
175
|
}
|
|
177
176
|
},
|
|
178
177
|
deleteFrame: (componentName) => {
|
|
179
178
|
const fragmentId = config.componentNameToFragmentId[componentName];
|
|
180
|
-
if (fragmentId
|
|
181
|
-
|
|
179
|
+
if (fragmentId === undefined) {
|
|
180
|
+
deletePartFrame(componentName);
|
|
182
181
|
}
|
|
183
182
|
else {
|
|
184
|
-
|
|
183
|
+
deleteFragmentFrame(fragmentId, componentName);
|
|
185
184
|
}
|
|
186
185
|
},
|
|
187
186
|
createFrame: (componentName) => {
|
|
188
187
|
const fragmentId = config.componentNameToFragmentId[componentName];
|
|
189
|
-
if (fragmentId
|
|
190
|
-
|
|
188
|
+
if (fragmentId === undefined) {
|
|
189
|
+
createPartFrame(componentName);
|
|
191
190
|
}
|
|
192
191
|
else {
|
|
193
|
-
|
|
192
|
+
createFragmentFrame(fragmentId, componentName);
|
|
194
193
|
}
|
|
195
194
|
},
|
|
196
195
|
save: () => config.save?.(),
|
|
@@ -47,10 +47,10 @@ export const providePointcloudObjects = (partID) => {
|
|
|
47
47
|
*/
|
|
48
48
|
$effect(() => {
|
|
49
49
|
for (const [name, query] of propQueries) {
|
|
50
|
-
if (name &&
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (name &&
|
|
51
|
+
query.data?.objectPointCloudsSupported === false &&
|
|
52
|
+
disabledVisionServices.get(name) === undefined) {
|
|
53
|
+
disabledVisionServices.set(name, true);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
});
|
|
@@ -50,10 +50,8 @@ export const providePointclouds = (partID) => {
|
|
|
50
50
|
*/
|
|
51
51
|
$effect(() => {
|
|
52
52
|
for (const [name, query] of propQueries) {
|
|
53
|
-
if (name && query.data?.supportsPcd === false) {
|
|
54
|
-
|
|
55
|
-
disabledCameras.set(name, true);
|
|
56
|
-
}
|
|
53
|
+
if (name && query.data?.supportsPcd === false && disabledCameras.get(name) === undefined) {
|
|
54
|
+
disabledCameras.set(name, true);
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
});
|
|
@@ -10,7 +10,7 @@ import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
|
|
|
10
10
|
import { useLogs } from './useLogs.svelte';
|
|
11
11
|
import { useResourceByName } from './useResourceByName.svelte';
|
|
12
12
|
import { useRefetchPoses } from './useRefetchPoses';
|
|
13
|
-
const
|
|
13
|
+
const originFrameComponentTypes = new Set(['arm', 'gantry', 'gripper', 'base']);
|
|
14
14
|
export const usePose = (name, parent) => {
|
|
15
15
|
const environment = useEnvironment();
|
|
16
16
|
const logs = useLogs();
|
|
@@ -26,12 +26,8 @@ export const usePose = (name, parent) => {
|
|
|
26
26
|
const frames = useFrames();
|
|
27
27
|
let pose = $state();
|
|
28
28
|
const interval = $derived(refreshRates.get(RefreshRates.poses));
|
|
29
|
-
const resolvedParent = $derived(
|
|
30
|
-
|
|
31
|
-
: parent());
|
|
32
|
-
const resolvedName = $derived(origingFrameComponentTypes.includes(resource?.subtype ?? '')
|
|
33
|
-
? `${currentName}_origin`
|
|
34
|
-
: currentName);
|
|
29
|
+
const resolvedParent = $derived(originFrameComponentTypes.has(parentResource?.subtype ?? '') ? `${parent()}_origin` : parent());
|
|
30
|
+
const resolvedName = $derived(originFrameComponentTypes.has(resource?.subtype ?? '') ? `${currentName}_origin` : currentName);
|
|
35
31
|
const query = createRobotQuery(robotClient, 'getPose', () => [resolvedName, resolvedParent ?? 'world', []], () => ({
|
|
36
32
|
enabled: interval !== RefetchRates.OFF && environment.current.viewerMode === 'monitor',
|
|
37
33
|
refetchInterval: interval === RefetchRates.MANUAL ? false : interval,
|
|
@@ -28,10 +28,11 @@ export const useResizable = (name, defaultDimensions) => {
|
|
|
28
28
|
});
|
|
29
29
|
observer.observe(target);
|
|
30
30
|
};
|
|
31
|
+
const disconnect = () => {
|
|
32
|
+
observer?.disconnect();
|
|
33
|
+
};
|
|
31
34
|
$effect(() => {
|
|
32
|
-
return
|
|
33
|
-
observer?.disconnect();
|
|
34
|
-
};
|
|
35
|
+
return disconnect;
|
|
35
36
|
});
|
|
36
37
|
return {
|
|
37
38
|
get current() {
|
|
@@ -30,11 +30,11 @@ const defaults = () => ({
|
|
|
30
30
|
renderSubEntityHoverDetail: false,
|
|
31
31
|
xrController: {
|
|
32
32
|
left: {
|
|
33
|
-
scaleFactor: 1
|
|
33
|
+
scaleFactor: 1,
|
|
34
34
|
rotationEnabled: true,
|
|
35
35
|
},
|
|
36
36
|
right: {
|
|
37
|
-
scaleFactor: 1
|
|
37
|
+
scaleFactor: 1,
|
|
38
38
|
rotationEnabled: true,
|
|
39
39
|
},
|
|
40
40
|
},
|
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
import { get, set } from 'idb-keyval';
|
|
2
1
|
import { getContext, setContext } from 'svelte';
|
|
3
2
|
import { SvelteMap } from 'svelte/reactivity';
|
|
4
3
|
const key = Symbol('object-visibility-context');
|
|
5
|
-
const idbKey = 'object-visibility';
|
|
6
4
|
export const provideVisibility = () => {
|
|
7
5
|
const map = new SvelteMap();
|
|
8
|
-
get(idbKey).then((entries) => {
|
|
9
|
-
if (entries) {
|
|
10
|
-
for (const [key, value] of entries) {
|
|
11
|
-
map.set(key, value);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
$effect(() => {
|
|
16
|
-
set(idbKey, [...map.entries()]);
|
|
17
|
-
});
|
|
18
6
|
setContext(key, map);
|
|
19
7
|
};
|
|
20
8
|
export const useVisibility = () => {
|
|
@@ -17,6 +17,7 @@ const addCookie = (name, value, days, path = '/') => {
|
|
|
17
17
|
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); // days in milliseconds
|
|
18
18
|
expires = '; expires=' + date.toUTCString();
|
|
19
19
|
}
|
|
20
|
+
// eslint-disable-next-line unicorn/no-document-cookie
|
|
20
21
|
document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}${expires}; path=${path}`;
|
|
21
22
|
};
|
|
22
23
|
const getCookieExperiments = () => {
|
|
@@ -44,10 +45,10 @@ export const createWeblabs = () => {
|
|
|
44
45
|
};
|
|
45
46
|
};
|
|
46
47
|
export const provideWeblabs = () => {
|
|
47
|
-
const urlExperiment = new URLSearchParams(
|
|
48
|
+
const urlExperiment = new URLSearchParams(globalThis.location.search).get('experiment');
|
|
48
49
|
if (urlExperiment) {
|
|
49
50
|
const experimentSet = new Set([...getCookieExperiments(), urlExperiment]);
|
|
50
|
-
addCookie('weblab_experiments',
|
|
51
|
+
addCookie('weblab_experiments', [...experimentSet].join(','));
|
|
51
52
|
}
|
|
52
53
|
setContext(WEBLABS_CONTEXT_KEY, createWeblabs());
|
|
53
54
|
};
|
|
@@ -189,15 +189,17 @@ const createWorldState = (client) => {
|
|
|
189
189
|
continue;
|
|
190
190
|
}
|
|
191
191
|
switch (event.changeType) {
|
|
192
|
-
case TransformChangeType.REMOVED:
|
|
192
|
+
case TransformChangeType.REMOVED: {
|
|
193
193
|
eventsByUUID.set(uuid, event);
|
|
194
194
|
break;
|
|
195
|
-
|
|
195
|
+
}
|
|
196
|
+
case TransformChangeType.ADDED: {
|
|
196
197
|
if (existing.changeType !== TransformChangeType.REMOVED) {
|
|
197
198
|
eventsByUUID.set(uuid, event);
|
|
198
199
|
}
|
|
199
200
|
break;
|
|
200
|
-
|
|
201
|
+
}
|
|
202
|
+
case TransformChangeType.UPDATED: {
|
|
201
203
|
// merge with existing updated event
|
|
202
204
|
if (existing.changeType === TransformChangeType.UPDATED) {
|
|
203
205
|
existing.updatedFields ??= { paths: [] };
|
|
@@ -214,6 +216,7 @@ const createWorldState = (client) => {
|
|
|
214
216
|
eventsByUUID.set(uuid, event);
|
|
215
217
|
}
|
|
216
218
|
break;
|
|
219
|
+
}
|
|
217
220
|
}
|
|
218
221
|
}
|
|
219
222
|
pendingEvents.push(...eventsByUUID.values());
|
|
@@ -22,6 +22,7 @@ export const parsePcdInWorker = (data) => {
|
|
|
22
22
|
return new Promise((resolve, reject) => {
|
|
23
23
|
const id = ++requestId;
|
|
24
24
|
pending.set(id, { resolve, reject });
|
|
25
|
-
|
|
25
|
+
const copy = new Uint8Array(data);
|
|
26
|
+
worker.postMessage({ id, data: copy }, [copy.buffer]);
|
|
26
27
|
});
|
|
27
28
|
};
|