@luxonis/visualizer-protobuf 2.16.2 → 2.18.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/FoxgloveServer-C39Uooyk.js +1172 -0
- package/dist/{WorkerImageDecoder.worker-DCoSYoLL.js → WorkerImageDecoder.worker-tkX9-IYo.js} +3 -2
- package/dist/_commonjsHelpers-E-ZsRS8r.js +32 -0
- package/dist/{comlink-D0blLC4P.js → comlink-DHMAu6X7.js} +1 -1
- package/dist/{communicator-CkB-oBVq.js → communicator-D49kmBTQ.js} +1 -1
- package/dist/{decodeImage-NYPkamnK.js → decodeImage-C8kB6T3V.js} +1 -1
- package/dist/deserialization.worker-DsG76nP8.js +1326 -0
- package/dist/{foxglove-protocol-RZlF5fna.js → foxglove-protocol-CYoMweAY.js} +1 -1
- package/dist/{i18next-C5Qe4-E1.js → i18next-IYI3-Nuv.js} +1624 -3124
- package/dist/{i420ToRgbaToPoitcloud.worker-CQFm7P7B.js → i420ToRgbaToPoitcloud.worker-CzFC0VI1.js} +1 -1
- package/dist/{index-_CotNV5x.js → index-4PQpGzhb.js} +10 -8
- package/dist/{index-C8kEVNt8.js → index-BFMXTxLw.js} +10 -8
- package/dist/{index-D7BaFI3k.js → index-BQecGu9I.js} +10 -8
- package/dist/{index-BFmZhB_k.js → index-BT9CBn7l.js} +2663 -2658
- package/dist/{index-CGZy-t2h.js → index-BWittpbR.js} +10 -8
- package/dist/{index-BRyhvg1u.js → index-BeQ1w8aW.js} +10 -8
- package/dist/{index-B-NuHgKz.js → index-BomoqOv5.js} +10 -8
- package/dist/{index-qRQvVkdj.js → index-ByIsztCr.js} +10 -8
- package/dist/{index-C7bn4vhH.js → index-CJRhjhJ0.js} +10 -8
- package/dist/{index-De_-85Dx.js → index-CR6XGTJc.js} +26206 -31958
- package/dist/{index-BflsEH7y.js → index-CXIVXFcJ.js} +13 -10
- package/dist/{index-DeqZpaJF.js → index-CXThSQcL.js} +10 -8
- package/dist/{index-BA7oWwVg.js → index-CcIi7pJR.js} +10 -8
- package/dist/{index-BDNOxLbq.js → index-CcP1Qppv.js} +10 -8
- package/dist/{index-BsSLQ0Qh.js → index-Ci0X5xT3.js} +10 -8
- package/dist/{index-D_n427cy.js → index-CrtBH66u.js} +10 -8
- package/dist/{index--q0v8_7h.js → index-DUUnuN10.js} +10 -8
- package/dist/{index-C3EAt3Mi.js → index-DchGURxJ.js} +10 -8
- package/dist/{index-Cls5O6Ds.js → index-DdKOhCXT.js} +10 -8
- package/dist/index.js +10 -8
- package/dist/isArrayLikeObject-Bytw9p-q.js +1503 -0
- package/dist/lib/src/components/Panel.d.ts +1 -0
- package/dist/lib/src/components/Panel.d.ts.map +1 -1
- package/dist/lib/src/components/Panel.js +2 -2
- package/dist/lib/src/components/Panel.js.map +1 -1
- package/dist/lib/src/components/PanelToolbar.d.ts +1 -0
- package/dist/lib/src/components/PanelToolbar.d.ts.map +1 -1
- package/dist/lib/src/components/PanelToolbar.js +6 -3
- package/dist/lib/src/components/PanelToolbar.js.map +1 -1
- package/dist/lib/src/components/measure-render-delay.d.ts.map +1 -1
- package/dist/lib/src/components/measure-render-delay.js +5 -0
- package/dist/lib/src/components/measure-render-delay.js.map +1 -1
- package/dist/lib/src/messaging/{deserialization.d.ts → deserialization.worker.d.ts} +6 -2
- package/dist/lib/src/messaging/deserialization.worker.d.ts.map +1 -0
- package/dist/lib/src/messaging/{deserialization.js → deserialization.worker.js} +28 -3
- package/dist/lib/src/messaging/deserialization.worker.js.map +1 -0
- package/dist/lib/src/messaging/message-handler.d.ts.map +1 -1
- package/dist/lib/src/messaging/message-handler.js +14 -20
- package/dist/lib/src/messaging/message-handler.js.map +1 -1
- package/dist/lib/src/panels/ImagePanel.d.ts +3 -5
- package/dist/lib/src/panels/ImagePanel.d.ts.map +1 -1
- package/dist/lib/src/panels/ImagePanel.js +1 -0
- package/dist/lib/src/panels/ImagePanel.js.map +1 -1
- package/dist/lib/src/panels/PointCloudPanel.d.ts +2 -0
- package/dist/lib/src/panels/PointCloudPanel.d.ts.map +1 -1
- package/dist/lib/src/panels/PointCloudPanel.js +29 -4
- package/dist/lib/src/panels/PointCloudPanel.js.map +1 -1
- package/dist/lib/src/utils/poitcloud-sync.d.ts.map +1 -1
- package/dist/lib/src/utils/poitcloud-sync.js +5 -2
- package/dist/lib/src/utils/poitcloud-sync.js.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js +3 -0
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/CameraStateSettings.js +2 -2
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/CameraStateSettings.js.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.d.ts.map +1 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.js +0 -1
- package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.js.map +1 -1
- package/dist/{FoxgloveServer-DiLI7KZU.js → protobuf-Cr0sn6Ua.js} +996 -2196
- package/dist/tslib.es6-D98N6tjc.js +4116 -0
- package/dist/useMessageReducer-Cg30zaG9.js +422 -0
- package/dist/{worker-CtuCYYTr.js → worker-B5OJw-Fq.js} +5 -3
- package/dist/{worker-Bd7K1fGT.js → worker-aVL4LGa3.js} +5 -3
- package/package.json +1 -1
- package/dist/lib/src/messaging/deserialization.d.ts.map +0 -1
- package/dist/lib/src/messaging/deserialization.js.map +0 -1
|
@@ -0,0 +1,1326 @@
|
|
|
1
|
+
import { e as expose } from './comlink-DHMAu6X7.js';
|
|
2
|
+
import { t as typescript } from './useMessageReducer-Cg30zaG9.js';
|
|
3
|
+
import { e as estimateObjectSize, U as uint8ArrayToUint16Array, d as dist } from './tslib.es6-D98N6tjc.js';
|
|
4
|
+
import { T as Type, P as PointsAnnotationType, p as protobufsBySchema, a as Profile } from './protobuf-Cr0sn6Ua.js';
|
|
5
|
+
import 'react';
|
|
6
|
+
import './_commonjsHelpers-E-ZsRS8r.js';
|
|
7
|
+
import 'zustand';
|
|
8
|
+
import 'react-mosaic-component';
|
|
9
|
+
import '@mui/material';
|
|
10
|
+
import './isArrayLikeObject-Bytw9p-q.js';
|
|
11
|
+
import 'protobufjs/minimal';
|
|
12
|
+
|
|
13
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
14
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
15
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
16
|
+
|
|
17
|
+
const glColor = (r, g, b, a) => ({
|
|
18
|
+
r: r / 255,
|
|
19
|
+
g: g / 255,
|
|
20
|
+
b: b / 255,
|
|
21
|
+
a
|
|
22
|
+
});
|
|
23
|
+
const DEFAULT_WIDTH = 1920;
|
|
24
|
+
const DEFAULT_HEIGHT = 1080;
|
|
25
|
+
function interpolate(width, height, base) {
|
|
26
|
+
const widthScale = width / DEFAULT_WIDTH;
|
|
27
|
+
const heightScale = height / DEFAULT_HEIGHT;
|
|
28
|
+
const scale = (widthScale + heightScale) / 2;
|
|
29
|
+
return base * scale;
|
|
30
|
+
}
|
|
31
|
+
const DEFAULT_SIZE = 42;
|
|
32
|
+
const DEFAULT_THICKNESS = 10;
|
|
33
|
+
const getTextSize = (width, height) => interpolate(width, height, DEFAULT_SIZE);
|
|
34
|
+
const getBorderThickness = (width, height) => interpolate(width, height, DEFAULT_THICKNESS);
|
|
35
|
+
|
|
36
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
37
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
38
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
39
|
+
|
|
40
|
+
const GROUP_COLORS = {
|
|
41
|
+
entity: {
|
|
42
|
+
fill: glColor(21, 56, 127, 0.1),
|
|
43
|
+
outline: glColor(21, 56, 127, 1)
|
|
44
|
+
},
|
|
45
|
+
item: {
|
|
46
|
+
fill: glColor(21, 127, 88, 0.1),
|
|
47
|
+
outline: glColor(21, 127, 88, 1)
|
|
48
|
+
},
|
|
49
|
+
bulk: {
|
|
50
|
+
fill: glColor(127, 21, 42, 0.1),
|
|
51
|
+
outline: glColor(127, 21, 42, 1)
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const DETECTION_STYLE = [{
|
|
55
|
+
label: "Person",
|
|
56
|
+
...GROUP_COLORS.entity
|
|
57
|
+
}, {
|
|
58
|
+
label: "Bicycle",
|
|
59
|
+
...GROUP_COLORS.bulk
|
|
60
|
+
}, {
|
|
61
|
+
label: "Car",
|
|
62
|
+
...GROUP_COLORS.bulk
|
|
63
|
+
}, {
|
|
64
|
+
label: "Motorbike",
|
|
65
|
+
...GROUP_COLORS.bulk
|
|
66
|
+
}, {
|
|
67
|
+
label: "Aeroplane",
|
|
68
|
+
...GROUP_COLORS.bulk
|
|
69
|
+
}, {
|
|
70
|
+
label: "Bus",
|
|
71
|
+
...GROUP_COLORS.bulk
|
|
72
|
+
}, {
|
|
73
|
+
label: "Train",
|
|
74
|
+
...GROUP_COLORS.bulk
|
|
75
|
+
}, {
|
|
76
|
+
label: "Truck",
|
|
77
|
+
...GROUP_COLORS.bulk
|
|
78
|
+
}, {
|
|
79
|
+
label: "Boat",
|
|
80
|
+
...GROUP_COLORS.bulk
|
|
81
|
+
}, {
|
|
82
|
+
label: "Traffic Light",
|
|
83
|
+
...GROUP_COLORS.item
|
|
84
|
+
}, {
|
|
85
|
+
label: "Fire Hydrant",
|
|
86
|
+
...GROUP_COLORS.item
|
|
87
|
+
}, {
|
|
88
|
+
label: "Stop Sign",
|
|
89
|
+
...GROUP_COLORS.item
|
|
90
|
+
}, {
|
|
91
|
+
label: "Parking Meter",
|
|
92
|
+
...GROUP_COLORS.item
|
|
93
|
+
}, {
|
|
94
|
+
label: "Bench",
|
|
95
|
+
...GROUP_COLORS.bulk
|
|
96
|
+
}, {
|
|
97
|
+
label: "Bird",
|
|
98
|
+
...GROUP_COLORS.entity
|
|
99
|
+
}, {
|
|
100
|
+
label: "Cat",
|
|
101
|
+
...GROUP_COLORS.entity
|
|
102
|
+
}, {
|
|
103
|
+
label: "Dog",
|
|
104
|
+
...GROUP_COLORS.entity
|
|
105
|
+
}, {
|
|
106
|
+
label: "Horse",
|
|
107
|
+
...GROUP_COLORS.entity
|
|
108
|
+
}, {
|
|
109
|
+
label: "Sheep",
|
|
110
|
+
...GROUP_COLORS.entity
|
|
111
|
+
}, {
|
|
112
|
+
label: "Cow",
|
|
113
|
+
...GROUP_COLORS.entity
|
|
114
|
+
}, {
|
|
115
|
+
label: "Elephant",
|
|
116
|
+
...GROUP_COLORS.entity
|
|
117
|
+
}, {
|
|
118
|
+
label: "Bear",
|
|
119
|
+
...GROUP_COLORS.entity
|
|
120
|
+
}, {
|
|
121
|
+
label: "Zebra",
|
|
122
|
+
...GROUP_COLORS.entity
|
|
123
|
+
}, {
|
|
124
|
+
label: "Giraffe",
|
|
125
|
+
...GROUP_COLORS.entity
|
|
126
|
+
}, {
|
|
127
|
+
label: "Backpack",
|
|
128
|
+
...GROUP_COLORS.item
|
|
129
|
+
}, {
|
|
130
|
+
label: "Umbrella",
|
|
131
|
+
...GROUP_COLORS.item
|
|
132
|
+
}, {
|
|
133
|
+
label: "Handbag",
|
|
134
|
+
...GROUP_COLORS.item
|
|
135
|
+
}, {
|
|
136
|
+
label: "Tie",
|
|
137
|
+
...GROUP_COLORS.item
|
|
138
|
+
}, {
|
|
139
|
+
label: "Suitcase",
|
|
140
|
+
...GROUP_COLORS.item
|
|
141
|
+
}, {
|
|
142
|
+
label: "Frisbee",
|
|
143
|
+
...GROUP_COLORS.item
|
|
144
|
+
}, {
|
|
145
|
+
label: "Skis",
|
|
146
|
+
...GROUP_COLORS.bulk
|
|
147
|
+
}, {
|
|
148
|
+
label: "Snowboard",
|
|
149
|
+
...GROUP_COLORS.bulk
|
|
150
|
+
}, {
|
|
151
|
+
label: "Sports Ball",
|
|
152
|
+
...GROUP_COLORS.item
|
|
153
|
+
}, {
|
|
154
|
+
label: "Lite",
|
|
155
|
+
...GROUP_COLORS.item
|
|
156
|
+
}, {
|
|
157
|
+
label: "Baseball Bat",
|
|
158
|
+
...GROUP_COLORS.item
|
|
159
|
+
}, {
|
|
160
|
+
label: "Baseball Glove",
|
|
161
|
+
...GROUP_COLORS.item
|
|
162
|
+
}, {
|
|
163
|
+
label: "Skateboard",
|
|
164
|
+
...GROUP_COLORS.item
|
|
165
|
+
}, {
|
|
166
|
+
label: "Surfboard",
|
|
167
|
+
...GROUP_COLORS.bulk
|
|
168
|
+
}, {
|
|
169
|
+
label: "Tennis Racket",
|
|
170
|
+
...GROUP_COLORS.item
|
|
171
|
+
}, {
|
|
172
|
+
label: "Bottle",
|
|
173
|
+
...GROUP_COLORS.item
|
|
174
|
+
}, {
|
|
175
|
+
label: "Wine Glass",
|
|
176
|
+
...GROUP_COLORS.item
|
|
177
|
+
}, {
|
|
178
|
+
label: "Cup",
|
|
179
|
+
...GROUP_COLORS.item
|
|
180
|
+
}, {
|
|
181
|
+
label: "Fork",
|
|
182
|
+
...GROUP_COLORS.item
|
|
183
|
+
}, {
|
|
184
|
+
label: "Knife",
|
|
185
|
+
...GROUP_COLORS.item
|
|
186
|
+
}, {
|
|
187
|
+
label: "Spoon",
|
|
188
|
+
...GROUP_COLORS.item
|
|
189
|
+
}, {
|
|
190
|
+
label: "Bowl",
|
|
191
|
+
...GROUP_COLORS.item
|
|
192
|
+
}, {
|
|
193
|
+
label: "Banana",
|
|
194
|
+
...GROUP_COLORS.item
|
|
195
|
+
}, {
|
|
196
|
+
label: "Apple",
|
|
197
|
+
...GROUP_COLORS.item
|
|
198
|
+
}, {
|
|
199
|
+
label: "Sandwich",
|
|
200
|
+
...GROUP_COLORS.item
|
|
201
|
+
}, {
|
|
202
|
+
label: "Orange",
|
|
203
|
+
...GROUP_COLORS.item
|
|
204
|
+
}, {
|
|
205
|
+
label: "Broccoli",
|
|
206
|
+
...GROUP_COLORS.item
|
|
207
|
+
}, {
|
|
208
|
+
label: "Carrot",
|
|
209
|
+
...GROUP_COLORS.item
|
|
210
|
+
}, {
|
|
211
|
+
label: "Hot Dog",
|
|
212
|
+
...GROUP_COLORS.item
|
|
213
|
+
}, {
|
|
214
|
+
label: "Pizza",
|
|
215
|
+
...GROUP_COLORS.item
|
|
216
|
+
}, {
|
|
217
|
+
label: "Donut",
|
|
218
|
+
...GROUP_COLORS.item
|
|
219
|
+
}, {
|
|
220
|
+
label: "Cake",
|
|
221
|
+
...GROUP_COLORS.item
|
|
222
|
+
}, {
|
|
223
|
+
label: "Chair",
|
|
224
|
+
...GROUP_COLORS.bulk
|
|
225
|
+
}, {
|
|
226
|
+
label: "Sofa",
|
|
227
|
+
...GROUP_COLORS.bulk
|
|
228
|
+
}, {
|
|
229
|
+
label: "Potted Plant",
|
|
230
|
+
...GROUP_COLORS.item
|
|
231
|
+
}, {
|
|
232
|
+
label: "Bed",
|
|
233
|
+
...GROUP_COLORS.bulk
|
|
234
|
+
}, {
|
|
235
|
+
label: "Diningtable",
|
|
236
|
+
...GROUP_COLORS.bulk
|
|
237
|
+
}, {
|
|
238
|
+
label: "Toilet",
|
|
239
|
+
...GROUP_COLORS.bulk
|
|
240
|
+
}, {
|
|
241
|
+
label: "TV Monitor",
|
|
242
|
+
...GROUP_COLORS.item
|
|
243
|
+
}, {
|
|
244
|
+
label: "Laptop",
|
|
245
|
+
...GROUP_COLORS.item
|
|
246
|
+
}, {
|
|
247
|
+
label: "Mouse",
|
|
248
|
+
...GROUP_COLORS.item
|
|
249
|
+
}, {
|
|
250
|
+
label: "Remote",
|
|
251
|
+
...GROUP_COLORS.item
|
|
252
|
+
}, {
|
|
253
|
+
label: "Keyboard",
|
|
254
|
+
...GROUP_COLORS.item
|
|
255
|
+
}, {
|
|
256
|
+
label: "Cell Phone",
|
|
257
|
+
...GROUP_COLORS.item
|
|
258
|
+
}, {
|
|
259
|
+
label: "Microwave",
|
|
260
|
+
...GROUP_COLORS.item
|
|
261
|
+
}, {
|
|
262
|
+
label: "Oven",
|
|
263
|
+
...GROUP_COLORS.item
|
|
264
|
+
}, {
|
|
265
|
+
label: "Toaster",
|
|
266
|
+
...GROUP_COLORS.item
|
|
267
|
+
}, {
|
|
268
|
+
label: "Sink",
|
|
269
|
+
...GROUP_COLORS.item
|
|
270
|
+
}, {
|
|
271
|
+
label: "Refrigerator",
|
|
272
|
+
...GROUP_COLORS.bulk
|
|
273
|
+
}, {
|
|
274
|
+
label: "Book",
|
|
275
|
+
...GROUP_COLORS.item
|
|
276
|
+
}, {
|
|
277
|
+
label: "Clock",
|
|
278
|
+
...GROUP_COLORS.item
|
|
279
|
+
}, {
|
|
280
|
+
label: "Vase",
|
|
281
|
+
...GROUP_COLORS.item
|
|
282
|
+
}, {
|
|
283
|
+
label: "Scissors",
|
|
284
|
+
...GROUP_COLORS.item
|
|
285
|
+
}, {
|
|
286
|
+
label: "Teddy Bear",
|
|
287
|
+
...GROUP_COLORS.item
|
|
288
|
+
}, {
|
|
289
|
+
label: "Hair Drier",
|
|
290
|
+
...GROUP_COLORS.item
|
|
291
|
+
}, {
|
|
292
|
+
label: "Toothbrush",
|
|
293
|
+
...GROUP_COLORS.item
|
|
294
|
+
}];
|
|
295
|
+
const DEBUG_COLOR = {
|
|
296
|
+
r: 0,
|
|
297
|
+
g: 0.5,
|
|
298
|
+
b: 0,
|
|
299
|
+
a: 1
|
|
300
|
+
};
|
|
301
|
+
const DEFAULT_STYLE = {
|
|
302
|
+
label: null,
|
|
303
|
+
...GROUP_COLORS.item
|
|
304
|
+
};
|
|
305
|
+
const DEFAULT_TEXT_COLOR = {
|
|
306
|
+
r: 1,
|
|
307
|
+
g: 1,
|
|
308
|
+
b: 1,
|
|
309
|
+
a: 1
|
|
310
|
+
};
|
|
311
|
+
const DEFAULT_BACKGROUND_COLOR = {
|
|
312
|
+
r: 0,
|
|
313
|
+
g: 0,
|
|
314
|
+
b: 0,
|
|
315
|
+
a: 0
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
function fromMillis(value) {
|
|
319
|
+
let sec = Math.trunc(value / 1000);
|
|
320
|
+
let nsec = Math.round((value - sec * 1000) * 1e6);
|
|
321
|
+
sec += Math.trunc(nsec / 1e9);
|
|
322
|
+
nsec %= 1e9;
|
|
323
|
+
return {
|
|
324
|
+
sec,
|
|
325
|
+
nsec
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function parsePixelFormat(format) {
|
|
329
|
+
switch (format) {
|
|
330
|
+
case "BGRA":
|
|
331
|
+
return ["bgra8", 3];
|
|
332
|
+
case "BGRX":
|
|
333
|
+
return ["bgr8", 3];
|
|
334
|
+
// Closest supported
|
|
335
|
+
case "I420":
|
|
336
|
+
case "I420A":
|
|
337
|
+
return ['I420', 2];
|
|
338
|
+
case "I422":
|
|
339
|
+
case "I444":
|
|
340
|
+
return ['yuv422', 2];
|
|
341
|
+
case "RGBA":
|
|
342
|
+
return ["rgba8", 1];
|
|
343
|
+
case "RGBX":
|
|
344
|
+
return ["rgb8", 1];
|
|
345
|
+
// Closest supported
|
|
346
|
+
case "NV12":
|
|
347
|
+
return ["nv12", 1];
|
|
348
|
+
default:
|
|
349
|
+
// Unsupported
|
|
350
|
+
return ["bgra8", 3];
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function parseMessageType(type) {
|
|
354
|
+
switch (type) {
|
|
355
|
+
case Type.YUV422i:
|
|
356
|
+
case Type.YUV422p:
|
|
357
|
+
return ["yuv422", 2];
|
|
358
|
+
case Type.NV12:
|
|
359
|
+
return ["nv12", 1];
|
|
360
|
+
case Type.RGB888i:
|
|
361
|
+
return ["rgb8", 3];
|
|
362
|
+
case Type.RGB888p:
|
|
363
|
+
return ["rgb8p", 1];
|
|
364
|
+
case Type.RGBA8888:
|
|
365
|
+
return ["rgba8", 1];
|
|
366
|
+
case Type.BGR888i:
|
|
367
|
+
return ["bgr8i", 3];
|
|
368
|
+
case Type.BGR888p:
|
|
369
|
+
return ["bgr8p", 3];
|
|
370
|
+
case Type.RAW16:
|
|
371
|
+
return ["mono16", 2];
|
|
372
|
+
case Type.RAW8:
|
|
373
|
+
return ["mono8", 2];
|
|
374
|
+
default:
|
|
375
|
+
throw new Error(`Unsupported encoding ${Type[type]}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function parseMessage(message) {
|
|
379
|
+
const width = Number(message.fb?.width ?? message.sourceFb?.width ?? 1920);
|
|
380
|
+
const height = Number(message.fb?.height ?? message.sourceFb?.height ?? 1200);
|
|
381
|
+
const stride = message.fb?.stride ?? message.sourceFb?.stride ?? null;
|
|
382
|
+
const p2Offset = message.fb?.p2Offset ?? message.sourceFb?.p2Offset ?? null;
|
|
383
|
+
const p1Offset = message.fb?.p1Offset ?? message.sourceFb?.p1Offset ?? null;
|
|
384
|
+
let planeStride = p1Offset != null && p2Offset != null ? p2Offset - p1Offset : 0;
|
|
385
|
+
if (planeStride <= 0) {
|
|
386
|
+
planeStride = null;
|
|
387
|
+
}
|
|
388
|
+
const type = message.fb?.type ?? message.sourceFb?.type ?? Type.RGB888p;
|
|
389
|
+
const [encoding, step] = parseMessageType(type);
|
|
390
|
+
const receiveTime = message.ts ?? message.tsDevice ?? fromMillis(Date.now());
|
|
391
|
+
return {
|
|
392
|
+
encoding,
|
|
393
|
+
step: stride ?? step,
|
|
394
|
+
receiveTime,
|
|
395
|
+
width,
|
|
396
|
+
height,
|
|
397
|
+
stride,
|
|
398
|
+
planeStride,
|
|
399
|
+
type
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
404
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
405
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
406
|
+
|
|
407
|
+
function deserializeImgDetectionsCustom({
|
|
408
|
+
topic,
|
|
409
|
+
message,
|
|
410
|
+
callback,
|
|
411
|
+
topicSizes
|
|
412
|
+
}) {
|
|
413
|
+
const {
|
|
414
|
+
receiveTime
|
|
415
|
+
} = parseMessage(message);
|
|
416
|
+
const {
|
|
417
|
+
width,
|
|
418
|
+
height
|
|
419
|
+
} = topicSizes.values().next().value ?? {
|
|
420
|
+
width: DEFAULT_WIDTH,
|
|
421
|
+
height: DEFAULT_HEIGHT
|
|
422
|
+
};
|
|
423
|
+
const xMultiplier = width >= height ? 1 : height / width;
|
|
424
|
+
const yMultiplier = height >= width ? 1 : width / height;
|
|
425
|
+
const points = [];
|
|
426
|
+
const texts = [];
|
|
427
|
+
const circles = [];
|
|
428
|
+
for (const annotations of message.annotations) {
|
|
429
|
+
points.push(...annotations.points.map(annotation => ({
|
|
430
|
+
timestamp: receiveTime,
|
|
431
|
+
type: annotation.type === PointsAnnotationType.UNRECOGNIZED ? typescript.PointsAnnotationType.UNKNOWN : Number(annotation.type),
|
|
432
|
+
points: annotation.points,
|
|
433
|
+
outline_color: annotation.outlineColor ?? DEFAULT_STYLE.outline,
|
|
434
|
+
outline_colors: [],
|
|
435
|
+
fill_color: annotation.fillColor ?? DEFAULT_STYLE.fill,
|
|
436
|
+
thickness: annotation.thickness
|
|
437
|
+
})));
|
|
438
|
+
texts.push(...annotations.texts.map(annotation => ({
|
|
439
|
+
timestamp: receiveTime,
|
|
440
|
+
position: annotation.position ?? {
|
|
441
|
+
x: 0,
|
|
442
|
+
y: 0
|
|
443
|
+
},
|
|
444
|
+
text: annotation.text,
|
|
445
|
+
font_size: annotation.fontSize ?? getTextSize(width, height),
|
|
446
|
+
text_color: annotation.textColor ?? DEFAULT_TEXT_COLOR,
|
|
447
|
+
background_color: annotation.backgroundColor ?? DEFAULT_BACKGROUND_COLOR
|
|
448
|
+
})));
|
|
449
|
+
circles.push(...annotations.circles.map(annotation => ({
|
|
450
|
+
timestamp: receiveTime,
|
|
451
|
+
xMultiplier,
|
|
452
|
+
yMultiplier,
|
|
453
|
+
position: annotation.position ?? {
|
|
454
|
+
x: 0,
|
|
455
|
+
y: 0
|
|
456
|
+
},
|
|
457
|
+
diameter: annotation.diameter,
|
|
458
|
+
thickness: annotation.thickness,
|
|
459
|
+
fill_color: annotation.fillColor ?? DEFAULT_STYLE.fill,
|
|
460
|
+
outline_color: annotation.outlineColor ?? DEFAULT_STYLE.outline
|
|
461
|
+
})));
|
|
462
|
+
}
|
|
463
|
+
const foxgloveMessage = {
|
|
464
|
+
points,
|
|
465
|
+
texts,
|
|
466
|
+
circles
|
|
467
|
+
};
|
|
468
|
+
callback({
|
|
469
|
+
topic,
|
|
470
|
+
receiveTime,
|
|
471
|
+
message: foxgloveMessage,
|
|
472
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
473
|
+
schemaName: "foxglove.ImageAnnotations"
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
478
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
479
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
480
|
+
|
|
481
|
+
function deserializeImgDetections({
|
|
482
|
+
topic,
|
|
483
|
+
message,
|
|
484
|
+
callback,
|
|
485
|
+
topicSizes
|
|
486
|
+
}) {
|
|
487
|
+
const {
|
|
488
|
+
receiveTime
|
|
489
|
+
} = parseMessage(message);
|
|
490
|
+
const foxgloveMessage = {
|
|
491
|
+
points: [],
|
|
492
|
+
texts: [],
|
|
493
|
+
circles: []
|
|
494
|
+
};
|
|
495
|
+
if (message.detections.length > 0) {
|
|
496
|
+
for (const detection of message.detections) {
|
|
497
|
+
const detectionWidth = detection.xmax - detection.xmin;
|
|
498
|
+
const {
|
|
499
|
+
width,
|
|
500
|
+
height
|
|
501
|
+
} = topicSizes.values().next().value ?? {
|
|
502
|
+
width: DEFAULT_WIDTH,
|
|
503
|
+
height: DEFAULT_HEIGHT
|
|
504
|
+
};
|
|
505
|
+
const ratio = width / height;
|
|
506
|
+
const highligtLength = 0.035;
|
|
507
|
+
const highlightSizeX = Math.min(highligtLength, detectionWidth);
|
|
508
|
+
const highlightSizeY = Math.min(highligtLength * ratio, detection.ymax - detection.ymin);
|
|
509
|
+
const style = DETECTION_STYLE[detection.label] ?? DEFAULT_STYLE;
|
|
510
|
+
foxgloveMessage.points.push({
|
|
511
|
+
timestamp: receiveTime,
|
|
512
|
+
points: [{
|
|
513
|
+
x: detection.xmin,
|
|
514
|
+
y: detection.ymin
|
|
515
|
+
}, {
|
|
516
|
+
x: detection.xmin,
|
|
517
|
+
y: detection.ymax
|
|
518
|
+
}, {
|
|
519
|
+
x: detection.xmax,
|
|
520
|
+
y: detection.ymax
|
|
521
|
+
}, {
|
|
522
|
+
x: detection.xmax,
|
|
523
|
+
y: detection.ymin
|
|
524
|
+
}],
|
|
525
|
+
type: typescript.PointsAnnotationType.LINE_LOOP,
|
|
526
|
+
outline_colors: [],
|
|
527
|
+
thickness: 0,
|
|
528
|
+
outline_color: DEBUG_COLOR,
|
|
529
|
+
fill_color: style.fill
|
|
530
|
+
});
|
|
531
|
+
const baseHighlightConfig = {
|
|
532
|
+
timestamp: receiveTime,
|
|
533
|
+
type: typescript.PointsAnnotationType.LINE_LIST,
|
|
534
|
+
outline_colors: [],
|
|
535
|
+
thickness: getBorderThickness(width, height),
|
|
536
|
+
outline_color: style.outline,
|
|
537
|
+
fill_color: DEBUG_COLOR
|
|
538
|
+
};
|
|
539
|
+
foxgloveMessage.points.push({
|
|
540
|
+
...baseHighlightConfig,
|
|
541
|
+
points: [{
|
|
542
|
+
x: detection.xmin,
|
|
543
|
+
y: detection.ymin
|
|
544
|
+
}, {
|
|
545
|
+
x: detection.xmin + highlightSizeX,
|
|
546
|
+
y: detection.ymin
|
|
547
|
+
}]
|
|
548
|
+
});
|
|
549
|
+
foxgloveMessage.points.push({
|
|
550
|
+
...baseHighlightConfig,
|
|
551
|
+
points: [{
|
|
552
|
+
x: detection.xmin,
|
|
553
|
+
y: detection.ymin
|
|
554
|
+
}, {
|
|
555
|
+
x: detection.xmin,
|
|
556
|
+
y: detection.ymin + highlightSizeY
|
|
557
|
+
}]
|
|
558
|
+
});
|
|
559
|
+
foxgloveMessage.points.push({
|
|
560
|
+
...baseHighlightConfig,
|
|
561
|
+
points: [{
|
|
562
|
+
x: detection.xmax,
|
|
563
|
+
y: detection.ymin
|
|
564
|
+
}, {
|
|
565
|
+
x: detection.xmax - highlightSizeX,
|
|
566
|
+
y: detection.ymin
|
|
567
|
+
}]
|
|
568
|
+
});
|
|
569
|
+
foxgloveMessage.points.push({
|
|
570
|
+
...baseHighlightConfig,
|
|
571
|
+
points: [{
|
|
572
|
+
x: detection.xmax,
|
|
573
|
+
y: detection.ymin
|
|
574
|
+
}, {
|
|
575
|
+
x: detection.xmax,
|
|
576
|
+
y: detection.ymin + highlightSizeY
|
|
577
|
+
}]
|
|
578
|
+
});
|
|
579
|
+
foxgloveMessage.points.push({
|
|
580
|
+
...baseHighlightConfig,
|
|
581
|
+
points: [{
|
|
582
|
+
x: detection.xmax,
|
|
583
|
+
y: detection.ymax
|
|
584
|
+
}, {
|
|
585
|
+
x: detection.xmax - highlightSizeX,
|
|
586
|
+
y: detection.ymax
|
|
587
|
+
}]
|
|
588
|
+
});
|
|
589
|
+
foxgloveMessage.points.push({
|
|
590
|
+
...baseHighlightConfig,
|
|
591
|
+
points: [{
|
|
592
|
+
x: detection.xmax,
|
|
593
|
+
y: detection.ymax
|
|
594
|
+
}, {
|
|
595
|
+
x: detection.xmax,
|
|
596
|
+
y: detection.ymax - highlightSizeY
|
|
597
|
+
}]
|
|
598
|
+
});
|
|
599
|
+
foxgloveMessage.points.push({
|
|
600
|
+
...baseHighlightConfig,
|
|
601
|
+
points: [{
|
|
602
|
+
x: detection.xmin,
|
|
603
|
+
y: detection.ymax
|
|
604
|
+
}, {
|
|
605
|
+
x: detection.xmin + highlightSizeX,
|
|
606
|
+
y: detection.ymax
|
|
607
|
+
}]
|
|
608
|
+
});
|
|
609
|
+
foxgloveMessage.points.push({
|
|
610
|
+
...baseHighlightConfig,
|
|
611
|
+
points: [{
|
|
612
|
+
x: detection.xmin,
|
|
613
|
+
y: detection.ymax
|
|
614
|
+
}, {
|
|
615
|
+
x: detection.xmin,
|
|
616
|
+
y: detection.ymax - highlightSizeY
|
|
617
|
+
}]
|
|
618
|
+
});
|
|
619
|
+
const label = `${style.label ?? `Unknown #${detection.label}`} ${Math.round(detection.confidence * 100)}%`;
|
|
620
|
+
foxgloveMessage.texts.push({
|
|
621
|
+
timestamp: receiveTime,
|
|
622
|
+
position: {
|
|
623
|
+
x: detection.xmin + highligtLength / 2,
|
|
624
|
+
y: detection.ymin + highlightSizeY
|
|
625
|
+
},
|
|
626
|
+
text: label,
|
|
627
|
+
font_size: getTextSize(width, height),
|
|
628
|
+
text_color: DEFAULT_TEXT_COLOR,
|
|
629
|
+
background_color: DEFAULT_BACKGROUND_COLOR
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
callback({
|
|
634
|
+
topic,
|
|
635
|
+
receiveTime,
|
|
636
|
+
message: foxgloveMessage,
|
|
637
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
638
|
+
schemaName: "foxglove.ImageAnnotations"
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
643
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
644
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
645
|
+
|
|
646
|
+
function deserializePointCloudData({
|
|
647
|
+
topic,
|
|
648
|
+
message,
|
|
649
|
+
callback
|
|
650
|
+
}) {
|
|
651
|
+
const receiveTime = fromMillis(Date.now());
|
|
652
|
+
const foxgloveMessage = {
|
|
653
|
+
timestamp: receiveTime,
|
|
654
|
+
frame_id: `pointcloud-${topic}-frame`,
|
|
655
|
+
point_stride: 12,
|
|
656
|
+
pose: {
|
|
657
|
+
position: {
|
|
658
|
+
x: 0,
|
|
659
|
+
y: 0,
|
|
660
|
+
z: 0
|
|
661
|
+
},
|
|
662
|
+
orientation: {
|
|
663
|
+
x: 0,
|
|
664
|
+
y: 0,
|
|
665
|
+
z: 1,
|
|
666
|
+
w: 0
|
|
667
|
+
}
|
|
668
|
+
},
|
|
669
|
+
fields: [{
|
|
670
|
+
name: "x",
|
|
671
|
+
offset: 0,
|
|
672
|
+
type: typescript.NumericType.FLOAT32
|
|
673
|
+
}, {
|
|
674
|
+
name: "y",
|
|
675
|
+
offset: 4,
|
|
676
|
+
type: typescript.NumericType.FLOAT32
|
|
677
|
+
}, {
|
|
678
|
+
name: "z",
|
|
679
|
+
offset: 8,
|
|
680
|
+
type: typescript.NumericType.FLOAT32
|
|
681
|
+
}],
|
|
682
|
+
data: message.data
|
|
683
|
+
};
|
|
684
|
+
if (message.color) {
|
|
685
|
+
foxgloveMessage.fields.push({
|
|
686
|
+
name: "red",
|
|
687
|
+
offset: 12,
|
|
688
|
+
type: typescript.NumericType.UINT8
|
|
689
|
+
}, {
|
|
690
|
+
name: "green",
|
|
691
|
+
offset: 13,
|
|
692
|
+
type: typescript.NumericType.UINT8
|
|
693
|
+
}, {
|
|
694
|
+
name: "blue",
|
|
695
|
+
offset: 14,
|
|
696
|
+
type: typescript.NumericType.UINT8
|
|
697
|
+
}, {
|
|
698
|
+
name: "alpha",
|
|
699
|
+
offset: 15,
|
|
700
|
+
type: typescript.NumericType.UINT8
|
|
701
|
+
});
|
|
702
|
+
foxgloveMessage.point_stride = 16;
|
|
703
|
+
}
|
|
704
|
+
callback({
|
|
705
|
+
topic,
|
|
706
|
+
receiveTime,
|
|
707
|
+
message: foxgloveMessage,
|
|
708
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
709
|
+
schemaName: "foxglove.PointCloud"
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
714
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
715
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
716
|
+
|
|
717
|
+
function deserializeColorFrame({
|
|
718
|
+
topic,
|
|
719
|
+
message,
|
|
720
|
+
callback
|
|
721
|
+
}) {
|
|
722
|
+
const {
|
|
723
|
+
receiveTime,
|
|
724
|
+
encoding,
|
|
725
|
+
step,
|
|
726
|
+
width,
|
|
727
|
+
height,
|
|
728
|
+
stride,
|
|
729
|
+
planeStride
|
|
730
|
+
} = parseMessage(message);
|
|
731
|
+
const foxgloveMessage = {
|
|
732
|
+
timestamp: receiveTime,
|
|
733
|
+
frame_id: `color-${topic}-frame`,
|
|
734
|
+
width,
|
|
735
|
+
height,
|
|
736
|
+
encoding,
|
|
737
|
+
step: width * step,
|
|
738
|
+
data: message.data,
|
|
739
|
+
stride,
|
|
740
|
+
planeStride
|
|
741
|
+
};
|
|
742
|
+
callback({
|
|
743
|
+
topic,
|
|
744
|
+
receiveTime,
|
|
745
|
+
message: foxgloveMessage,
|
|
746
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
747
|
+
schemaName: "foxglove.RawImage"
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
752
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
753
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
754
|
+
/* eslint-disable no-underscore-dangle */
|
|
755
|
+
|
|
756
|
+
const shader = `
|
|
757
|
+
@group(0) @binding(0) var<storage, read> depthBuffer: array<u32>; // Uint16 stored as u32
|
|
758
|
+
@group(0) @binding(1) var<storage, read> intrinsicsBuffer: array<f32>;
|
|
759
|
+
@group(0) @binding(2) var<storage, read_write> xyzColorBuffer: array<u32>; // Stores XYZ + RGBA
|
|
760
|
+
|
|
761
|
+
@compute @workgroup_size(256, 1, 1)
|
|
762
|
+
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
763
|
+
let i = global_id.x;
|
|
764
|
+
let fx = intrinsicsBuffer[0];
|
|
765
|
+
let fy = intrinsicsBuffer[1];
|
|
766
|
+
let cx = intrinsicsBuffer[2];
|
|
767
|
+
let cy = intrinsicsBuffer[3];
|
|
768
|
+
let scale = intrinsicsBuffer[4];
|
|
769
|
+
let width = intrinsicsBuffer[5];
|
|
770
|
+
let height = intrinsicsBuffer[6];
|
|
771
|
+
|
|
772
|
+
if (i >= u32(width * height)) { return; }
|
|
773
|
+
|
|
774
|
+
let u = i % u32(width);
|
|
775
|
+
let v = i / u32(width);
|
|
776
|
+
|
|
777
|
+
// Convert uint16 depth value to float (stored as u32, so we bitwise mask)
|
|
778
|
+
let rawDepth = depthBuffer[i] & 0xFFFFu;
|
|
779
|
+
let z = f32(rawDepth) * scale;
|
|
780
|
+
|
|
781
|
+
let x = (cx - f32(u)) * z / fx;
|
|
782
|
+
let y = (cy - f32(v)) * z / fy;
|
|
783
|
+
|
|
784
|
+
let base = i * 4u; // 4 values per point (X, Y, Z, Color)
|
|
785
|
+
|
|
786
|
+
// Convert floats to u32 representation for storage
|
|
787
|
+
xyzColorBuffer[base] = bitcast<u32>(x);
|
|
788
|
+
xyzColorBuffer[base + 1u] = bitcast<u32>(y);
|
|
789
|
+
xyzColorBuffer[base + 2u] = bitcast<u32>(z);
|
|
790
|
+
|
|
791
|
+
// Example: RGB set based on depth, Alpha is fixed at 255
|
|
792
|
+
let r = u32(clamp(z * 255.0, 0.0, 255.0));
|
|
793
|
+
let g = u32(clamp(y * 255.0, 0.0, 255.0));
|
|
794
|
+
let b = u32(clamp(x * 255.0, 0.0, 255.0));
|
|
795
|
+
xyzColorBuffer[base + 3u] = (r & 0xFFu) | ((g & 0xFFu) << 8) | ((b & 0xFFu) << 16) | (255u << 24);
|
|
796
|
+
}
|
|
797
|
+
`;
|
|
798
|
+
async function depthToPointcloudGPU(depthArray, width, height, fx, fy, cx, cy) {
|
|
799
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
800
|
+
if (!navigator.gpu) {
|
|
801
|
+
console.warn("WebGPU not supported.");
|
|
802
|
+
return depthToPointCloudBuffer(depthArray, width, height, fx, fy, cx, cy);
|
|
803
|
+
}
|
|
804
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
805
|
+
if (!adapter) {
|
|
806
|
+
console.warn("Couldn't request WebGPU adapter.");
|
|
807
|
+
return depthToPointCloudBuffer(depthArray, width, height, fx, fy, cx, cy);
|
|
808
|
+
}
|
|
809
|
+
const device = await adapter.requestDevice();
|
|
810
|
+
const queue = device.queue;
|
|
811
|
+
const scale = 1.0;
|
|
812
|
+
const numPixels = width * height;
|
|
813
|
+
const outputSize = numPixels * 16;
|
|
814
|
+
const depthData32 = new Uint32Array(depthArray);
|
|
815
|
+
const intrinsics = new Float32Array([fx, fy, cx, cy, scale, width, height]);
|
|
816
|
+
const depthBuffer = device.createBuffer({
|
|
817
|
+
size: depthData32.byteLength,
|
|
818
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
819
|
+
});
|
|
820
|
+
const intrinsicsBuffer = device.createBuffer({
|
|
821
|
+
size: intrinsics.byteLength,
|
|
822
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
823
|
+
});
|
|
824
|
+
const xyzColorBuffer = device.createBuffer({
|
|
825
|
+
size: outputSize,
|
|
826
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
827
|
+
});
|
|
828
|
+
queue.writeBuffer(depthBuffer, 0, depthData32);
|
|
829
|
+
queue.writeBuffer(intrinsicsBuffer, 0, intrinsics);
|
|
830
|
+
const bindGroupLayout = device.createBindGroupLayout({
|
|
831
|
+
entries: [{
|
|
832
|
+
binding: 0,
|
|
833
|
+
visibility: GPUShaderStage.COMPUTE,
|
|
834
|
+
buffer: {
|
|
835
|
+
type: "read-only-storage"
|
|
836
|
+
}
|
|
837
|
+
}, {
|
|
838
|
+
binding: 1,
|
|
839
|
+
visibility: GPUShaderStage.COMPUTE,
|
|
840
|
+
buffer: {
|
|
841
|
+
type: "read-only-storage"
|
|
842
|
+
}
|
|
843
|
+
}, {
|
|
844
|
+
binding: 2,
|
|
845
|
+
visibility: GPUShaderStage.COMPUTE,
|
|
846
|
+
buffer: {
|
|
847
|
+
type: "storage"
|
|
848
|
+
}
|
|
849
|
+
}]
|
|
850
|
+
});
|
|
851
|
+
const bindGroup = device.createBindGroup({
|
|
852
|
+
layout: bindGroupLayout,
|
|
853
|
+
entries: [{
|
|
854
|
+
binding: 0,
|
|
855
|
+
resource: {
|
|
856
|
+
buffer: depthBuffer
|
|
857
|
+
}
|
|
858
|
+
}, {
|
|
859
|
+
binding: 1,
|
|
860
|
+
resource: {
|
|
861
|
+
buffer: intrinsicsBuffer
|
|
862
|
+
}
|
|
863
|
+
}, {
|
|
864
|
+
binding: 2,
|
|
865
|
+
resource: {
|
|
866
|
+
buffer: xyzColorBuffer
|
|
867
|
+
}
|
|
868
|
+
}]
|
|
869
|
+
});
|
|
870
|
+
const shaderModule = device.createShaderModule({
|
|
871
|
+
code: shader
|
|
872
|
+
});
|
|
873
|
+
const pipeline = device.createComputePipeline({
|
|
874
|
+
layout: device.createPipelineLayout({
|
|
875
|
+
bindGroupLayouts: [bindGroupLayout]
|
|
876
|
+
}),
|
|
877
|
+
compute: {
|
|
878
|
+
module: shaderModule,
|
|
879
|
+
entryPoint: "main"
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
const commandEncoder = device.createCommandEncoder();
|
|
883
|
+
const passEncoder = commandEncoder.beginComputePass();
|
|
884
|
+
passEncoder.setPipeline(pipeline);
|
|
885
|
+
passEncoder.setBindGroup(0, bindGroup);
|
|
886
|
+
passEncoder.dispatchWorkgroups(Math.ceil(numPixels / 256));
|
|
887
|
+
passEncoder.end();
|
|
888
|
+
device.queue.submit([commandEncoder.finish()]);
|
|
889
|
+
const outputBuffer = device.createBuffer({
|
|
890
|
+
size: xyzColorBuffer.size,
|
|
891
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
892
|
+
});
|
|
893
|
+
const copyEncoder = device.createCommandEncoder();
|
|
894
|
+
copyEncoder.copyBufferToBuffer(xyzColorBuffer, 0, outputBuffer, 0, xyzColorBuffer.size);
|
|
895
|
+
device.queue.submit([copyEncoder.finish()]);
|
|
896
|
+
|
|
897
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
898
|
+
await outputBuffer.mapAsync(GPUMapMode.READ);
|
|
899
|
+
const mappedRange = outputBuffer.getMappedRange();
|
|
900
|
+
const result = new Uint8Array(mappedRange.byteLength);
|
|
901
|
+
result.set(new Uint8Array(mappedRange));
|
|
902
|
+
outputBuffer.unmap();
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
function depthToPointCloudBuffer(uint16Array, width, height, fx, fy, cx, cy) {
|
|
906
|
+
const depthData = Array.from({
|
|
907
|
+
length: height
|
|
908
|
+
}, () => new Array(width));
|
|
909
|
+
for (let v = 0; v < height; v++) {
|
|
910
|
+
depthData[v] = depthData[v] ?? [];
|
|
911
|
+
for (let u = 0; u < width; u++) {
|
|
912
|
+
const d = uint16Array[v * width + u] ?? -1;
|
|
913
|
+
depthData[v][u] = d > 0 ? d : -1;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
const points = [];
|
|
917
|
+
// Accumulate the x, y, z values for each pixel.
|
|
918
|
+
for (let v = 0; v < height; v++) {
|
|
919
|
+
const row = depthData[v];
|
|
920
|
+
if (!row) {
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
for (let u = 0; u < width; u++) {
|
|
924
|
+
const z = row[u] ?? 0;
|
|
925
|
+
const x = (cx - u) * z / fx;
|
|
926
|
+
const y = (cy - v) * z / fy;
|
|
927
|
+
points.push(x, y, z);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
const pointCount = points.length / 3;
|
|
931
|
+
const buffer = new ArrayBuffer(pointCount * 16);
|
|
932
|
+
const view = new DataView(buffer);
|
|
933
|
+
for (let i = 0; i < pointCount; i++) {
|
|
934
|
+
const offset = i * 16;
|
|
935
|
+
view.setFloat32(offset, points[i * 3] ?? 0, true); //X
|
|
936
|
+
view.setFloat32(offset + 4, points[i * 3 + 1] ?? 0, true); //Y
|
|
937
|
+
view.setFloat32(offset + 8, points[i * 3 + 2] ?? 0, true); //Z
|
|
938
|
+
view.setUint8(offset + 12, 0); // R
|
|
939
|
+
view.setUint8(offset + 13, 0); // G
|
|
940
|
+
view.setUint8(offset + 14, 0); // B
|
|
941
|
+
view.setUint8(offset + 15, 255); // A
|
|
942
|
+
}
|
|
943
|
+
return new Uint8Array(buffer);
|
|
944
|
+
}
|
|
945
|
+
async function deserializeDepthFrame({
|
|
946
|
+
topic,
|
|
947
|
+
message,
|
|
948
|
+
callback
|
|
949
|
+
}) {
|
|
950
|
+
const {
|
|
951
|
+
receiveTime,
|
|
952
|
+
width,
|
|
953
|
+
height
|
|
954
|
+
} = parseMessage(message);
|
|
955
|
+
const neuralCameraIntrinsics = JSON.parse(localStorage.getItem("neuralCameraIntrinsics") ?? "{}");
|
|
956
|
+
const uint16Array = uint8ArrayToUint16Array(message.data);
|
|
957
|
+
const fx = neuralCameraIntrinsics.right.focalLenght.x;
|
|
958
|
+
const fy = neuralCameraIntrinsics.right.focalLenght.y;
|
|
959
|
+
const cx = neuralCameraIntrinsics.right.principalPoint.x;
|
|
960
|
+
const cy = neuralCameraIntrinsics.right.principalPoint.y;
|
|
961
|
+
const pointCloudBufferGPU = depthToPointcloudGPU(uint16Array, width, height, fx, fy, cx, cy);
|
|
962
|
+
const foxgloveMessage = {
|
|
963
|
+
timestamp: receiveTime,
|
|
964
|
+
frame_id: `pointcloud-${topic}-frame`,
|
|
965
|
+
point_stride: 16,
|
|
966
|
+
pose: {
|
|
967
|
+
position: {
|
|
968
|
+
x: 0,
|
|
969
|
+
y: 0,
|
|
970
|
+
z: 0
|
|
971
|
+
},
|
|
972
|
+
orientation: {
|
|
973
|
+
x: 0,
|
|
974
|
+
y: 0,
|
|
975
|
+
z: 1,
|
|
976
|
+
w: 0
|
|
977
|
+
}
|
|
978
|
+
},
|
|
979
|
+
width,
|
|
980
|
+
height,
|
|
981
|
+
fields: [{
|
|
982
|
+
name: "x",
|
|
983
|
+
offset: 0,
|
|
984
|
+
type: typescript.NumericType.FLOAT32
|
|
985
|
+
}, {
|
|
986
|
+
name: "y",
|
|
987
|
+
offset: 4,
|
|
988
|
+
type: typescript.NumericType.FLOAT32
|
|
989
|
+
}, {
|
|
990
|
+
name: "z",
|
|
991
|
+
offset: 8,
|
|
992
|
+
type: typescript.NumericType.FLOAT32
|
|
993
|
+
}, {
|
|
994
|
+
name: "red",
|
|
995
|
+
offset: 12,
|
|
996
|
+
type: typescript.NumericType.UINT8
|
|
997
|
+
}, {
|
|
998
|
+
name: "green",
|
|
999
|
+
offset: 13,
|
|
1000
|
+
type: typescript.NumericType.UINT8
|
|
1001
|
+
}, {
|
|
1002
|
+
name: "blue",
|
|
1003
|
+
offset: 14,
|
|
1004
|
+
type: typescript.NumericType.UINT8
|
|
1005
|
+
}, {
|
|
1006
|
+
name: "alpha",
|
|
1007
|
+
offset: 15,
|
|
1008
|
+
type: typescript.NumericType.UINT8
|
|
1009
|
+
}],
|
|
1010
|
+
data: await pointCloudBufferGPU
|
|
1011
|
+
};
|
|
1012
|
+
callback({
|
|
1013
|
+
topic,
|
|
1014
|
+
receiveTime,
|
|
1015
|
+
message: foxgloveMessage,
|
|
1016
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
1017
|
+
schemaName: "foxglove.PointCloud"
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
1022
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
1023
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
1024
|
+
|
|
1025
|
+
function ensureWebCodecsSupported(target) {
|
|
1026
|
+
const supported = typeof target !== "undefined";
|
|
1027
|
+
if (!supported) {
|
|
1028
|
+
const isProtocolSupported = window.location.protocol === "https:" || window.location.protocol === "file:";
|
|
1029
|
+
const isLocalHostname = window.location.hostname === "127.0.0.1" || window.location.hostname === "localhost";
|
|
1030
|
+
const reason = isProtocolSupported || isLocalHostname ? "Unsupported browser" : `${target} only supports \`https\` or \`localhost\` or \`127.0.0.1\``;
|
|
1031
|
+
console.error(`${target} is not available. Reason: ${reason}`);
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
1038
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
1039
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
1040
|
+
|
|
1041
|
+
function createVideoDecoder({
|
|
1042
|
+
topic,
|
|
1043
|
+
callback,
|
|
1044
|
+
topicDecoders
|
|
1045
|
+
}) {
|
|
1046
|
+
return new VideoDecoder({
|
|
1047
|
+
output: async frame => {
|
|
1048
|
+
const buffer = new Uint8Array(frame.allocationSize());
|
|
1049
|
+
await frame.copyTo(buffer);
|
|
1050
|
+
const receiveTime = topicDecoders.get(topic)?.timing.get(frame.timestamp) ?? dist.fromMicros(frame.timestamp);
|
|
1051
|
+
const [encoding, step] = parsePixelFormat(frame.format);
|
|
1052
|
+
const foxgloveMessage = {
|
|
1053
|
+
timestamp: receiveTime,
|
|
1054
|
+
frame_id: `h264-${topic}-frame`,
|
|
1055
|
+
width: frame.displayWidth,
|
|
1056
|
+
height: frame.displayHeight,
|
|
1057
|
+
data: buffer,
|
|
1058
|
+
encoding,
|
|
1059
|
+
step: frame.displayWidth * step
|
|
1060
|
+
};
|
|
1061
|
+
callback({
|
|
1062
|
+
topic,
|
|
1063
|
+
receiveTime,
|
|
1064
|
+
message: foxgloveMessage,
|
|
1065
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
1066
|
+
schemaName: "foxglove.RawImage"
|
|
1067
|
+
});
|
|
1068
|
+
frame.close();
|
|
1069
|
+
},
|
|
1070
|
+
error: console.error
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
async function deserializeEncodedFrameH264({
|
|
1074
|
+
topic,
|
|
1075
|
+
message,
|
|
1076
|
+
topicDecoders,
|
|
1077
|
+
callback
|
|
1078
|
+
}) {
|
|
1079
|
+
const {
|
|
1080
|
+
receiveTime
|
|
1081
|
+
} = parseMessage(message);
|
|
1082
|
+
const supported = ensureWebCodecsSupported("VideoDecoder");
|
|
1083
|
+
if (!supported) {
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
if (!topicDecoders.has(topic)) {
|
|
1087
|
+
const decoder = createVideoDecoder({
|
|
1088
|
+
topic,
|
|
1089
|
+
callback,
|
|
1090
|
+
topicDecoders
|
|
1091
|
+
});
|
|
1092
|
+
decoder.configure({
|
|
1093
|
+
codec: "avc1.42001E",
|
|
1094
|
+
optimizeForLatency: true
|
|
1095
|
+
});
|
|
1096
|
+
topicDecoders.set(topic, {
|
|
1097
|
+
decoder,
|
|
1098
|
+
timing: new Map()
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
const decoderInfo = topicDecoders.get(topic);
|
|
1102
|
+
if (!decoderInfo) {
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
if (decoderInfo.decoder.decodeQueueSize > 60) {
|
|
1106
|
+
decoderInfo.decoder.reset();
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
const microTimestamp = receiveTime.sec * 1_000_000 + Math.floor(receiveTime.nsec / 1_000);
|
|
1110
|
+
decoderInfo.timing.set(microTimestamp, receiveTime);
|
|
1111
|
+
const frame = {
|
|
1112
|
+
type: 'key',
|
|
1113
|
+
data: message.data,
|
|
1114
|
+
timestamp: microTimestamp
|
|
1115
|
+
};
|
|
1116
|
+
try {
|
|
1117
|
+
const chunk = new EncodedVideoChunk(frame);
|
|
1118
|
+
decoderInfo.decoder.decode(chunk);
|
|
1119
|
+
} catch {
|
|
1120
|
+
topicDecoders.delete(topic);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
1125
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
1126
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
1127
|
+
|
|
1128
|
+
async function deserializeMJPEGFrame({
|
|
1129
|
+
topic,
|
|
1130
|
+
message,
|
|
1131
|
+
callback
|
|
1132
|
+
}) {
|
|
1133
|
+
const {
|
|
1134
|
+
receiveTime
|
|
1135
|
+
} = parseMessage(message);
|
|
1136
|
+
const supported = ensureWebCodecsSupported("ImageDecoder");
|
|
1137
|
+
if (!supported) {
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
const decoder = new ImageDecoder({
|
|
1141
|
+
type: "image/jpeg",
|
|
1142
|
+
data: message.data
|
|
1143
|
+
});
|
|
1144
|
+
const {
|
|
1145
|
+
image: frame
|
|
1146
|
+
} = await decoder.decode();
|
|
1147
|
+
const buffer = new Uint8Array(frame.allocationSize());
|
|
1148
|
+
await frame.copyTo(buffer);
|
|
1149
|
+
const [encoding, step] = parsePixelFormat(frame.format);
|
|
1150
|
+
const foxgloveMessage = {
|
|
1151
|
+
timestamp: receiveTime,
|
|
1152
|
+
frame_id: "camera",
|
|
1153
|
+
width: frame.displayWidth,
|
|
1154
|
+
height: frame.displayHeight,
|
|
1155
|
+
data: buffer,
|
|
1156
|
+
encoding,
|
|
1157
|
+
step: frame.displayWidth * step
|
|
1158
|
+
};
|
|
1159
|
+
frame.close();
|
|
1160
|
+
callback({
|
|
1161
|
+
topic,
|
|
1162
|
+
receiveTime,
|
|
1163
|
+
message: foxgloveMessage,
|
|
1164
|
+
sizeInBytes: estimateObjectSize(foxgloveMessage),
|
|
1165
|
+
schemaName: "foxglove.RawImage"
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
1170
|
+
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
1171
|
+
// file, You can obtain one at http://mozilla.org/MPL/2.0/
|
|
1172
|
+
const topicDecoders = new Map();
|
|
1173
|
+
const topicSizes = new Map();
|
|
1174
|
+
let callback;
|
|
1175
|
+
function initCallback(cb) {
|
|
1176
|
+
callback = cb;
|
|
1177
|
+
}
|
|
1178
|
+
function handleMessageToDecode({
|
|
1179
|
+
schema,
|
|
1180
|
+
buffer,
|
|
1181
|
+
topic
|
|
1182
|
+
}) {
|
|
1183
|
+
const protobufSchema = protobufsBySchema[schema];
|
|
1184
|
+
if (!protobufSchema) {
|
|
1185
|
+
console.warn(`Unsupported message schema "${schema}"`);
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
const bufferArray = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
1189
|
+
const message = protobufSchema.decoder.decode(bufferArray);
|
|
1190
|
+
void deserializeDepthAiMessage({
|
|
1191
|
+
topic,
|
|
1192
|
+
topicSizes,
|
|
1193
|
+
topicDecoders,
|
|
1194
|
+
message,
|
|
1195
|
+
callback,
|
|
1196
|
+
type: protobufSchema.type
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
async function deserializeDepthAiMessage(args) {
|
|
1200
|
+
const {
|
|
1201
|
+
topicDecoders,
|
|
1202
|
+
topicSizes,
|
|
1203
|
+
type,
|
|
1204
|
+
message,
|
|
1205
|
+
callback,
|
|
1206
|
+
topic
|
|
1207
|
+
} = args;
|
|
1208
|
+
switch (type) {
|
|
1209
|
+
case "encodedFrame":
|
|
1210
|
+
{
|
|
1211
|
+
topicSizes.set(topic, {
|
|
1212
|
+
width: message.width,
|
|
1213
|
+
height: message.height
|
|
1214
|
+
});
|
|
1215
|
+
if (message.profile === Profile.AVC) {
|
|
1216
|
+
await deserializeEncodedFrameH264({
|
|
1217
|
+
topic,
|
|
1218
|
+
message,
|
|
1219
|
+
topicDecoders,
|
|
1220
|
+
callback
|
|
1221
|
+
});
|
|
1222
|
+
} else if (message.profile === Profile.JPEG) {
|
|
1223
|
+
await deserializeMJPEGFrame({
|
|
1224
|
+
topic,
|
|
1225
|
+
message,
|
|
1226
|
+
callback
|
|
1227
|
+
});
|
|
1228
|
+
} else ;
|
|
1229
|
+
break;
|
|
1230
|
+
}
|
|
1231
|
+
case "imageFrame":
|
|
1232
|
+
{
|
|
1233
|
+
const {
|
|
1234
|
+
width,
|
|
1235
|
+
height,
|
|
1236
|
+
type: messageType
|
|
1237
|
+
} = parseMessage(message);
|
|
1238
|
+
topicSizes.set(topic, {
|
|
1239
|
+
width,
|
|
1240
|
+
height
|
|
1241
|
+
});
|
|
1242
|
+
switch (messageType) {
|
|
1243
|
+
case Type.BITSTREAM:
|
|
1244
|
+
{
|
|
1245
|
+
await deserializeEncodedFrameH264({
|
|
1246
|
+
topic,
|
|
1247
|
+
message,
|
|
1248
|
+
topicDecoders,
|
|
1249
|
+
callback
|
|
1250
|
+
});
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
case Type.RAW16:
|
|
1254
|
+
{
|
|
1255
|
+
await deserializeDepthFrame({
|
|
1256
|
+
topic,
|
|
1257
|
+
message,
|
|
1258
|
+
callback
|
|
1259
|
+
});
|
|
1260
|
+
break;
|
|
1261
|
+
}
|
|
1262
|
+
default:
|
|
1263
|
+
{
|
|
1264
|
+
deserializeColorFrame({
|
|
1265
|
+
topic,
|
|
1266
|
+
message,
|
|
1267
|
+
callback
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
break;
|
|
1272
|
+
}
|
|
1273
|
+
case "imageDetections":
|
|
1274
|
+
{
|
|
1275
|
+
deserializeImgDetections({
|
|
1276
|
+
topic,
|
|
1277
|
+
message,
|
|
1278
|
+
callback,
|
|
1279
|
+
topicSizes
|
|
1280
|
+
});
|
|
1281
|
+
break;
|
|
1282
|
+
}
|
|
1283
|
+
case "imageDetectionsCustom":
|
|
1284
|
+
{
|
|
1285
|
+
deserializeImgDetectionsCustom({
|
|
1286
|
+
topic,
|
|
1287
|
+
message,
|
|
1288
|
+
callback,
|
|
1289
|
+
topicSizes
|
|
1290
|
+
});
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1293
|
+
case "imageDetectionsSpatial":
|
|
1294
|
+
{
|
|
1295
|
+
// TODO: Use separate 3D detection deserializer
|
|
1296
|
+
deserializeImgDetections({
|
|
1297
|
+
topic,
|
|
1298
|
+
topicSizes,
|
|
1299
|
+
message: {
|
|
1300
|
+
...message,
|
|
1301
|
+
detections: message.detections.map(detections => detections.detection)
|
|
1302
|
+
},
|
|
1303
|
+
callback
|
|
1304
|
+
});
|
|
1305
|
+
break;
|
|
1306
|
+
}
|
|
1307
|
+
case "pointCloud":
|
|
1308
|
+
{
|
|
1309
|
+
deserializePointCloudData({
|
|
1310
|
+
topic,
|
|
1311
|
+
message,
|
|
1312
|
+
callback
|
|
1313
|
+
});
|
|
1314
|
+
break;
|
|
1315
|
+
}
|
|
1316
|
+
default:
|
|
1317
|
+
{
|
|
1318
|
+
console.warn(`Message decoding failed: unsupported type "${type}"`);
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
expose({
|
|
1324
|
+
initCallback,
|
|
1325
|
+
handleMessageToDecode
|
|
1326
|
+
});
|