@viamrobotics/test-widgets 0.6.1 → 0.8.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/README.md +1 -1
- package/dist/api-docs-href.d.ts +8 -0
- package/dist/api-docs-href.js +17 -0
- package/dist/client-map.d.ts +30 -30
- package/dist/client-map.js +32 -29
- package/dist/components/angle-unit-toggle.svelte +1 -4
- package/dist/components/api-section.svelte +21 -23
- package/dist/components/api-section.svelte.d.ts +2 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/index.js +21 -0
- package/dist/components/is-moving.svelte +4 -5
- package/dist/components/is-moving.svelte.d.ts +1 -0
- package/dist/components/mutation-section.svelte +20 -23
- package/dist/components/mutation-section.svelte.d.ts +2 -0
- package/dist/components/section-title.svelte +63 -0
- package/dist/components/section-title.svelte.d.ts +14 -0
- package/dist/components/widgets/arm/arm.svelte +25 -29
- package/dist/components/widgets/arm/get-joint-positions-widget.svelte +36 -0
- package/dist/components/widgets/arm/get-joint-positions-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/arm/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/arm/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/arm/joint-position-editor.svelte +89 -0
- package/dist/components/widgets/arm/joint-position-editor.svelte.d.ts +11 -0
- package/dist/components/widgets/arm/joint-position-quick-move.svelte +85 -0
- package/dist/components/widgets/arm/joint-position-quick-move.svelte.d.ts +9 -0
- package/dist/components/widgets/arm/joint-position-slider.svelte +36 -0
- package/dist/components/widgets/arm/joint-position-slider.svelte.d.ts +9 -0
- package/dist/components/widgets/arm/move-to-joint-positions-widget.svelte +9 -5
- package/dist/components/widgets/arm/move-to-joint-positions.svelte +73 -127
- package/dist/components/widgets/arm/move-to-joint-positions.svelte.d.ts +1 -0
- package/dist/components/widgets/arm/move-to-position.svelte +31 -3
- package/dist/components/widgets/audio-input/audio-input.svelte +2 -0
- package/dist/components/widgets/audio-input/get-properties-widget.svelte +43 -0
- package/dist/components/widgets/audio-input/get-properties-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/audio-output/audio-output.svelte +2 -0
- package/dist/components/widgets/audio-output/get-properties-widget.svelte +43 -0
- package/dist/components/widgets/audio-output/get-properties-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/base/base.svelte +9 -1
- package/dist/components/widgets/base/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/base/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/base/quick-move.svelte +12 -5
- package/dist/components/widgets/camera/camera.svelte +156 -142
- package/dist/components/widgets/camera/live-or-polling-video.svelte +9 -1
- package/dist/components/widgets/discovery/discovery.svelte +1 -0
- package/dist/components/widgets/encoder/encoder-position-type.d.ts +8 -0
- package/dist/components/widgets/encoder/encoder-position-type.js +20 -0
- package/dist/components/widgets/encoder/encoder.svelte +5 -20
- package/dist/components/widgets/encoder/get-position-widget.svelte +54 -0
- package/dist/components/widgets/encoder/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/gantry/gantry.svelte +28 -5
- package/dist/components/widgets/gantry/get-position-widget.svelte +43 -0
- package/dist/components/widgets/gantry/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/gantry/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/gantry/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/generic/generic.svelte +8 -1
- package/dist/components/widgets/gripper/gripper.svelte +11 -5
- package/dist/components/widgets/gripper/is-holding-something.svelte +2 -4
- package/dist/components/widgets/gripper/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/gripper/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/input-controller/input-controller.svelte +2 -1
- package/dist/components/widgets/motor/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/motor/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/motor/motor.svelte +13 -9
- package/dist/components/widgets/movement-sensor/get-accuracy-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-accuracy-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-compass-heading-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-compass-heading-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-orientation-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-orientation-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/get-position-widget.svelte +38 -0
- package/dist/components/widgets/movement-sensor/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/movement-sensor/movement-sensor.svelte +53 -26
- package/dist/components/widgets/power-sensor/get-current-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-current-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/get-power-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-power-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/get-voltage-widget.svelte +38 -0
- package/dist/components/widgets/power-sensor/get-voltage-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/power-sensor/power-sensor.svelte +4 -0
- package/dist/components/widgets/sensor/sensor.svelte +1 -0
- package/dist/components/widgets/servo/is-moving-widget.svelte +20 -0
- package/dist/components/widgets/servo/is-moving-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/servo/servo.svelte +10 -2
- package/dist/components/widgets/slam/get-position-widget.svelte +38 -0
- package/dist/components/widgets/slam/get-position-widget.svelte.d.ts +7 -0
- package/dist/components/widgets/slam/move-on-map.svelte +4 -1
- package/dist/components/widgets/slam/slam.svelte +4 -1
- package/dist/components/widgets/vision-service/context.svelte.d.ts +1 -0
- package/dist/components/widgets/vision-service/context.svelte.js +7 -0
- package/dist/components/widgets/vision-service/detection-row.svelte +38 -0
- package/dist/components/widgets/vision-service/detection-row.svelte.d.ts +8 -0
- package/dist/components/widgets/vision-service/detection.svelte +7 -4
- package/dist/components/widgets/vision-service/legend.svelte +14 -11
- package/dist/components/widgets/vision-service/vision-service.svelte +9 -10
- package/dist/index.d.ts +5 -1
- package/dist/index.js +6 -1
- package/dist/pip/context.svelte.d.ts +2 -0
- package/dist/pip/context.svelte.js +48 -20
- package/dist/resource-triplet.d.ts +37 -0
- package/dist/resource-triplet.js +37 -0
- package/dist/resource-widget.js +187 -0
- package/dist/resource.d.ts +0 -9
- package/dist/resource.js +0 -72
- package/package.json +7 -4
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
createRefetchIntervalStore,
|
|
13
13
|
RefetchIntervals,
|
|
14
14
|
} from '../../refetch-interval-store.svelte'
|
|
15
|
+
import SectionTitle from '../../section-title.svelte'
|
|
15
16
|
|
|
16
17
|
import PCDWidget from '../pcd/pcd-widget.svelte'
|
|
17
18
|
import ExportScreenshot from './export-screenshot.svelte'
|
|
@@ -150,166 +151,179 @@
|
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
const headingID = $props.id()
|
|
154
|
+
const getImagesHeadingID = `${headingID}-images`
|
|
155
|
+
const getPointCloudHeadingID = `${headingID}-point-cloud`
|
|
153
156
|
</script>
|
|
154
157
|
|
|
155
158
|
<ConnectionStatus {partID}>
|
|
156
159
|
{#snippet connected()}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
<section
|
|
161
|
+
class="flex flex-col"
|
|
162
|
+
aria-labelledby={getImagesHeadingID}
|
|
163
|
+
>
|
|
164
|
+
<div class="flex flex-col gap-0.5 p-4 pb-0">
|
|
165
|
+
<SectionTitle
|
|
166
|
+
title="GetImages"
|
|
167
|
+
api="rdk:component:camera"
|
|
168
|
+
headingId={getImagesHeadingID}
|
|
163
169
|
/>
|
|
164
|
-
{#if sourceNames.length > 0 && refetchInterval.current !== RefetchIntervals.LIVE}
|
|
165
|
-
<Label position="left">
|
|
166
|
-
Source
|
|
167
|
-
<Select
|
|
168
|
-
value={selectedSource}
|
|
169
|
-
on:change={onSourceSelect}
|
|
170
|
-
slot="input"
|
|
171
|
-
>
|
|
172
|
-
{#each sourceNames as name (name)}
|
|
173
|
-
<option value={name}>{name}</option>
|
|
174
|
-
{/each}
|
|
175
|
-
</Select>
|
|
176
|
-
</Label>
|
|
177
|
-
{/if}
|
|
178
|
-
{#if panoCoverage}
|
|
179
|
-
<Label>
|
|
180
|
-
{panoToggleLabel}
|
|
181
|
-
<ToggleButtons
|
|
182
|
-
slot="input"
|
|
183
|
-
options={['On', 'Off']}
|
|
184
|
-
selected={displayAs360 ? 'On' : 'Off'}
|
|
185
|
-
on:input={(event) => {
|
|
186
|
-
displayAs360 = event.detail === 'On'
|
|
187
|
-
}}
|
|
188
|
-
/>
|
|
189
|
-
</Label>
|
|
190
|
-
{/if}
|
|
191
170
|
</div>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
171
|
+
{#if isPlaying}
|
|
172
|
+
<div class="flex gap-4 p-4 pb-3">
|
|
173
|
+
<RefetchController
|
|
174
|
+
{refetchInterval}
|
|
175
|
+
allowLive
|
|
176
|
+
queries={[imageQuery, pointcloudQuery]}
|
|
177
|
+
/>
|
|
178
|
+
{#if sourceNames.length > 0 && refetchInterval.current !== RefetchIntervals.LIVE}
|
|
179
|
+
<Label position="left">
|
|
180
|
+
Source
|
|
181
|
+
<Select
|
|
182
|
+
value={selectedSource}
|
|
183
|
+
on:change={onSourceSelect}
|
|
184
|
+
slot="input"
|
|
185
|
+
>
|
|
186
|
+
{#each sourceNames as name (name)}
|
|
187
|
+
<option value={name}>{name}</option>
|
|
188
|
+
{/each}
|
|
189
|
+
</Select>
|
|
190
|
+
</Label>
|
|
191
|
+
{/if}
|
|
192
|
+
{#if panoCoverage}
|
|
193
|
+
<Label>
|
|
194
|
+
{panoToggleLabel}
|
|
195
|
+
<ToggleButtons
|
|
196
|
+
slot="input"
|
|
197
|
+
options={['On', 'Off']}
|
|
198
|
+
selected={displayAs360 ? 'On' : 'Off'}
|
|
199
|
+
on:input={(event) => {
|
|
200
|
+
displayAs360 = event.detail === 'On'
|
|
201
|
+
}}
|
|
202
|
+
/>
|
|
203
|
+
</Label>
|
|
204
|
+
{/if}
|
|
205
|
+
</div>
|
|
206
|
+
{/if}
|
|
207
|
+
<div class="flex h-full w-full gap-4 p-4">
|
|
208
|
+
<div class="grow">
|
|
209
|
+
{#if isPlaying}
|
|
210
|
+
{#if displayAs360}
|
|
211
|
+
{#if isLive}
|
|
212
|
+
<!-- renderMode="always" keeps the live VideoTexture advancing each frame -->
|
|
213
|
+
<Canvas renderMode="always">
|
|
214
|
+
<LiveThreeSixtyCameraView
|
|
215
|
+
{partID}
|
|
216
|
+
{resourceName}
|
|
217
|
+
coverage={panoCoverage}
|
|
218
|
+
/>
|
|
219
|
+
</Canvas>
|
|
220
|
+
{:else}
|
|
221
|
+
<Canvas>
|
|
222
|
+
<ThreeSixtyCameraView
|
|
223
|
+
data={imageQuery.data}
|
|
224
|
+
coverage={panoCoverage}
|
|
225
|
+
/>
|
|
226
|
+
</Canvas>
|
|
227
|
+
{/if}
|
|
206
228
|
{:else}
|
|
207
|
-
<
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
229
|
+
<LiveOrPollingVideo
|
|
230
|
+
{partID}
|
|
231
|
+
{resourceName}
|
|
232
|
+
showResolutionOptions
|
|
233
|
+
{isLive}
|
|
234
|
+
data={imageQuery.data}
|
|
235
|
+
error={imageQuery.error}
|
|
236
|
+
isLoading={imageQuery.isLoading}
|
|
237
|
+
refetch={imageQuery.refetch}
|
|
238
|
+
showMousePositionTooltip={mousePostionTooltip === 'On'}
|
|
239
|
+
sourceName={selectedSource}
|
|
240
|
+
/>
|
|
213
241
|
{/if}
|
|
214
242
|
{:else}
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
243
|
+
<div class="bg-medium flex h-64 w-80 items-center justify-center">
|
|
244
|
+
<Button
|
|
245
|
+
icon="play-circle-outline"
|
|
246
|
+
variant="dark"
|
|
247
|
+
onclick={() => {
|
|
248
|
+
isPlaying = true
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
Start feed
|
|
252
|
+
</Button>
|
|
253
|
+
</div>
|
|
254
|
+
{/if}
|
|
255
|
+
</div>
|
|
256
|
+
{#if isPlaying}
|
|
257
|
+
<div class="flex flex-col items-start gap-2">
|
|
258
|
+
<ExportScreenshot
|
|
259
|
+
name={client.current?.name ?? ''}
|
|
225
260
|
sourceName={selectedSource}
|
|
261
|
+
getImage={exportScreenshotQuery.refetch}
|
|
226
262
|
/>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
</div>
|
|
240
|
-
{/if}
|
|
241
|
-
</div>
|
|
242
|
-
{#if isPlaying}
|
|
243
|
-
<div class="flex flex-col items-start gap-2">
|
|
244
|
-
<ExportScreenshot
|
|
245
|
-
name={client.current?.name ?? ''}
|
|
246
|
-
sourceName={selectedSource}
|
|
247
|
-
getImage={exportScreenshotQuery.refetch}
|
|
248
|
-
/>
|
|
249
|
-
{#if addImageToDataset}
|
|
250
|
-
<Button
|
|
251
|
-
icon="layers-triple-outline"
|
|
252
|
-
onclick={async () => {
|
|
253
|
-
let imgData
|
|
254
|
-
if (refetchInterval.current === RefetchIntervals.LIVE) {
|
|
255
|
-
const { isSuccess, data } = await imageQuery.refetch()
|
|
256
|
-
if (!isSuccess) return
|
|
257
|
-
imgData = data
|
|
258
|
-
} else {
|
|
259
|
-
imgData = imageQuery.data
|
|
260
|
-
}
|
|
263
|
+
{#if addImageToDataset}
|
|
264
|
+
<Button
|
|
265
|
+
icon="layers-triple-outline"
|
|
266
|
+
onclick={async () => {
|
|
267
|
+
let imgData
|
|
268
|
+
if (refetchInterval.current === RefetchIntervals.LIVE) {
|
|
269
|
+
const { isSuccess, data } = await imageQuery.refetch()
|
|
270
|
+
if (!isSuccess) return
|
|
271
|
+
imgData = data
|
|
272
|
+
} else {
|
|
273
|
+
imgData = imageQuery.data
|
|
274
|
+
}
|
|
261
275
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
276
|
+
const matchingImage = pickImageForSource(imgData?.images, selectedSource)
|
|
277
|
+
const image = matchingImage?.image
|
|
278
|
+
const mimeType = matchingImage?.mimeType
|
|
265
279
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
280
|
+
if (image) {
|
|
281
|
+
addImageToDataset({
|
|
282
|
+
binaryData: new Uint8Array(image),
|
|
283
|
+
partID,
|
|
284
|
+
componentType: 'camera',
|
|
285
|
+
componentName: resourceName,
|
|
286
|
+
methodName: 'captureAllFromCamera',
|
|
287
|
+
mimeType: mimeType ?? 'image/png',
|
|
288
|
+
dataRequestTimes: [new Date(), new Date()],
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
}}
|
|
292
|
+
>
|
|
293
|
+
Add current image to dataset
|
|
294
|
+
</Button>
|
|
295
|
+
{/if}
|
|
296
|
+
{#if !isFirefox}
|
|
297
|
+
<PictureInPictureButton
|
|
298
|
+
{resourceName}
|
|
299
|
+
rate={refetchInterval.current}
|
|
300
|
+
/>
|
|
301
|
+
{/if}
|
|
302
|
+
<Label>
|
|
303
|
+
Mouse Position Tooltip
|
|
290
304
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
305
|
+
<ToggleButtons
|
|
306
|
+
slot="input"
|
|
307
|
+
options={['On', 'Off']}
|
|
308
|
+
selected={mousePostionTooltip}
|
|
309
|
+
on:input={setMousePostionTooltip}
|
|
310
|
+
/>
|
|
311
|
+
</Label>
|
|
312
|
+
</div>
|
|
313
|
+
{/if}
|
|
314
|
+
</div>
|
|
315
|
+
</section>
|
|
301
316
|
|
|
302
317
|
<section
|
|
303
318
|
class="flex flex-col gap-4 p-4"
|
|
304
|
-
aria-labelledby={
|
|
319
|
+
aria-labelledby={getPointCloudHeadingID}
|
|
305
320
|
>
|
|
306
|
-
<div>
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
</h3>
|
|
321
|
+
<div class="flex flex-col gap-0.5">
|
|
322
|
+
<SectionTitle
|
|
323
|
+
title="GetPointCloud"
|
|
324
|
+
api="rdk:component:camera"
|
|
325
|
+
headingId={getPointCloudHeadingID}
|
|
326
|
+
/>
|
|
313
327
|
<p class="text-subtle-2 text-xs">
|
|
314
328
|
Get depth measurement data from cameras with depth sensing support
|
|
315
329
|
</p>
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import Progress from '../../progress.svelte'
|
|
15
15
|
import { formatNumeric } from '../../../format'
|
|
16
16
|
import { useMeasureFps } from '../../../fps.svelte'
|
|
17
|
+
import { usePip } from '../../../pip/context.svelte'
|
|
17
18
|
|
|
18
19
|
import { getBlobForViamDepth, VIAM_DEPTH_MIME_TYPE } from './decode-viam-depth'
|
|
19
20
|
import { pickImageForSource } from './pick-image-for-source'
|
|
@@ -52,7 +53,13 @@
|
|
|
52
53
|
let vfcID = 0
|
|
53
54
|
let liveStreamStart: DOMHighResTimeStamp | undefined
|
|
54
55
|
|
|
56
|
+
const pip = usePip()
|
|
57
|
+
|
|
55
58
|
const setMediaStream = (mediaStream: MediaStream | null) => {
|
|
59
|
+
if (mediaStream) {
|
|
60
|
+
pip.setStream(resourceName, mediaStream)
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
if (videoElement) {
|
|
57
64
|
// TODO(2025-01-31): Remove these function guards.
|
|
58
65
|
// Sentry has some error traces where "cancelVideoFrameCallback is not a function".
|
|
@@ -190,6 +197,7 @@
|
|
|
190
197
|
return () =>
|
|
191
198
|
untrack(() => {
|
|
192
199
|
disableStream().then(() => {
|
|
200
|
+
pip.setStream(resourceName, null)
|
|
193
201
|
setMediaStream(null)
|
|
194
202
|
})
|
|
195
203
|
})
|
|
@@ -301,7 +309,6 @@
|
|
|
301
309
|
}
|
|
302
310
|
|
|
303
311
|
const fps = useMeasureFps()
|
|
304
|
-
|
|
305
312
|
$effect(() => {
|
|
306
313
|
let id: number | undefined
|
|
307
314
|
|
|
@@ -393,6 +400,7 @@
|
|
|
393
400
|
{#if showResolutionOptions && isLive}
|
|
394
401
|
<MutationSection
|
|
395
402
|
title="SetStreamOptions"
|
|
403
|
+
api="rdk:component:camera"
|
|
396
404
|
description="Change the resolution of the live stream video feed"
|
|
397
405
|
lastError={resolutionMutation.error}
|
|
398
406
|
class="-m-4 mt-4"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EncoderPositionType, type EncoderProperties } from '@viamrobotics/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Picks the position type to request from an encoder based on its properties.
|
|
4
|
+
* @param properties - The encoder's reported properties, if loaded.
|
|
5
|
+
* @returns A single-element argument tuple for `getPosition`.
|
|
6
|
+
* @example getEncoderPositionArgs({ angleDegreesSupported: true }) // [EncoderPositionType.ANGLE_DEGREES]
|
|
7
|
+
*/
|
|
8
|
+
export declare const getEncoderPositionArgs: (properties: EncoderProperties | undefined) => [EncoderPositionType];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EncoderPositionType } from '@viamrobotics/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Picks the position type to request from an encoder based on its properties.
|
|
4
|
+
* @param properties - The encoder's reported properties, if loaded.
|
|
5
|
+
* @returns A single-element argument tuple for `getPosition`.
|
|
6
|
+
* @example getEncoderPositionArgs({ angleDegreesSupported: true }) // [EncoderPositionType.ANGLE_DEGREES]
|
|
7
|
+
*/
|
|
8
|
+
export const getEncoderPositionArgs = (properties) => {
|
|
9
|
+
if (!properties) {
|
|
10
|
+
return [EncoderPositionType.UNSPECIFIED];
|
|
11
|
+
}
|
|
12
|
+
const { angleDegreesSupported, ticksCountSupported } = properties;
|
|
13
|
+
if (angleDegreesSupported) {
|
|
14
|
+
return [EncoderPositionType.ANGLE_DEGREES];
|
|
15
|
+
}
|
|
16
|
+
if (ticksCountSupported) {
|
|
17
|
+
return [EncoderPositionType.TICKS_COUNT];
|
|
18
|
+
}
|
|
19
|
+
return [EncoderPositionType.UNSPECIFIED];
|
|
20
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Button } from '@viamrobotics/prime-core'
|
|
3
|
-
import { EncoderClient
|
|
3
|
+
import { EncoderClient } from '@viamrobotics/sdk'
|
|
4
4
|
import {
|
|
5
5
|
createResourceClient,
|
|
6
6
|
createResourceMutation,
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import RefetchController from '../../refetch-controller.svelte'
|
|
15
15
|
import { createRefetchIntervalStore } from '../../refetch-interval-store.svelte'
|
|
16
16
|
|
|
17
|
+
import { getEncoderPositionArgs } from './encoder-position-type'
|
|
17
18
|
import Position from './position.svelte'
|
|
18
19
|
|
|
19
20
|
interface Props {
|
|
@@ -35,24 +36,6 @@
|
|
|
35
36
|
'encoder-view'
|
|
36
37
|
)
|
|
37
38
|
|
|
38
|
-
const getPositionArgs = (properties: EncoderProperties | undefined): [EncoderPositionType] => {
|
|
39
|
-
if (!properties) {
|
|
40
|
-
return [EncoderPositionType.UNSPECIFIED]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const { angleDegreesSupported, ticksCountSupported } = properties
|
|
44
|
-
|
|
45
|
-
if (angleDegreesSupported) {
|
|
46
|
-
return [EncoderPositionType.ANGLE_DEGREES]
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (ticksCountSupported) {
|
|
50
|
-
return [EncoderPositionType.TICKS_COUNT]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return [EncoderPositionType.UNSPECIFIED]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
39
|
const propertiesQuery = createResourceQuery(client, 'getProperties', () => ({
|
|
57
40
|
refetchInterval: refetchInterval.current,
|
|
58
41
|
}))
|
|
@@ -60,7 +43,7 @@
|
|
|
60
43
|
const positionQuery = createResourceQuery(
|
|
61
44
|
client,
|
|
62
45
|
'getPosition',
|
|
63
|
-
() =>
|
|
46
|
+
() => getEncoderPositionArgs(propertiesQuery.data),
|
|
64
47
|
() => ({
|
|
65
48
|
enabled: propertiesQuery.data !== undefined,
|
|
66
49
|
refetchInterval: refetchInterval.current,
|
|
@@ -81,6 +64,7 @@
|
|
|
81
64
|
<div class="grid w-full grid-cols-2 divide-x">
|
|
82
65
|
<ApiSection
|
|
83
66
|
title="GetPosition"
|
|
67
|
+
api="rdk:component:encoder"
|
|
84
68
|
tooltip="Relative encoders return ticks since last zeroing. Absolute encoders return degrees."
|
|
85
69
|
class="gap-3"
|
|
86
70
|
>
|
|
@@ -99,6 +83,7 @@
|
|
|
99
83
|
|
|
100
84
|
<ApiSection
|
|
101
85
|
title="ResetPosition"
|
|
86
|
+
api="rdk:component:encoder"
|
|
102
87
|
description="Set the current position as the new zero position"
|
|
103
88
|
>
|
|
104
89
|
<Button
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { EncoderClient } from '@viamrobotics/sdk'
|
|
3
|
+
import { createResourceClient, createResourceQuery } from '@viamrobotics/svelte-sdk'
|
|
4
|
+
|
|
5
|
+
import ApiSection from '../../api-section.svelte'
|
|
6
|
+
import Queries from '../../queries.svelte'
|
|
7
|
+
|
|
8
|
+
import { getEncoderPositionArgs } from './encoder-position-type'
|
|
9
|
+
import Position from './position.svelte'
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
partID: string
|
|
13
|
+
resourceName: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { partID, resourceName }: Props = $props()
|
|
17
|
+
|
|
18
|
+
const client = createResourceClient(
|
|
19
|
+
EncoderClient,
|
|
20
|
+
() => partID,
|
|
21
|
+
() => resourceName
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const propertiesQuery = createResourceQuery(client, 'getProperties', { refetchInterval: 500 })
|
|
25
|
+
|
|
26
|
+
const positionQuery = createResourceQuery(
|
|
27
|
+
client,
|
|
28
|
+
'getPosition',
|
|
29
|
+
() => getEncoderPositionArgs(propertiesQuery.data),
|
|
30
|
+
() => ({
|
|
31
|
+
enabled: propertiesQuery.data !== undefined,
|
|
32
|
+
refetchInterval: 500,
|
|
33
|
+
})
|
|
34
|
+
)
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<ApiSection
|
|
38
|
+
title="GetPosition"
|
|
39
|
+
tooltip="Relative encoders return ticks since last zeroing. Absolute encoders return degrees."
|
|
40
|
+
bottomText="Updates automatically"
|
|
41
|
+
class="grow"
|
|
42
|
+
>
|
|
43
|
+
<Queries queries={[propertiesQuery, positionQuery]}>
|
|
44
|
+
{#if positionQuery.data !== undefined}
|
|
45
|
+
{@const [position, encoderPositionType] = positionQuery.data}
|
|
46
|
+
<div class="font-roboto-mono flex flex-col gap-2 text-sm">
|
|
47
|
+
<Position
|
|
48
|
+
{position}
|
|
49
|
+
{encoderPositionType}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
{/if}
|
|
53
|
+
</Queries>
|
|
54
|
+
</ApiSection>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
createResourceQuery,
|
|
7
7
|
} from '@viamrobotics/svelte-sdk'
|
|
8
8
|
|
|
9
|
+
import { apiDocsHref } from '../../../api-docs-href'
|
|
9
10
|
import ApiSection from '../../api-section.svelte'
|
|
10
11
|
import ConnectionStatus from '../../connection-status.svelte'
|
|
11
12
|
import IsMoving from '../../is-moving.svelte'
|
|
@@ -51,12 +52,26 @@
|
|
|
51
52
|
aria-labelledby={positionHeadingID}
|
|
52
53
|
>
|
|
53
54
|
<h3
|
|
54
|
-
class="flex flex-row items-center gap-1 text-sm"
|
|
55
|
+
class="text-subtle-2 flex flex-row items-center gap-1 text-sm"
|
|
55
56
|
id={positionHeadingID}
|
|
56
57
|
>
|
|
57
|
-
<
|
|
58
|
+
<a
|
|
59
|
+
href={apiDocsHref('rdk:component:gantry', 'getPosition')}
|
|
60
|
+
target="_blank"
|
|
61
|
+
rel="noopener noreferrer external"
|
|
62
|
+
class="decoration-gray-5 hover:decoration-default text-default font-mono font-semibold underline underline-offset-3"
|
|
63
|
+
>
|
|
64
|
+
GetPosition
|
|
65
|
+
</a>
|
|
58
66
|
and
|
|
59
|
-
<
|
|
67
|
+
<a
|
|
68
|
+
href={apiDocsHref('rdk:component:gantry', 'getLengths')}
|
|
69
|
+
target="_blank"
|
|
70
|
+
rel="noopener noreferrer external"
|
|
71
|
+
class="decoration-gray-5 hover:decoration-default text-default font-mono font-semibold underline underline-offset-3"
|
|
72
|
+
>
|
|
73
|
+
GetLengths
|
|
74
|
+
</a>
|
|
60
75
|
</h3>
|
|
61
76
|
<Queries queries={[positionQuery, lengthsQuery]}>
|
|
62
77
|
{@const positions = positionQuery.data}
|
|
@@ -69,7 +84,10 @@
|
|
|
69
84
|
{/if}
|
|
70
85
|
</Queries>
|
|
71
86
|
</ApiSection>
|
|
72
|
-
<ApiSection
|
|
87
|
+
<ApiSection
|
|
88
|
+
title="MoveToPosition"
|
|
89
|
+
api="rdk:component:gantry"
|
|
90
|
+
>
|
|
73
91
|
<Query query={positionQuery}>
|
|
74
92
|
{@const positions = positionQuery.data}
|
|
75
93
|
{#if positions !== undefined}
|
|
@@ -106,6 +124,7 @@
|
|
|
106
124
|
</ApiSection>
|
|
107
125
|
<ApiSection
|
|
108
126
|
title="Home"
|
|
127
|
+
api="rdk:component:gantry"
|
|
109
128
|
description="Run the homing sequence"
|
|
110
129
|
>
|
|
111
130
|
<Home
|
|
@@ -116,7 +135,10 @@
|
|
|
116
135
|
</div>
|
|
117
136
|
</div>
|
|
118
137
|
<div class="ml-auto flex w-full max-w-40 flex-col divide-y">
|
|
119
|
-
<ApiSection
|
|
138
|
+
<ApiSection
|
|
139
|
+
title="Stop"
|
|
140
|
+
api="rdk:component:gantry"
|
|
141
|
+
>
|
|
120
142
|
<StopButton
|
|
121
143
|
error={stopMutation.error}
|
|
122
144
|
onStop={() => {
|
|
@@ -126,6 +148,7 @@
|
|
|
126
148
|
</ApiSection>
|
|
127
149
|
<IsMoving
|
|
128
150
|
client={GantryClient}
|
|
151
|
+
api="rdk:component:gantry"
|
|
129
152
|
{partID}
|
|
130
153
|
{resourceName}
|
|
131
154
|
/>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { GantryClient } from '@viamrobotics/sdk'
|
|
3
|
+
import { createResourceClient, createResourceQuery } from '@viamrobotics/svelte-sdk'
|
|
4
|
+
|
|
5
|
+
import ApiSection from '../../api-section.svelte'
|
|
6
|
+
import Queries from '../../queries.svelte'
|
|
7
|
+
|
|
8
|
+
import PositionAndLengths from './position-and-lengths.svelte'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
partID: string
|
|
12
|
+
resourceName: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { partID, resourceName }: Props = $props()
|
|
16
|
+
|
|
17
|
+
const client = createResourceClient(
|
|
18
|
+
GantryClient,
|
|
19
|
+
() => partID,
|
|
20
|
+
() => resourceName
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const options = { refetchInterval: 500 }
|
|
24
|
+
const positionQuery = createResourceQuery(client, 'getPosition', options)
|
|
25
|
+
const lengthsQuery = createResourceQuery(client, 'getLengths', options)
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<ApiSection
|
|
29
|
+
title="GetPosition"
|
|
30
|
+
bottomText="Updates automatically"
|
|
31
|
+
class="grow"
|
|
32
|
+
>
|
|
33
|
+
<Queries queries={[positionQuery, lengthsQuery]}>
|
|
34
|
+
{@const positions = positionQuery.data}
|
|
35
|
+
{@const lengths = lengthsQuery.data ?? []}
|
|
36
|
+
{#if positions !== undefined}
|
|
37
|
+
<PositionAndLengths
|
|
38
|
+
{positions}
|
|
39
|
+
{lengths}
|
|
40
|
+
/>
|
|
41
|
+
{/if}
|
|
42
|
+
</Queries>
|
|
43
|
+
</ApiSection>
|