@viamrobotics/motion-tools 1.4.0 → 1.5.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.
@@ -665,6 +665,14 @@ export declare class GetKinematicsResponse extends Message<GetKinematicsResponse
665
665
  * @generated from field: bytes kinematics_data = 2;
666
666
  */
667
667
  kinematicsData: Uint8Array<ArrayBuffer>;
668
+ /**
669
+ * Map of URDF mesh file paths to mesh data
670
+ *
671
+ * @generated from field: map<string, viam.common.v1.Mesh> meshes_by_urdf_filepath = 3;
672
+ */
673
+ meshesByUrdfFilepath: {
674
+ [key: string]: Mesh;
675
+ };
668
676
  constructor(data?: PartialMessage<GetKinematicsResponse>);
669
677
  static readonly runtime: typeof proto3;
670
678
  static readonly typeName = "viam.common.v1.GetKinematicsResponse";
@@ -959,6 +959,12 @@ export class GetKinematicsResponse extends Message {
959
959
  * @generated from field: bytes kinematics_data = 2;
960
960
  */
961
961
  kinematicsData = new Uint8Array(0);
962
+ /**
963
+ * Map of URDF mesh file paths to mesh data
964
+ *
965
+ * @generated from field: map<string, viam.common.v1.Mesh> meshes_by_urdf_filepath = 3;
966
+ */
967
+ meshesByUrdfFilepath = {};
962
968
  constructor(data) {
963
969
  super();
964
970
  proto3.util.initPartial(data, this);
@@ -968,6 +974,7 @@ export class GetKinematicsResponse extends Message {
968
974
  static fields = proto3.util.newFieldList(() => [
969
975
  { no: 1, name: "format", kind: "enum", T: proto3.getEnumType(KinematicsFileFormat) },
970
976
  { no: 2, name: "kinematics_data", kind: "scalar", T: 12 /* ScalarType.BYTES */ },
977
+ { no: 3, name: "meshes_by_urdf_filepath", kind: "map", K: 9 /* ScalarType.STRING */, V: { kind: "message", T: Mesh } },
971
978
  ]);
972
979
  static fromBinary(bytes, options) {
973
980
  return new GetKinematicsResponse().fromBinary(bytes, options);
@@ -25,7 +25,6 @@
25
25
  label="unfold more icon"
26
26
  variant="ghost"
27
27
  cx="size-6"
28
- onclick={() => (expanded.current = !expanded.current)}
29
28
  />
30
29
  {name}
31
30
  {@render titleAlert?.()}
@@ -10,6 +10,7 @@
10
10
  import { useEnvironment } from '../../hooks/useEnvironment.svelte'
11
11
  import { usePartID } from '../../hooks/usePartID.svelte'
12
12
  import { usePartConfig } from '../../hooks/usePartConfig.svelte'
13
+ import { useFrames } from '../../hooks/useFrames.svelte'
13
14
  import { traits, useQuery, useWorld } from '../../ecs'
14
15
  import { IsExcluded, type Entity } from 'koota'
15
16
  import { buildTreeNodes, type TreeNode } from './buildTree'
@@ -30,13 +31,19 @@
30
31
  )
31
32
  const environment = useEnvironment()
32
33
  const partConfig = usePartConfig()
34
+ const frames = useFrames()
33
35
  const world = useWorld()
34
36
 
35
37
  const worldEntity = world.spawn(IsExcluded, traits.Name('World'))
36
38
 
37
39
  const allEntities = useQuery(traits.Name)
38
40
 
39
- const { rootNodes, nodeMap } = $derived(buildTreeNodes(allEntities.current))
41
+ const { rootNodes, nodeMap } = $derived.by(() => {
42
+ // This ensures the tree rebuilds when frame parent relationships change
43
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
44
+ frames.current
45
+ return buildTreeNodes(allEntities.current)
46
+ })
40
47
 
41
48
  const rootNode = $derived<TreeNode>({
42
49
  entity: worldEntity,
@@ -383,7 +383,8 @@ export const provideDrawAPI = () => {
383
383
  }
384
384
  else if (type === bufferTypes.DRAW_GLTF) {
385
385
  operation = 'DrawGLTF';
386
- drawGLTF(reader.buffer);
386
+ // GLTF payload starts after the 20-byte header (16 bytes UUID + 4 bytes type)
387
+ drawGLTF(reader.buffer.slice(20));
387
388
  }
388
389
  else {
389
390
  throw new Error('Invalid buffer');
@@ -7,6 +7,8 @@ import { createPose } from '../transform';
7
7
  import { useThrelte } from '@threlte/core';
8
8
  import { createBox, createCapsule, createSphere } from '../geometry';
9
9
  import { parsePlyInput } from '../ply';
10
+ import { parsePcdInWorker } from '../loaders/pcd';
11
+ import { createBufferGeometry } from '../attribute';
10
12
  export const provideWorldStates = () => {
11
13
  const partID = usePartID();
12
14
  const resourceNames = useResourceNames(() => partID.current, 'world_state_store');
@@ -45,7 +47,22 @@ const createWorldState = (client) => {
45
47
  entityTraits.push(traits.VertexColors(metadata.colors));
46
48
  }
47
49
  if (transform.physicalObject) {
48
- entityTraits.push(traits.Geometry(transform.physicalObject));
50
+ if (transform.physicalObject.geometryType.case === 'pointcloud') {
51
+ parsePcdInWorker(new Uint8Array(transform.physicalObject.geometryType.value.pointCloud)).then((pointcloud) => {
52
+ // pcds are a special case since they have to be loaded in a worker and the trait will be added to the existing entity
53
+ const entity = entities.get(transform.uuidString);
54
+ if (!entity) {
55
+ console.error('Entity not found to add pointcloud trait to', transform.uuidString);
56
+ return;
57
+ }
58
+ const geometry = createBufferGeometry(pointcloud.positions, pointcloud.colors);
59
+ entity.add(traits.BufferGeometry(geometry));
60
+ entity.add(traits.Points);
61
+ });
62
+ }
63
+ else {
64
+ entityTraits.push(traits.Geometry(transform.physicalObject));
65
+ }
49
66
  }
50
67
  if (metadata.shape === 'line' && metadata.points) {
51
68
  const { points } = metadata;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -129,7 +129,7 @@
129
129
  "@neodrag/svelte": "^2.3.3",
130
130
  "@tanstack/svelte-query-devtools": "^6.0.2",
131
131
  "koota": "^0.5.3",
132
- "lodash-es": "4.17.21",
132
+ "lodash-es": "4.17.23",
133
133
  "uuid-tool": "^2.0.3"
134
134
  },
135
135
  "scripts": {