@viamrobotics/motion-tools 1.3.5 → 1.4.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.
@@ -1,3 +1,3 @@
1
1
  import { BufferGeometry } from 'three';
2
- export declare const createBufferGeometry: (positions: Float32Array, colors?: Float32Array | null) => BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
3
- export declare const updateBufferGeometry: (geometry: BufferGeometry, positions: Float32Array, colors?: Float32Array | null) => void;
2
+ export declare const createBufferGeometry: (positions: Float32Array, colors?: Uint8Array | null) => BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
3
+ export declare const updateBufferGeometry: (geometry: BufferGeometry, positions: Float32Array, colors?: Uint8Array | null) => void;
package/dist/attribute.js CHANGED
@@ -3,7 +3,7 @@ export const createBufferGeometry = (positions, colors) => {
3
3
  const geometry = new BufferGeometry();
4
4
  geometry.setAttribute('position', new BufferAttribute(positions, 3));
5
5
  if (colors) {
6
- geometry.setAttribute('color', new BufferAttribute(colors, 3));
6
+ geometry.setAttribute('color', new BufferAttribute(colors, 3, true));
7
7
  }
8
8
  return geometry;
9
9
  };
@@ -24,7 +24,7 @@ export const updateBufferGeometry = (geometry, positions, colors) => {
24
24
  colorAttr.needsUpdate = true;
25
25
  }
26
26
  else {
27
- geometry.setAttribute('color', new BufferAttribute(colors, 3));
27
+ geometry.setAttribute('color', new BufferAttribute(colors, 3, true));
28
28
  }
29
29
  }
30
30
  };
@@ -3,7 +3,7 @@
3
3
  lang="ts"
4
4
  >
5
5
  import { OrientationVector } from '../three/OrientationVector'
6
- import { Quaternion, Vector3, MathUtils } from 'three'
6
+ import { Quaternion, Vector3, MathUtils, BufferAttribute } from 'three'
7
7
 
8
8
  const vec3 = new Vector3()
9
9
  const quaternion = new Quaternion()
@@ -13,7 +13,7 @@
13
13
  <script lang="ts">
14
14
  import { draggable } from '@neodrag/svelte'
15
15
  import { Check, Copy } from 'lucide-svelte'
16
- import { useTask } from '@threlte/core'
16
+ import { useTask, isInstanceOf } from '@threlte/core'
17
17
  import { Button, Icon, Select, Input, Tooltip } from '@viamrobotics/prime-core'
