@viamrobotics/motion-tools 0.15.3 → 0.16.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/components/App.svelte +33 -29
- package/dist/components/App.svelte.d.ts +5 -0
- package/dist/components/CameraControls.svelte +8 -23
- package/dist/components/Details.svelte +4 -1
- package/dist/components/KeyboardControls.svelte +4 -1
- package/dist/components/Pointcloud.svelte +4 -1
- package/dist/components/SceneProviders.svelte +9 -2
- package/dist/components/SceneProviders.svelte.d.ts +2 -0
- package/dist/components/Selected.svelte +4 -1
- package/dist/components/xr/CameraFeed.svelte +3 -1
- package/dist/components/xr/OriginMarker.svelte +3 -1
- package/dist/hooks/useControls.svelte.d.ts +15 -2
- package/dist/hooks/useControls.svelte.js +31 -3
- package/dist/hooks/useDrawAPI.svelte.d.ts +0 -7
- package/dist/hooks/useDrawAPI.svelte.js +10 -15
- package/dist/transform.d.ts +1 -1
- package/dist/transform.js +7 -2
- package/package.json +1 -1
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
import Details from './Details.svelte'
|
|
10
10
|
import SceneProviders from './SceneProviders.svelte'
|
|
11
11
|
import XR from './xr/XR.svelte'
|
|
12
|
-
import { World } from '@threlte/rapier'
|
|
13
12
|
import { createPartIDContext } from '../hooks/usePartID.svelte'
|
|
14
13
|
import Dashboard from './dashboard/Dashboard.svelte'
|
|
15
14
|
import { domPortal } from '../portal'
|
|
@@ -21,6 +20,7 @@
|
|
|
21
20
|
import LiveUpdatesBanner from './LiveUpdatesBanner.svelte'
|
|
22
21
|
import ArmPositions from './widgets/ArmPositions.svelte'
|
|
23
22
|
import { provideEnvironment } from '../hooks/useEnvironment.svelte'
|
|
23
|
+
import type { CameraPose } from '../hooks/useControls.svelte'
|
|
24
24
|
|
|
25
25
|
interface LocalConfigProps {
|
|
26
26
|
getLocalPartConfig: () => Struct
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
enableKeybindings?: boolean
|
|
35
35
|
children?: Snippet
|
|
36
36
|
localConfigProps?: LocalConfigProps
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Allows setting the initial camera pose
|
|
40
|
+
*/
|
|
41
|
+
cameraPose?: CameraPose
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
let {
|
|
@@ -41,6 +46,7 @@
|
|
|
41
46
|
enableKeybindings = true,
|
|
42
47
|
children: appChildren,
|
|
43
48
|
localConfigProps,
|
|
49
|
+
cameraPose,
|
|
44
50
|
}: Props = $props()
|
|
45
51
|
|
|
46
52
|
const appClient = useViamClient()
|
|
@@ -87,34 +93,32 @@
|
|
|
87
93
|
class="relative h-full w-full overflow-hidden"
|
|
88
94
|
bind:this={root}
|
|
89
95
|
>
|
|
90
|
-
<Canvas renderMode="
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
</SceneProviders>
|
|
117
|
-
</World>
|
|
96
|
+
<Canvas renderMode="on-demand">
|
|
97
|
+
<SceneProviders {cameraPose}>
|
|
98
|
+
{#snippet children({ focus })}
|
|
99
|
+
<Scene>
|
|
100
|
+
{@render appChildren?.()}
|
|
101
|
+
</Scene>
|
|
102
|
+
|
|
103
|
+
<XR {@attach domPortal(root)} />
|
|
104
|
+
|
|
105
|
+
<Dashboard {@attach domPortal(root)} />
|
|
106
|
+
<Details {@attach domPortal(root)} />
|
|
107
|
+
{#if environment.current.isStandalone}
|
|
108
|
+
<LiveUpdatesBanner {@attach domPortal(root)} />
|
|
109
|
+
{/if}
|
|
110
|
+
|
|
111
|
+
{#if !focus}
|
|
112
|
+
<TreeContainer {@attach domPortal(root)} />
|
|
113
|
+
{/if}
|
|
114
|
+
|
|
115
|
+
{#if !focus && settings.current.enableArmPositionsWidget}
|
|
116
|
+
<ArmPositions {@attach domPortal(root)} />
|
|
117
|
+
{/if}
|
|
118
|
+
|
|
119
|
+
<FileDrop {@attach domPortal(root)} />
|
|
120
|
+
{/snippet}
|
|
121
|
+
</SceneProviders>
|
|
118
122
|
</Canvas>
|
|
119
123
|
|
|
120
124
|
<ToastContainer />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { Struct } from '@viamrobotics/sdk';
|
|
3
|
+
import type { CameraPose } from '../hooks/useControls.svelte';
|
|
3
4
|
interface LocalConfigProps {
|
|
4
5
|
getLocalPartConfig: () => Struct;
|
|
5
6
|
setLocalPartConfig: (config: Struct) => void;
|
|
@@ -11,6 +12,10 @@ interface Props {
|
|
|
11
12
|
enableKeybindings?: boolean;
|
|
12
13
|
children?: Snippet;
|
|
13
14
|
localConfigProps?: LocalConfigProps;
|
|
15
|
+
/**
|
|
16
|
+
* Allows setting the initial camera pose
|
|
17
|
+
*/
|
|
18
|
+
cameraPose?: CameraPose;
|
|
14
19
|
}
|
|
15
20
|
declare const App: import("svelte").Component<Props, {}, "">;
|
|
16
21
|
type App = ReturnType<typeof App>;
|
|
@@ -1,36 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { MathUtils } from 'three'
|
|
3
3
|
import { CameraControls, type CameraControlsRef, Gizmo } from '@threlte/extras'
|
|
4
|
-
import { useTransformControls } from '../hooks/useControls.svelte'
|
|
4
|
+
import { useCameraControls, useTransformControls } from '../hooks/useControls.svelte'
|
|
5
5
|
import KeyboardControls from './KeyboardControls.svelte'
|
|
6
6
|
import Portal from './portal/Portal.svelte'
|
|
7
7
|
import Button from './dashboard/Button.svelte'
|
|
8
|
-
import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
|
|
9
8
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
10
9
|
|
|
10
|
+
const cameraControls = useCameraControls()
|
|
11
11
|
const settings = useSettings()
|
|
12
|
-
const drawAPI = useDrawAPI()
|
|
13
12
|
const transformControls = useTransformControls()
|
|
14
13
|
|
|
15
14
|
const enableKeybindings = $derived(settings.current.enableKeybindings)
|
|
16
|
-
|
|
17
|
-
let ref = $state.raw<CameraControlsRef>()
|
|
18
|
-
|
|
19
|
-
$effect(() => {
|
|
20
|
-
if (drawAPI.camera) {
|
|
21
|
-
const { position, lookAt, animate } = drawAPI.camera
|
|
22
|
-
ref?.setPosition(position.x, position.y, position.z, animate)
|
|
23
|
-
ref?.setLookAt(position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, animate)
|
|
24
|
-
drawAPI.clearCamera()
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
$effect(() => {
|
|
29
|
-
if (ref) {
|
|
30
|
-
;(window as unknown as { MathUtils: typeof MathUtils }).MathUtils = MathUtils
|
|
31
|
-
;(window as unknown as { cameraControls: CameraControlsRef }).cameraControls = ref
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
15
|
</script>
|
|
35
16
|
|
|
36
17
|
<Portal id="dashboard">
|
|
@@ -40,15 +21,19 @@
|
|
|
40
21
|
icon="camera-outline"
|
|
41
22
|
description="Reset camera"
|
|
42
23
|
onclick={() => {
|
|
43
|
-
|
|
24
|
+
cameraControls.current?.reset(true)
|
|
44
25
|
}}
|
|
45
26
|
/>
|
|
46
27
|
</fieldset>
|
|
47
28
|
</Portal>
|
|
48
29
|
|
|
49
30
|
<CameraControls
|
|
50
|
-
bind:ref
|
|
51
31
|
enabled={!transformControls.active}
|
|
32
|
+
oncreate={(ref) => {
|
|
33
|
+
cameraControls.set(ref)
|
|
34
|
+
;(window as unknown as { MathUtils: typeof MathUtils }).MathUtils = MathUtils
|
|
35
|
+
;(window as unknown as { cameraControls: CameraControlsRef }).cameraControls = ref
|
|
36
|
+
}}
|
|
52
37
|
>
|
|
53
38
|
{#snippet children({ ref }: { ref: CameraControlsRef })}
|
|
54
39
|
{#if enableKeybindings}
|
|
@@ -66,7 +66,10 @@
|
|
|
66
66
|
// resized to half zoom to take up the same screen space.
|
|
67
67
|
material.size = pointSize * ((camera.current as OrthographicCamera).zoom / 2)
|
|
68
68
|
},
|
|
69
|
-
{
|
|
69
|
+
{
|
|
70
|
+
autoStart: false,
|
|
71
|
+
autoInvalidate: false,
|
|
72
|
+
}
|
|
70
73
|
)
|
|
71
74
|
|
|
72
75
|
$effect(() => {
|
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
import { provideVisibility } from '../hooks/useVisibility.svelte'
|
|
10
10
|
import { provideDrawAPI } from '../hooks/useDrawAPI.svelte'
|
|
11
11
|
import { provideMachineSettings } from '../hooks/useMachineSettings.svelte'
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
provideCameraControls,
|
|
14
|
+
provideTransformControls,
|
|
15
|
+
type CameraPose,
|
|
16
|
+
} from '../hooks/useControls.svelte'
|
|
13
17
|
import { provideObjects } from '../hooks/useObjects.svelte'
|
|
14
18
|
import { provideMotionClient } from '../hooks/useMotionClient.svelte'
|
|
15
19
|
import { provideLogs } from '../hooks/useLogs.svelte'
|
|
@@ -19,14 +23,17 @@
|
|
|
19
23
|
import { provideArrows } from '../hooks/useArrows.svelte'
|
|
20
24
|
import { provideFramelessComponents } from '../hooks/useFramelessComponents.svelte'
|
|
21
25
|
import { provideResourceByName } from '../hooks/useResourceByName.svelte'
|
|
26
|
+
|
|
22
27
|
interface Props {
|
|
28
|
+
cameraPose?: CameraPose
|
|
23
29
|
children: Snippet<[{ focus: boolean }]>
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
let { children }: Props = $props()
|
|
32
|
+
let { cameraPose, children }: Props = $props()
|
|
27
33
|
|
|
28
34
|
const partID = usePartID()
|
|
29
35
|
|
|
36
|
+
provideCameraControls(() => cameraPose)
|
|
30
37
|
provideTransformControls()
|
|
31
38
|
provideVisibility()
|
|
32
39
|
provideMachineSettings()
|
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CameraControlsRef } from '@threlte/extras';
|
|
2
|
+
import type { Vector3Tuple } from 'three';
|
|
3
|
+
export interface CameraPose {
|
|
4
|
+
position: Vector3Tuple;
|
|
5
|
+
lookAt: Vector3Tuple;
|
|
6
|
+
}
|
|
7
|
+
interface CameraControlsContext {
|
|
8
|
+
current: CameraControlsRef | undefined;
|
|
9
|
+
set(current: CameraControlsRef): void;
|
|
10
|
+
setPose(pose: CameraPose, animate?: boolean): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const provideCameraControls: (cameraPose: () => CameraPose | undefined) => void;
|
|
13
|
+
export declare const useCameraControls: () => CameraControlsContext;
|
|
14
|
+
interface TransformControlsContext {
|
|
2
15
|
active: boolean;
|
|
3
16
|
setActive: (value: boolean) => void;
|
|
4
17
|
}
|
|
5
18
|
export declare const provideTransformControls: () => void;
|
|
6
|
-
export declare const useTransformControls: () =>
|
|
19
|
+
export declare const useTransformControls: () => TransformControlsContext;
|
|
7
20
|
export {};
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
|
-
const
|
|
2
|
+
const TRANSFORM_CONTROLS_KEY = Symbol('tranform-controls-context');
|
|
3
|
+
const CAMERA_CONTROLS_KEY = Symbol('camera-controls-context');
|
|
4
|
+
export const provideCameraControls = (cameraPose) => {
|
|
5
|
+
let controls = $state.raw();
|
|
6
|
+
const setPose = (pose, animate = false) => {
|
|
7
|
+
const [x, y, z] = pose.position;
|
|
8
|
+
const [lookAtX, lookAtY, lookAtZ] = pose.lookAt;
|
|
9
|
+
controls?.setPosition(x, y, z, animate);
|
|
10
|
+
controls?.setLookAt(x, y, z, lookAtX, lookAtY, lookAtZ, animate);
|
|
11
|
+
};
|
|
12
|
+
$effect(() => {
|
|
13
|
+
const pose = cameraPose();
|
|
14
|
+
if (pose) {
|
|
15
|
+
setPose(pose);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
setContext(CAMERA_CONTROLS_KEY, {
|
|
19
|
+
get current() {
|
|
20
|
+
return controls;
|
|
21
|
+
},
|
|
22
|
+
set(current) {
|
|
23
|
+
controls = current;
|
|
24
|
+
},
|
|
25
|
+
setPose,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const useCameraControls = () => {
|
|
29
|
+
return getContext(CAMERA_CONTROLS_KEY);
|
|
30
|
+
};
|
|
3
31
|
export const provideTransformControls = () => {
|
|
4
32
|
let active = $state(false);
|
|
5
|
-
setContext(
|
|
33
|
+
setContext(TRANSFORM_CONTROLS_KEY, {
|
|
6
34
|
get active() {
|
|
7
35
|
return active;
|
|
8
36
|
},
|
|
@@ -12,5 +40,5 @@ export const provideTransformControls = () => {
|
|
|
12
40
|
});
|
|
13
41
|
};
|
|
14
42
|
export const useTransformControls = () => {
|
|
15
|
-
return getContext(
|
|
43
|
+
return getContext(TRANSFORM_CONTROLS_KEY);
|
|
16
44
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Vector3 } from 'three';
|
|
2
1
|
import { WorldObject, type PointsGeometry } from '../WorldObject.svelte';
|
|
3
2
|
type ConnectionStatus = 'connecting' | 'open' | 'closed';
|
|
4
3
|
interface Context {
|
|
@@ -10,14 +9,8 @@ interface Context {
|
|
|
10
9
|
nurbs: WorldObject[];
|
|
11
10
|
models: WorldObject[];
|
|
12
11
|
connectionStatus: ConnectionStatus;
|
|
13
|
-
camera: {
|
|
14
|
-
position: Vector3;
|
|
15
|
-
lookAt: Vector3;
|
|
16
|
-
animate: boolean;
|
|
17
|
-
} | undefined;
|
|
18
12
|
addPoints(worldObject: WorldObject<PointsGeometry>): void;
|
|
19
13
|
addMesh(worldObject: WorldObject): void;
|
|
20
|
-
clearCamera: () => void;
|
|
21
14
|
}
|
|
22
15
|
export declare const provideDrawAPI: () => void;
|
|
23
16
|
export declare const useDrawAPI: () => Context;
|
|
@@ -6,7 +6,8 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
|
6
6
|
import { WorldObject } from '../WorldObject.svelte';
|
|
7
7
|
import { useArrows } from './useArrows.svelte';
|
|
8
8
|
import { createGeometry } from '../geometry';
|
|
9
|
-
import { createPoseFromFrame } from '../transform';
|
|
9
|
+
import { createPose, createPoseFromFrame } from '../transform';
|
|
10
|
+
import { useCameraControls } from './useControls.svelte';
|
|
10
11
|
const key = Symbol('draw-api-context-key');
|
|
11
12
|
const tryParse = (json) => {
|
|
12
13
|
try {
|
|
@@ -49,6 +50,7 @@ class Float32Reader {
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
export const provideDrawAPI = () => {
|
|
53
|
+
const cameraControls = useCameraControls();
|
|
52
54
|
let pointsIndex = 0;
|
|
53
55
|
let geometryIndex = 0;
|
|
54
56
|
let poseIndex = 0;
|
|
@@ -62,7 +64,6 @@ export const provideDrawAPI = () => {
|
|
|
62
64
|
const poses = $state([]);
|
|
63
65
|
const nurbs = $state([]);
|
|
64
66
|
const models = $state([]);
|
|
65
|
-
let camera = $state.raw();
|
|
66
67
|
let connectionStatus = $state('connecting');
|
|
67
68
|
const color = new Color();
|
|
68
69
|
const direction = new Vector3();
|
|
@@ -109,7 +110,7 @@ export const provideDrawAPI = () => {
|
|
|
109
110
|
const drawGeometry = (data, color, parent) => {
|
|
110
111
|
const result = meshes.find((mesh) => mesh.name === data.label);
|
|
111
112
|
if (result) {
|
|
112
|
-
result.pose = data.center;
|
|
113
|
+
result.pose = createPose(data.center);
|
|
113
114
|
return;
|
|
114
115
|
}
|
|
115
116
|
const geometry = createGeometry();
|
|
@@ -129,7 +130,7 @@ export const provideDrawAPI = () => {
|
|
|
129
130
|
geometry.geometryType.case = 'capsule';
|
|
130
131
|
geometry.geometryType.value = data.capsule;
|
|
131
132
|
}
|
|
132
|
-
const object = new WorldObject(data.label ?? ++geometryIndex, data.center, parent, geometry, {
|
|
133
|
+
const object = new WorldObject(data.label ?? ++geometryIndex, createPose(data.center), parent, geometry, {
|
|
133
134
|
color: new Color(color),
|
|
134
135
|
});
|
|
135
136
|
meshes.push(object);
|
|
@@ -394,11 +395,11 @@ export const provideDrawAPI = () => {
|
|
|
394
395
|
if (!data)
|
|
395
396
|
return;
|
|
396
397
|
if ('setCameraPose' in data) {
|
|
397
|
-
|
|
398
|
-
position:
|
|
399
|
-
lookAt:
|
|
400
|
-
|
|
401
|
-
|
|
398
|
+
cameraControls.setPose({
|
|
399
|
+
position: [data.Position.X, data.Position.Y, data.Position.Z],
|
|
400
|
+
lookAt: [data.LookAt.X, data.LookAt.Y, data.LookAt.Z],
|
|
401
|
+
}, data.Animate);
|
|
402
|
+
return;
|
|
402
403
|
}
|
|
403
404
|
if ('geometries' in data) {
|
|
404
405
|
return drawGeometries(data.geometries, data.colors, data.parent);
|
|
@@ -455,18 +456,12 @@ export const provideDrawAPI = () => {
|
|
|
455
456
|
get connectionStatus() {
|
|
456
457
|
return connectionStatus;
|
|
457
458
|
},
|
|
458
|
-
get camera() {
|
|
459
|
-
return camera;
|
|
460
|
-
},
|
|
461
459
|
addPoints(worldObject) {
|
|
462
460
|
points.push(worldObject);
|
|
463
461
|
},
|
|
464
462
|
addMesh(worldObject) {
|
|
465
463
|
meshes.push(worldObject);
|
|
466
464
|
},
|
|
467
|
-
clearCamera: () => {
|
|
468
|
-
camera = undefined;
|
|
469
|
-
},
|
|
470
465
|
});
|
|
471
466
|
};
|
|
472
467
|
export const useDrawAPI = () => {
|
package/dist/transform.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Geometry, Pose } from '@viamrobotics/sdk';
|
|
2
2
|
import { type Object3D, Matrix4, Quaternion, Vector3 } from 'three';
|
|
3
3
|
import type { Frame } from './frame';
|
|
4
|
-
export declare const createPose: (pose?: Pose) => Pose;
|
|
4
|
+
export declare const createPose: (pose?: Partial<Pose>) => Pose;
|
|
5
5
|
export declare const createPoseFromFrame: (frame: Partial<Frame>) => Pose;
|
|
6
6
|
export declare const quaternionToPose: (quaternion: Quaternion, pose: Partial<Pose>) => void;
|
|
7
7
|
export declare const vector3ToPose: (vec3: Vector3, pose: Partial<Pose>) => void;
|
package/dist/transform.js
CHANGED
|
@@ -6,13 +6,15 @@ const ov = new OrientationVector();
|
|
|
6
6
|
const translation = new Vector3();
|
|
7
7
|
const scale = new Vector3();
|
|
8
8
|
export const createPose = (pose) => {
|
|
9
|
+
// We should only default to the 0,0,1,0 orientation vector if the entire vector component is missing
|
|
10
|
+
const oZ = pose?.oX === undefined && pose?.oY === undefined && pose?.oZ === undefined ? 1 : (pose?.oZ ?? 0);
|
|
9
11
|
return {
|
|
10
12
|
x: pose?.x ?? 0,
|
|
11
13
|
y: pose?.y ?? 0,
|
|
12
14
|
z: pose?.z ?? 0,
|
|
13
15
|
oX: pose?.oX ?? 0,
|
|
14
16
|
oY: pose?.oY ?? 0,
|
|
15
|
-
oZ
|
|
17
|
+
oZ,
|
|
16
18
|
theta: pose?.theta ?? 0,
|
|
17
19
|
};
|
|
18
20
|
};
|
|
@@ -29,10 +31,13 @@ export const createPoseFromFrame = (frame) => {
|
|
|
29
31
|
else if (frame.orientation?.type === 'ov_radians') {
|
|
30
32
|
ov.copy(frame.orientation.value);
|
|
31
33
|
}
|
|
32
|
-
else {
|
|
34
|
+
else if (frame.orientation) {
|
|
33
35
|
const th = MathUtils.degToRad(frame.orientation?.value.th ?? 0);
|
|
34
36
|
ov.set(frame.orientation?.value.x, frame.orientation?.value.y, frame.orientation?.value.z, th);
|
|
35
37
|
}
|
|
38
|
+
else {
|
|
39
|
+
ov.set(0, 0, 1, 0);
|
|
40
|
+
}
|
|
36
41
|
return {
|
|
37
42
|
x: frame.translation?.x ?? 0,
|
|
38
43
|
y: frame.translation?.y ?? 0,
|