@viamrobotics/motion-tools 0.15.0 → 0.15.2
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/color.d.ts +2 -0
- package/dist/color.js +6 -0
- package/dist/components/SceneProviders.svelte +3 -1
- package/dist/geometry.d.ts +2 -0
- package/dist/geometry.js +34 -0
- package/dist/hooks/useFrames.svelte.js +13 -51
- package/dist/hooks/usePose.svelte.js +7 -11
- package/dist/hooks/useResourceByName.svelte.d.ts +7 -0
- package/dist/hooks/useResourceByName.svelte.js +21 -0
- package/package.json +1 -1
package/dist/color.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Color, type ColorRepresentation, type RGB } from 'three';
|
|
2
|
+
import { ResourceName } from '@viamrobotics/sdk';
|
|
2
3
|
/**
|
|
3
4
|
* Darkens a THREE.Color by a given percentage while preserving hue.
|
|
4
5
|
* @param color The original THREE.Color instance.
|
|
@@ -6,6 +7,7 @@ import { Color, type ColorRepresentation, type RGB } from 'three';
|
|
|
6
7
|
* @returns A new THREE.Color instance with the darkened color.
|
|
7
8
|
*/
|
|
8
9
|
export declare const darkenColor: (value: ColorRepresentation, percent: number) => Color;
|
|
10
|
+
export declare const resourceNameToColor: (resourceName?: ResourceName) => Color | undefined;
|
|
9
11
|
export declare const colors: {
|
|
10
12
|
readonly default: string;
|
|
11
13
|
};
|
package/dist/color.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Color } from 'three';
|
|
2
2
|
import twColors from 'tailwindcss/colors';
|
|
3
3
|
import { isNumber } from 'lodash-es';
|
|
4
|
+
import { ResourceName } from '@viamrobotics/sdk';
|
|
4
5
|
// Step 3: linear sRGB → sRGB
|
|
5
6
|
const linearToSrgb = (x) => {
|
|
6
7
|
return x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
|
|
@@ -53,6 +54,11 @@ export const darkenColor = (value, percent) => {
|
|
|
53
54
|
return new Color().setHSL(hsl.h, hsl.s, hsl.l);
|
|
54
55
|
};
|
|
55
56
|
const darkness = '600';
|
|
57
|
+
export const resourceNameToColor = (resourceName) => {
|
|
58
|
+
return resourceName
|
|
59
|
+
? new Color(resourceColors[resourceName.subtype])
|
|
60
|
+
: undefined;
|
|
61
|
+
};
|
|
56
62
|
export const colors = {
|
|
57
63
|
default: oklchToHex(twColors.red[darkness]),
|
|
58
64
|
};
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { provideArmClient } from '../hooks/useArmClient.svelte'
|
|
19
19
|
import { provideArrows } from '../hooks/useArrows.svelte'
|
|
20
20
|
import { provideFramelessComponents } from '../hooks/useFramelessComponents.svelte'
|
|
21
|
+
import { provideResourceByName } from '../hooks/useResourceByName.svelte'
|
|
21
22
|
interface Props {
|
|
22
23
|
children: Snippet<[{ focus: boolean }]>
|
|
23
24
|
}
|
|
@@ -36,13 +37,14 @@
|
|
|
36
37
|
provideStaticGeometries()
|
|
37
38
|
provideDrawAPI()
|
|
38
39
|
|
|
40
|
+
provideResourceByName(() => partID.current)
|
|
39
41
|
provideFrames(() => partID.current)
|
|
40
42
|
provideGeometries(() => partID.current)
|
|
41
43
|
providePointclouds(() => partID.current)
|
|
42
44
|
provideMotionClient(() => partID.current)
|
|
45
|
+
provideArmClient(() => partID.current)
|
|
43
46
|
provideObjects()
|
|
44
47
|
provideWorldStates()
|
|
45
|
-
provideArmClient(() => partID.current)
|
|
46
48
|
provideFramelessComponents()
|
|
47
49
|
|
|
48
50
|
const { focus } = provideSelection()
|
package/dist/geometry.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { Geometry } from '@viamrobotics/sdk';
|
|
2
|
+
import type { Frame } from './frame';
|
|
2
3
|
export declare const createGeometry: (geometryType?: Geometry["geometryType"], label?: string) => Geometry;
|
|
4
|
+
export declare const createGeometryFromFrame: (frame: Frame) => import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").Geometry> | undefined;
|
package/dist/geometry.js
CHANGED
|
@@ -6,3 +6,37 @@ export const createGeometry = (geometryType, label = '') => {
|
|
|
6
6
|
geometryType: geometryType ?? { case: undefined, value: undefined },
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
|
+
export const createGeometryFromFrame = (frame) => {
|
|
10
|
+
if (!frame.geometry) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (frame.geometry.type === 'box') {
|
|
14
|
+
return createGeometry({
|
|
15
|
+
case: 'box',
|
|
16
|
+
value: {
|
|
17
|
+
dimsMm: {
|
|
18
|
+
x: frame.geometry.x,
|
|
19
|
+
y: frame.geometry.y,
|
|
20
|
+
z: frame.geometry.z,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (frame.geometry.type === 'sphere') {
|
|
26
|
+
return createGeometry({
|
|
27
|
+
case: 'sphere',
|
|
28
|
+
value: {
|
|
29
|
+
radiusMm: frame.geometry.r,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (frame.geometry.type === 'capsule') {
|
|
34
|
+
return createGeometry({
|
|
35
|
+
case: 'capsule',
|
|
36
|
+
value: {
|
|
37
|
+
radiusMm: frame.geometry.r,
|
|
38
|
+
lengthMm: frame.geometry.l,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { getContext, setContext, untrack } from 'svelte';
|
|
2
|
-
import { useRobotClient, createRobotQuery, useMachineStatus
|
|
2
|
+
import { useRobotClient, createRobotQuery, useMachineStatus } from '@viamrobotics/svelte-sdk';
|
|
3
3
|
import { WorldObject } from '../WorldObject.svelte';
|
|
4
4
|
import { useLogs } from './useLogs.svelte';
|
|
5
|
-
import {
|
|
5
|
+
import { resourceNameToColor } from '../color';
|
|
6
6
|
import { usePartConfig } from './usePartConfig.svelte';
|
|
7
|
-
import { Color } from 'three';
|
|
8
7
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
9
8
|
import { createPoseFromFrame } from '../transform';
|
|
10
|
-
import {
|
|
9
|
+
import { createGeometryFromFrame } from '../geometry';
|
|
10
|
+
import { useResourceByName } from './useResourceByName.svelte';
|
|
11
11
|
const key = Symbol('frames-context');
|
|
12
12
|
export const provideFrames = (partID) => {
|
|
13
|
-
const
|
|
13
|
+
const resourceByName = useResourceByName();
|
|
14
14
|
const client = useRobotClient(partID);
|
|
15
15
|
const machineStatus = useMachineStatus(partID);
|
|
16
16
|
const logs = useLogs();
|
|
@@ -18,8 +18,10 @@ export const provideFrames = (partID) => {
|
|
|
18
18
|
const revision = $derived(machineStatus.current?.config?.revision);
|
|
19
19
|
const partConfig = usePartConfig();
|
|
20
20
|
const environment = useEnvironment();
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
$effect.pre(() => {
|
|
22
|
+
if (revision) {
|
|
23
|
+
untrack(() => query.current).refetch();
|
|
24
|
+
}
|
|
23
25
|
logs.add('Fetching frames...');
|
|
24
26
|
});
|
|
25
27
|
$effect.pre(() => {
|
|
@@ -36,13 +38,10 @@ export const provideFrames = (partID) => {
|
|
|
36
38
|
if (frame === undefined) {
|
|
37
39
|
continue;
|
|
38
40
|
}
|
|
39
|
-
const resourceName =
|
|
41
|
+
const resourceName = resourceByName.current[frame.referenceFrame];
|
|
40
42
|
const frameName = frame.referenceFrame ? frame.referenceFrame : 'Unnamed frame';
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
color: new Color(resourceColors[resourceName.subtype]),
|
|
44
|
-
}
|
|
45
|
-
: undefined));
|
|
43
|
+
const color = resourceNameToColor(resourceName);
|
|
44
|
+
objects.push(new WorldObject(frameName, frame.poseInObserverFrame?.pose, frame.poseInObserverFrame?.referenceFrame, frame.physicalObject, color ? { color } : undefined));
|
|
46
45
|
}
|
|
47
46
|
return objects;
|
|
48
47
|
});
|
|
@@ -56,44 +55,7 @@ export const provideFrames = (partID) => {
|
|
|
56
55
|
worldObject.referenceFrame = component.frame.parent;
|
|
57
56
|
worldObject.localEditedPose = createPoseFromFrame(component.frame);
|
|
58
57
|
if (component.frame.geometry) {
|
|
59
|
-
|
|
60
|
-
case 'box':
|
|
61
|
-
worldObject.geometry = {
|
|
62
|
-
...worldObject.geometry,
|
|
63
|
-
geometryType: {
|
|
64
|
-
case: 'box',
|
|
65
|
-
value: {
|
|
66
|
-
dimsMm: {
|
|
67
|
-
x: component.frame.geometry.x,
|
|
68
|
-
y: component.frame.geometry.y,
|
|
69
|
-
z: component.frame.geometry.z,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
break;
|
|
75
|
-
case 'sphere':
|
|
76
|
-
worldObject.geometry = {
|
|
77
|
-
...worldObject.geometry,
|
|
78
|
-
geometryType: { case: 'sphere', value: { radiusMm: component.frame.geometry.r } },
|
|
79
|
-
};
|
|
80
|
-
break;
|
|
81
|
-
case 'capsule':
|
|
82
|
-
worldObject.geometry = {
|
|
83
|
-
...worldObject.geometry,
|
|
84
|
-
geometryType: {
|
|
85
|
-
case: 'capsule',
|
|
86
|
-
value: {
|
|
87
|
-
radiusMm: component.frame.geometry.r,
|
|
88
|
-
lengthMm: component.frame.geometry.l,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
break;
|
|
93
|
-
default:
|
|
94
|
-
worldObject.geometry = undefined;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
58
|
+
worldObject.geometry = createGeometryFromFrame(component.frame);
|
|
97
59
|
}
|
|
98
60
|
else {
|
|
99
61
|
worldObject.geometry = undefined;
|
|
@@ -21,23 +21,15 @@ export const usePose = (name, parent) => {
|
|
|
21
21
|
const options = $derived(queryOptions({
|
|
22
22
|
enabled: interval !== -1 &&
|
|
23
23
|
client.current !== undefined &&
|
|
24
|
-
resource !== undefined &&
|
|
25
24
|
environment.current.viewerMode === 'monitor',
|
|
26
25
|
refetchInterval: interval === 0 ? false : interval,
|
|
27
|
-
queryKey: [
|
|
28
|
-
'partID',
|
|
29
|
-
partID.current,
|
|
30
|
-
client.current?.name,
|
|
31
|
-
'getPose',
|
|
32
|
-
resource?.name,
|
|
33
|
-
parent(),
|
|
34
|
-
],
|
|
26
|
+
queryKey: ['partID', partID.current, client.current?.name, 'getPose', name(), parent()],
|
|
35
27
|
queryFn: async () => {
|
|
36
|
-
if (!client.current
|
|
28
|
+
if (!client.current) {
|
|
37
29
|
throw new Error('No client');
|
|
38
30
|
}
|
|
39
31
|
const resolvedParent = parentResource?.subtype === 'arm' ? `${parent()}_origin` : parent();
|
|
40
|
-
const pose = await client.current.getPose(
|
|
32
|
+
const pose = await client.current.getPose(name(), resolvedParent ?? 'world', []);
|
|
41
33
|
return pose;
|
|
42
34
|
},
|
|
43
35
|
}));
|
|
@@ -49,6 +41,10 @@ export const usePose = (name, parent) => {
|
|
|
49
41
|
});
|
|
50
42
|
return {
|
|
51
43
|
get current() {
|
|
44
|
+
/**
|
|
45
|
+
* Do not return the pose of an arm because in this case the pose represents
|
|
46
|
+
* the end effector frame and not the origin frame
|
|
47
|
+
*/
|
|
52
48
|
if (resource?.subtype === 'arm') {
|
|
53
49
|
return;
|
|
54
50
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResourceName } from '@viamrobotics/sdk';
|
|
2
|
+
interface Context {
|
|
3
|
+
current: Record<string, ResourceName>;
|
|
4
|
+
}
|
|
5
|
+
export declare const provideResourceByName: (partID: () => string) => void;
|
|
6
|
+
export declare const useResourceByName: () => Context;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
const key = Symbol('resource-by-name-context');
|
|
4
|
+
export const provideResourceByName = (partID) => {
|
|
5
|
+
const resourceNames = useResourceNames(partID);
|
|
6
|
+
const resourceByName = $derived.by(() => {
|
|
7
|
+
const results = {};
|
|
8
|
+
for (const resourceName of resourceNames.current) {
|
|
9
|
+
results[resourceName.name] = resourceName;
|
|
10
|
+
}
|
|
11
|
+
return results;
|
|
12
|
+
});
|
|
13
|
+
setContext(key, {
|
|
14
|
+
get current() {
|
|
15
|
+
return resourceByName;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const useResourceByName = () => {
|
|
20
|
+
return getContext(key);
|
|
21
|
+
};
|