18
18
  import {
19
19
  useSelectedEntity,
@@ -596,6 +596,19 @@
596
596
  </div>
597
597
  </div>
598
598
  {/if}
599
+
600
+ {#if isInstanceOf(object3d, 'Points')}
601
+ <div>
602
+ <strong class="font-semibold">points</strong>
603
+ {@render ImmutableField({
604
+ label: 'count',
605
+ ariaLabel: 'points count',
606
+ value: new Intl.NumberFormat().format(
607
+ (object3d.geometry.getAttribute('position') as BufferAttribute).array.length / 3
608
+ ),
609
+ })}
610
+ </div>
611
+ {/if}
599
612
  </div>
600
613
 
601
614
  <h3 class="text-subtle-2 pt-3 pb-2">Actions</h3>
@@ -71,6 +71,11 @@ class BinaryReader {
71
71
  this.offsetBytes += 4;
72
72
  return v;
73
73
  }
74
+ readU32() {
75
+ const v = this.view.getUint32(this.offsetBytes, this.littleEndian);
76
+ this.offsetBytes += 4;
77
+ return v;
78
+ }
74
79
  /**
75
80
  * Get a Float32Array VIEW into the underlying buffer (no copy) and advance.
76
81
  * Requires current offset to be 4-byte aligned (it will be, if you only readF32 so far).
@@ -222,24 +227,32 @@ export const provideDrawAPI = () => {
222
227
  label += String.fromCharCode(reader.read());
223
228
  }
224
229
  // Read counts
225
- const nPoints = reader.read();
226
- const nColors = reader.read();
230
+ const nPoints = reader.readU32();
231
+ const nColors = reader.readU32();
227
232
  // Read default color
228
- const r = reader.read();
229
- const g = reader.read();
230
- const b = reader.read();
233
+ let r = reader.read();
234
+ let g = reader.read();
235
+ let b = reader.read();
231
236
  const nPointsElements = nPoints * 3;
232
237
  const positions = reader.readF32Array(nPointsElements);
233
238
  const nColorsElements = nColors * 3;
234
- const rawColors = reader.readF32Array(nColorsElements);
235
- const colors = new Float32Array(nPointsElements);
236
- colors.set(rawColors);
237
- // Cover the gap for any points not colored
238
- for (let i = nColors; i < nPoints; i++) {
239
- const offset = i * 3;
240
- colors[offset] = r;
241
- colors[offset + 1] = g;
242
- colors[offset + 2] = b;
239
+ const rawColors = reader.readU8Array(nColorsElements);
240
+ let colors = null;
241
+ if (nColors > 1) {
242
+ colors = new Uint8Array(nPointsElements);
243
+ colors.set(rawColors);
244
+ // Cover the gap for any points not colored
245
+ for (let i = nColors; i < nPoints; i++) {
246
+ const offset = i * 3;
247
+ colors[offset] = Math.round(r * 255);
248
+ colors[offset + 1] = Math.round(g * 255);
249
+ colors[offset + 2] = Math.round(b * 255);
250
+ }
251
+ }
252
+ else if (nColors === 1) {
253
+ r = rawColors[0] / 255;
254
+ g = rawColors[1] / 255;
255
+ b = rawColors[2] / 255;
243
256
  }
244
257
  const entities = world.query(traits.DrawAPI);
245
258
  const entity = entities.find((entity) => entity.get(traits.Name) === label);
@@ -22,11 +22,6 @@ export const provideFrames = (partID) => {
22
22
  }));
23
23
  const revision = $derived(machineStatus.current?.config?.revision);
24
24
  const partConfig = usePartConfig();
25
- $effect(() => {
26
- if (revision) {
27
- untrack(() => query.refetch());
28
- }
29
- });
30
25
  $effect(() => {
31
26
  if (query.isFetching) {
32
27
  logs.add('Fetching frames...');
@@ -118,15 +113,24 @@ export const provideFrames = (partID) => {
118
113
  const current = $derived(Object.values(frames));
119
114
  const entities = new Map();
120
115
  $effect.pre(() => {
121
- for (const [name, machineFrame] of Object.entries(machineFrames)) {
122
- if (machineFrame === undefined) {
123
- continue;
124
- }
125
- const existing = entities.get(name);
126
- if (existing) {
127
- const pose = createPose(machineFrame.transform.poseInObserverFrame?.pose);
128
- existing.set(traits.Pose, pose);
129
- }
116
+ if (revision) {
117
+ untrack(async () => {
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
+ });
130
134
  }
131
135
  });
132
136
  $effect.pre(() => {
@@ -10,7 +10,7 @@ import { RefetchRates } from '../components/RefreshRate.svelte';
10
10
  import { useLogs } from './useLogs.svelte';
11
11
  import { useResourceByName } from './useResourceByName.svelte';
12
12
  import { useRefetchPoses } from './useRefetchPoses';
13
- const origingFrameComponentTypes = ['arm', 'gantry', 'gripper'];
13
+ const origingFrameComponentTypes = ['arm', 'gantry', 'gripper', 'base'];
14
14
  export const usePose = (name, parent) => {
15
15
  const environment = useEnvironment();
16
16
  const logs = useLogs();
@@ -1,7 +1,7 @@
1
1
  export interface SuccessMessage {
2
2
  id: number;
3
3
  positions: Float32Array<ArrayBuffer>;
4
- colors: Float32Array<ArrayBuffer> | null;
4
+ colors: Uint8Array<ArrayBuffer> | null;
5
5
  }
6
6
  export type Message = SuccessMessage | {
7
7
  id: number;
@@ -15,7 +15,13 @@ self.onmessage = async (event) => {
15
15
  */
16
16
  const positions = pcd.geometry.attributes.position?.array ??
17
17
  new Float32Array(0);
18
- const colors = pcd.geometry.attributes.color?.array ?? null;
18
+ const colorsFloat = pcd.geometry.attributes.color?.array ?? null;
19
+ const colors = colorsFloat ? new Uint8Array(colorsFloat.length) : null;
20
+ if (colors) {
21
+ for (let i = 0, l = colorsFloat.length; i < l; i++) {
22
+ colors[i] = Math.round(colorsFloat[i] * 255);
23
+ }
24
+ }
19
25
  postMessage({ positions, colors, id }, colors ? [positions.buffer, colors.buffer] : [positions.buffer]);
20
26
  }
21
27
  else {
package/dist/snapshot.js CHANGED
@@ -192,9 +192,7 @@ const spawnEntitiesFromDrawing = (world, drawing) => {
192
192
  for (let i = 0, l = positions.length; i < l; i += 1) {
193
193
  positions[i] *= 0.001;
194
194
  }
195
- const colors = drawing.metadata?.colors
196
- ? rgbaBytesToFloat32(drawing.metadata.colors)
197
- : undefined;
195
+ const colors = drawing.metadata?.colors;
198
196
  const geometry = createBufferGeometry(positions, colors);
199
197
  entityTraits.push(traits.BufferGeometry(geometry));
200
198
  if (geometryType.value.pointSize) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "1.3.5",
3
+ "version": "1.4.0",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",