@luxonis/visualizer-protobuf 2.25.0 → 2.27.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.
Files changed (73) hide show
  1. package/dist/{index-D3DkLyZA.js → index-B1pNpslP.js} +1 -1
  2. package/dist/{index-Yd8mYo4X.js → index-B4d7dS8a.js} +1 -1
  3. package/dist/{index-DWrX4gRf.js → index-B5_Aa-W3.js} +1 -1
  4. package/dist/{index-DFjClLW-.js → index-BNXdmaeO.js} +1 -1
  5. package/dist/{index-BlPNVFW_.js → index-BZ8z044k.js} +1 -1
  6. package/dist/{index-CpNfgd1w.js → index-BuRQ7ljn.js} +255 -143
  7. package/dist/{index-9gGX6Zvk.js → index-CGXxFWjz.js} +1 -1
  8. package/dist/{index-3GQM86WK.js → index-CIHmVsn2.js} +1 -1
  9. package/dist/{index-C4kNkDQc.js → index-CJSOG1CX.js} +2 -2
  10. package/dist/{index-BshEtuHO.js → index-CLPc3bUH.js} +1 -1
  11. package/dist/{index-DuCWx5b9.js → index-CXdNn-IZ.js} +1 -1
  12. package/dist/{index-CWe6_z0e.js → index-CdXrBVPC.js} +177 -36
  13. package/dist/{index-2PbGVouo.js → index-DE0_tKGA.js} +1 -1
  14. package/dist/{index-DeEImmkI.js → index-DZgY6A3h.js} +1 -1
  15. package/dist/{index-XeyUYY6F.js → index-DbT8vr6l.js} +1 -1
  16. package/dist/{index-F42wp6uI.js → index-DsO3GPWF.js} +1 -1
  17. package/dist/{index-BhITngB2.js → index-I0XgHBlj.js} +1 -1
  18. package/dist/{index-CHN-su-T.js → index-LmBY2nOo.js} +1 -1
  19. package/dist/{index-jxrL_e5O.js → index-pwNtzQuf.js} +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/lib/src/components/Panel.d.ts +2 -1
  22. package/dist/lib/src/components/Panel.d.ts.map +1 -1
  23. package/dist/lib/src/components/Panel.js +8 -8
  24. package/dist/lib/src/components/Panel.js.map +1 -1
  25. package/dist/lib/src/components/PanelToolbar.d.ts +1 -0
  26. package/dist/lib/src/components/PanelToolbar.d.ts.map +1 -1
  27. package/dist/lib/src/components/PanelToolbar.js +9 -4
  28. package/dist/lib/src/components/PanelToolbar.js.map +1 -1
  29. package/dist/lib/src/index.d.ts +1 -0
  30. package/dist/lib/src/index.d.ts.map +1 -1
  31. package/dist/lib/src/index.js +1 -0
  32. package/dist/lib/src/index.js.map +1 -1
  33. package/dist/lib/src/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts +4 -4
  34. package/dist/lib/src/messaging/deserialization/pointcloud/poitcloudPoolManager.d.ts.map +1 -1
  35. package/dist/lib/src/messaging/deserialization/pointcloud/poitcloudPoolManager.js +144 -45
  36. package/dist/lib/src/messaging/deserialization/pointcloud/poitcloudPoolManager.js.map +1 -1
  37. package/dist/lib/src/panels/ImagePanel.d.ts +1 -0
  38. package/dist/lib/src/panels/ImagePanel.d.ts.map +1 -1
  39. package/dist/lib/src/panels/ImagePanel.js +7 -3
  40. package/dist/lib/src/panels/ImagePanel.js.map +1 -1
  41. package/dist/lib/src/panels/PointCloudPanel.js +1 -1
  42. package/dist/lib/src/utils/metrics-manager.d.ts.map +1 -1
  43. package/dist/lib/src/utils/metrics-manager.js +6 -2
  44. package/dist/lib/src/utils/metrics-manager.js.map +1 -1
  45. package/dist/lib/src/utils/poitcloud-sync.js +1 -1
  46. package/dist/lib/src/utils/poitcloud-sync.js.map +1 -1
  47. package/dist/packages/studio-base/src/panels/ThreeDeeRender/IRenderer.d.ts +2 -0
  48. package/dist/packages/studio-base/src/panels/ThreeDeeRender/IRenderer.d.ts.map +1 -1
  49. package/dist/packages/studio-base/src/panels/ThreeDeeRender/IRenderer.js.map +1 -1
  50. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.d.ts +1 -0
  51. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.d.ts.map +1 -1
  52. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js +3 -0
  53. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js.map +1 -1
  54. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts +1 -0
  55. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts.map +1 -1
  56. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js +4 -3
  57. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js.map +1 -1
  58. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.d.ts +1 -0
  59. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.d.ts.map +1 -1
  60. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.js +5 -3
  61. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.js.map +1 -1
  62. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/CameraStateSettings.d.ts.map +1 -1
  63. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/CameraStateSettings.js +2 -1
  64. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/CameraStateSettings.js.map +1 -1
  65. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.d.ts +1 -0
  66. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.d.ts.map +1 -1
  67. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.js +4 -0
  68. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/ImageMode.js.map +1 -1
  69. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/MessageHandler.d.ts +6 -2
  70. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/MessageHandler.d.ts.map +1 -1
  71. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/MessageHandler.js +141 -25
  72. package/dist/packages/studio-base/src/panels/ThreeDeeRender/renderables/ImageMode/MessageHandler.js.map +1 -1
  73. package/package.json +1 -1
@@ -447,42 +447,139 @@ class Condvar {
447
447
  // This Source Code Form is subject to the terms of the Mozilla Public
448
448
  // License, v2.0. If a copy of the MPL was not distributed with this
449
449
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
450
+
451
+ const MAX_SAMPLE_SIZE = 100;
452
+ function bytesToMegabits(bytes) {
453
+ return bytes / (1024 * 1024) * 8;
454
+ }
455
+ class EventMetricsManager {
456
+ metrics = {};
457
+ registerEvent(topic) {
458
+ const currentTime = performance.now();
459
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
460
+ this.metrics[topic] ??= [];
461
+ this.metrics[topic].unshift(currentTime);
462
+ if (this.metrics[topic].length > MAX_SAMPLE_SIZE) {
463
+ this.metrics[topic].length = MAX_SAMPLE_SIZE;
464
+ }
465
+ }
466
+ calculate(topic) {
467
+ const topicMetrics = this.metrics[topic];
468
+ if (!topicMetrics) {
469
+ return 0;
470
+ }
471
+ let totalInterval = 0;
472
+ for (let i = 1; i < topicMetrics.length; ++i) {
473
+ totalInterval += topicMetrics[i - 1] - topicMetrics[i];
474
+ }
475
+ if (isNaN(totalInterval)) {
476
+ return 0;
477
+ }
478
+ const fps = 1_000 / (totalInterval / (topicMetrics.length - 1));
479
+ return Math.round(fps);
480
+ }
481
+ }
482
+ class ThroughputMetricsManager {
483
+ metrics = {};
484
+ registerEvent(topic, value) {
485
+ const timestamp = performance.now();
486
+ this.metrics[topic] ??= [];
487
+ this.metrics[topic].unshift({
488
+ timestamp,
489
+ value
490
+ });
491
+ if (this.metrics[topic].length > MAX_SAMPLE_SIZE) {
492
+ this.metrics[topic].length = MAX_SAMPLE_SIZE;
493
+ }
494
+ }
495
+ calculate(topic) {
496
+ const topicMetrics = this.metrics[topic];
497
+ if (!topicMetrics || topicMetrics.length < 2 || !topicMetrics.at(0) || !topicMetrics.at(-1)) {
498
+ return 0;
499
+ }
500
+
501
+ // Get time span in seconds
502
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
503
+ const timeSpanMs = topicMetrics.at(0).timestamp - topicMetrics.at(-1).timestamp;
504
+ const timeSpanSec = timeSpanMs / 1000;
505
+ if (timeSpanSec === 0) {
506
+ return 0;
507
+ }
508
+
509
+ // Sum up all values (bytes)
510
+ const totalBytes = topicMetrics.reduce((sum, metric) => sum + metric.value, 0);
511
+
512
+ // Calculate bytes per second
513
+ const bytesPerSecond = totalBytes / timeSpanSec;
514
+
515
+ // Return rounded value
516
+ return Number(bytesToMegabits(bytesPerSecond).toFixed(2));
517
+ }
518
+ }
519
+
520
+ // This Source Code Form is subject to the terms of the Mozilla Public
521
+ // License, v2.0. If a copy of the MPL was not distributed with this
522
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/
523
+ /* eslint-disable @foxglove/strict-equality */
450
524
  const WORKER_COUNT = 4;
525
+ const DEFAULT_TARGET_FPS = 9;
526
+ const DEFAULT_MAX_PROCESSED_QUEUE_SIZE = 100;
451
527
  class DepthToPointcloudWorkerPool {
452
528
  lastUsedWorkerIndex = 0;
453
529
  #frameQueue = [];
530
+ #processedFrameQueue = [];
454
531
  #isWebGpuSupported = false;
532
+ #metrics;
455
533
  #FRAME_BATCH_SIZE;
534
+ #targetDispatchIntervalMs;
535
+ #maxProcessedQueueSize;
536
+ #dispatchCallback;
456
537
  #isProcessing = false;
457
- constructor(callback, batchSize = 10) {
538
+ #dispatchTimeoutId = undefined;
539
+ constructor(callback, batchSize = 10, targetFps = DEFAULT_TARGET_FPS, maxProcessedQueueSize = DEFAULT_MAX_PROCESSED_QUEUE_SIZE) {
458
540
  if (typeof navigator.gpu !== "undefined") {
459
541
  void navigator.gpu.requestAdapter().then(gpuAdapter => {
460
542
  if (!gpuAdapter) {
461
543
  this.#isWebGpuSupported = false;
462
- console.warn("WebGPU not supported. Falling back to CPU for all frames.");
463
- return;
544
+ console.warn("WebGPU adapter not found. Falling back to CPU for all frames.");
545
+ } else {
546
+ this.#isWebGpuSupported = true;
547
+ console.info("WebGPU potentially supported. Will attempt GPU processing.");
464
548
  }
465
- this.#isWebGpuSupported = true;
549
+ }).catch(err => {
550
+ console.warn("Error requesting WebGPU adapter. Falling back to CPU.", err);
551
+ this.#isWebGpuSupported = false;
466
552
  });
467
553
  } else {
468
- console.warn("WebGPU not supported. Falling back to CPU for all frames.");
554
+ console.warn("navigator.gpu is undefined. WebGPU not supported. Falling back to CPU for all frames.");
555
+ this.#isWebGpuSupported = false;
469
556
  }
470
- this.sumbmitCallback = callback;
557
+ this.#dispatchCallback = callback;
471
558
  this.#FRAME_BATCH_SIZE = Math.max(1, batchSize);
559
+ this.#targetDispatchIntervalMs = 1000 / Math.max(1, targetFps);
560
+ this.#maxProcessedQueueSize = Math.max(1, maxProcessedQueueSize);
472
561
  this.workerApis = new Array(WORKER_COUNT).fill(undefined).map(() => wrap$3(new Worker(new URL("pointcloudFromDepth.worker-JVTJ-r5q.js", import.meta.url), {
473
562
  type: "module"
474
563
  })));
564
+ this.#metrics = new EventMetricsManager();
565
+ this.#metrics.registerEvent("pcl-pool.frameInput");
475
566
  }
476
567
  async queueDepthFrame(data) {
477
- // @ts-expect-error - ITS unknow
478
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
479
- if (!(data.colorFrame.message.data instanceof Uint8Array)) {
568
+ // @ts-expect-error
569
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
570
+ if (!(data.colorFrame.message?.data instanceof Uint8Array)) {
571
+ console.warn("Skipping frame: colorFrame.message.data is not a Uint8Array", data.colorFrame);
480
572
  return;
481
573
  }
482
574
  this.#frameQueue.push(data);
483
575
  this.tryProcessBatch();
484
576
  }
485
577
  tryProcessBatch() {
578
+ this.#metrics?.registerEvent("pcl-pool.batchSent");
579
+ const fps = this.#metrics?.calculate("pcl-pool.batchSent");
580
+ if (fps && fps > 0) {
581
+ this.#targetDispatchIntervalMs = 1000 / Math.max(4, fps);
582
+ }
486
583
  if (this.#isProcessing || this.#frameQueue.length < this.#FRAME_BATCH_SIZE) {
487
584
  return;
488
585
  }
@@ -492,6 +589,7 @@ class DepthToPointcloudWorkerPool {
492
589
  this.#isProcessing = false;
493
590
  return;
494
591
  }
592
+
495
593
  // biome-ignore lint/style/noNonNullAssertion: <explanation>
496
594
  const firstFrame = batchToProcess[0];
497
595
  const width = firstFrame.width;
@@ -502,47 +600,115 @@ class DepthToPointcloudWorkerPool {
502
600
  const cy = firstFrame.cy;
503
601
  const i420Width = firstFrame.i420Width;
504
602
  const i420Height = firstFrame.i420Height;
505
- const depthDataArray = batchToProcess.map(f => uint8ArrayToUint16Array(f.depthFrame.data));
506
- const timestampsArray = batchToProcess.map(f => f.colorFrame.receiveTime.nsec);
507
- // @ts-expect-error - ITS unknow
508
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
509
- const i420DataArray = batchToProcess.map(f => f.colorFrame.message.data);
510
- const workerIndex = this.lastUsedWorkerIndex;
511
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
512
- const workerApi = this.workerApis[workerIndex];
513
- this.lastUsedWorkerIndex = (this.lastUsedWorkerIndex + 1) % WORKER_COUNT;
514
- workerApi.depthToPointcloudGPU(depthDataArray, width, height, fx, fy, cx, cy, i420DataArray, i420Width, i420Height, {
515
- hasGPU: this.#isWebGpuSupported
516
- }).then(results => {
517
- if (results.length === batchToProcess.length) {
518
- const firtFrame = batchToProcess[0];
519
- if (!firtFrame) {
520
- return;
521
- }
522
- for (let i = 0; i < results.length; i++) {
523
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
524
- const originalFrame = batchToProcess[i];
525
- const pointCloudResult = results[i];
526
- if (!pointCloudResult) {
527
- console.error(`Worker ${workerIndex}: Result ${i} is null!`);
528
- continue;
603
+ try {
604
+ const depthDataArray = batchToProcess.map(f => uint8ArrayToUint16Array(f.depthFrame.data));
605
+ // @ts-expect-error
606
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
607
+ const i420DataArray = batchToProcess.map(f => f.colorFrame.message.data);
608
+ const workerIndex = this.lastUsedWorkerIndex;
609
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
610
+ const workerApi = this.workerApis[workerIndex];
611
+ this.lastUsedWorkerIndex = (this.lastUsedWorkerIndex + 1) % WORKER_COUNT;
612
+ workerApi.depthToPointcloudGPU(depthDataArray, width, height, fx, fy, cx, cy, i420DataArray, i420Width, i420Height, {
613
+ hasGPU: this.#isWebGpuSupported
614
+ }).then(results => {
615
+ if (results.length === batchToProcess.length) {
616
+ for (let i = 0; i < results.length; i++) {
617
+ // biome-ignore lint/style/noNonNullAssertion: <explanation>
618
+ const originalFrame = batchToProcess[i];
619
+ const pointCloudResult = results[i];
620
+ if (!pointCloudResult) {
621
+ console.warn(`Worker ${workerIndex}: Result ${i} is null or undefined. Passing null to callback.`);
622
+ this.#addToProcessedQueue({
623
+ originalColorEvent: originalFrame.colorFrame,
624
+ originalDepthFrame: originalFrame.depthFrame,
625
+ processedPointCloud: null
626
+ });
627
+ } else {
628
+ this.#addToProcessedQueue({
629
+ originalColorEvent: originalFrame.colorFrame,
630
+ originalDepthFrame: originalFrame.depthFrame,
631
+ processedPointCloud: pointCloudResult
632
+ });
633
+ }
634
+ }
635
+ } else {
636
+ console.error(`Worker ${workerIndex}: Mismatch in result count (${results.length}) and batch size (${batchToProcess.length}). Discarding results for this batch.`);
637
+ for (const originalFrame of batchToProcess) {
638
+ this.#addToProcessedQueue({
639
+ originalColorEvent: originalFrame.colorFrame,
640
+ originalDepthFrame: originalFrame.depthFrame,
641
+ processedPointCloud: null
642
+ });
529
643
  }
530
- // biome-ignore lint/style/noNonNullAssertion: Workaround
531
- const delay = Math.min(500, Math.abs((firstFrame.colorFrame.receiveTime.nsec - timestampsArray[i]) / 10 ** 6));
532
- setTimeout(() => {
533
- this.sumbmitCallback(originalFrame.colorFrame, originalFrame.depthFrame, pointCloudResult);
534
- }, delay);
535
644
  }
536
- }
537
- }).catch(error => {
538
- console.error(`Worker ${workerIndex}: Error processing batch:`, error);
645
+ }).catch(error => {
646
+ console.error(`Worker ${workerIndex}: Error processing batch:`, error);
647
+ for (const originalFrame of batchToProcess) {
648
+ this.#addToProcessedQueue({
649
+ originalColorEvent: originalFrame.colorFrame,
650
+ originalDepthFrame: originalFrame.depthFrame,
651
+ processedPointCloud: null
652
+ });
653
+ }
654
+ }).finally(() => {
655
+ this.#isProcessing = false;
656
+ this.tryProcessBatch();
657
+ });
658
+ } catch (error) {
659
+ console.error("Error preparing data for worker:", error);
539
660
  for (const originalFrame of batchToProcess) {
540
- this.sumbmitCallback(originalFrame.colorFrame, originalFrame.depthFrame, null);
661
+ this.#addToProcessedQueue({
662
+ originalColorEvent: originalFrame.colorFrame,
663
+ originalDepthFrame: originalFrame.depthFrame,
664
+ processedPointCloud: null
665
+ });
541
666
  }
542
- }).finally(() => {
543
667
  this.#isProcessing = false;
544
668
  this.tryProcessBatch();
545
- });
669
+ }
670
+ }
671
+ #addToProcessedQueue(processedFrame) {
672
+ if (this.#processedFrameQueue.length >= this.#maxProcessedQueueSize) {
673
+ this.#processedFrameQueue.shift();
674
+ console.warn(`Processed frame queue full (>= ${this.#maxProcessedQueueSize}). Dropping oldest frame.`);
675
+ }
676
+ this.#processedFrameQueue.push(processedFrame);
677
+ if (this.#dispatchTimeoutId === undefined) {
678
+ this.#scheduleNextDispatch();
679
+ }
680
+ }
681
+ #scheduleNextDispatch() {
682
+ if (this.#dispatchTimeoutId !== undefined) {
683
+ clearTimeout(this.#dispatchTimeoutId);
684
+ }
685
+ if (this.#processedFrameQueue.length > 0) {
686
+ this.#dispatchTimeoutId = setTimeout(this.#dispatchNextFrame, this.#targetDispatchIntervalMs);
687
+ } else {
688
+ this.#dispatchTimeoutId = undefined;
689
+ }
690
+ }
691
+ #dispatchNextFrame = () => {
692
+ const frameToDispatch = this.#processedFrameQueue.shift();
693
+ if (frameToDispatch) {
694
+ try {
695
+ this.#dispatchCallback(frameToDispatch.originalColorEvent, frameToDispatch.originalDepthFrame, frameToDispatch.processedPointCloud);
696
+ } catch (error) {
697
+ console.error("Error in dispatchCallback:", error);
698
+ }
699
+ } else {
700
+ console.warn("Dispatch timer fired but processed queue was empty.");
701
+ }
702
+ this.#scheduleNextDispatch();
703
+ };
704
+ destroy() {
705
+ if (this.#dispatchTimeoutId !== undefined) {
706
+ clearTimeout(this.#dispatchTimeoutId);
707
+ this.#dispatchTimeoutId = undefined;
708
+ }
709
+ this.#frameQueue = [];
710
+ this.#processedFrameQueue = [];
711
+ this.workerApis = [];
546
712
  }
547
713
  }
548
714
 
@@ -587,75 +753,6 @@ function createMessageHandler(callback) {
587
753
  // License, v2.0. If a copy of the MPL was not distributed with this
588
754
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
589
755
 
590
- const MAX_SAMPLE_SIZE = 100;
591
- function bytesToMegabits(bytes) {
592
- return bytes / (1024 * 1024) * 8;
593
- }
594
- class EventMetricsManager {
595
- metrics = {};
596
- registerEvent(topic) {
597
- const currentTime = performance.now();
598
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
599
- this.metrics[topic] ??= [];
600
- this.metrics[topic].unshift(currentTime);
601
- this.metrics[topic].length = MAX_SAMPLE_SIZE;
602
- }
603
- calculate(topic) {
604
- const topicMetrics = this.metrics[topic];
605
- if (!topicMetrics) {
606
- return 0;
607
- }
608
- let totalInterval = 0;
609
- for (let i = 1; i < topicMetrics.length; ++i) {
610
- totalInterval += topicMetrics[i - 1] - topicMetrics[i];
611
- }
612
- if (isNaN(totalInterval)) {
613
- return 0;
614
- }
615
- const fps = 1_000 / (totalInterval / (topicMetrics.length - 1));
616
- return Math.round(fps);
617
- }
618
- }
619
- class ThroughputMetricsManager {
620
- metrics = {};
621
- registerEvent(topic, value) {
622
- const timestamp = performance.now();
623
- this.metrics[topic] ??= [];
624
- this.metrics[topic].unshift({
625
- timestamp,
626
- value
627
- });
628
- this.metrics[topic].length = MAX_SAMPLE_SIZE;
629
- }
630
- calculate(topic) {
631
- const topicMetrics = this.metrics[topic];
632
- if (!topicMetrics || topicMetrics.length < 2 || !topicMetrics.at(0) || !topicMetrics.at(-1)) {
633
- return 0;
634
- }
635
-
636
- // Get time span in seconds
637
- // biome-ignore lint/style/noNonNullAssertion: <explanation>
638
- const timeSpanMs = topicMetrics.at(0).timestamp - topicMetrics.at(-1).timestamp;
639
- const timeSpanSec = timeSpanMs / 1000;
640
- if (timeSpanSec === 0) {
641
- return 0;
642
- }
643
-
644
- // Sum up all values (bytes)
645
- const totalBytes = topicMetrics.reduce((sum, metric) => sum + metric.value, 0);
646
-
647
- // Calculate bytes per second
648
- const bytesPerSecond = totalBytes / timeSpanSec;
649
-
650
- // Return rounded value
651
- return Number(bytesToMegabits(bytesPerSecond).toFixed(2));
652
- }
653
- }
654
-
655
- // This Source Code Form is subject to the terms of the Mozilla Public
656
- // License, v2.0. If a copy of the MPL was not distributed with this
657
- // file, You can obtain one at http://mozilla.org/MPL/2.0/
658
-
659
756
  class PoitCloudSyncFramework {
660
757
  #binarySearch(arr, targetKey) {
661
758
  let left = 0;
@@ -709,7 +806,7 @@ class PoitCloudSyncFramework {
709
806
  };
710
807
  }
711
808
  storedFrames = [];
712
- #MAX_DELAY_SEC = 0.01;
809
+ #MAX_DELAY_SEC = 0.075;
713
810
  #MAX_STORED_FRAMES = 100;
714
811
  getFrame(nsec) {
715
812
  const {
@@ -85313,7 +85410,7 @@ function legacy(parser) {
85313
85410
  return new LanguageSupport(StreamLanguage.define(parser));
85314
85411
  }
85315
85412
  function sql$1(dialectName) {
85316
- return import('./index-DeEImmkI.js').then(m => m.sql({ dialect: m[dialectName] }));
85413
+ return import('./index-DZgY6A3h.js').then(m => m.sql({ dialect: m[dialectName] }));
85317
85414
  }
85318
85415
  /**
85319
85416
  An array of language descriptions for known language packages.
@@ -85324,7 +85421,7 @@ const languages = [
85324
85421
  name: "C",
85325
85422
  extensions: ["c", "h", "ino"],
85326
85423
  load() {
85327
- return import('./index-BhITngB2.js').then(m => m.cpp());
85424
+ return import('./index-I0XgHBlj.js').then(m => m.cpp());
85328
85425
  }
85329
85426
  }),
85330
85427
  /*@__PURE__*/LanguageDescription.of({
@@ -85332,7 +85429,7 @@ const languages = [
85332
85429
  alias: ["cpp"],
85333
85430
  extensions: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"],
85334
85431
  load() {
85335
- return import('./index-BhITngB2.js').then(m => m.cpp());
85432
+ return import('./index-I0XgHBlj.js').then(m => m.cpp());
85336
85433
  }
85337
85434
  }),
85338
85435
  /*@__PURE__*/LanguageDescription.of({
@@ -85352,7 +85449,7 @@ const languages = [
85352
85449
  name: "Go",
85353
85450
  extensions: ["go"],
85354
85451
  load() {
85355
- return import('./index-jxrL_e5O.js').then(m => m.go());
85452
+ return import('./index-pwNtzQuf.js').then(m => m.go());
85356
85453
  }
85357
85454
  }),
85358
85455
  /*@__PURE__*/LanguageDescription.of({
@@ -85367,7 +85464,7 @@ const languages = [
85367
85464
  name: "Java",
85368
85465
  extensions: ["java"],
85369
85466
  load() {
85370
- return import('./index-2PbGVouo.js').then(m => m.java());
85467
+ return import('./index-DE0_tKGA.js').then(m => m.java());
85371
85468
  }
85372
85469
  }),
85373
85470
  /*@__PURE__*/LanguageDescription.of({
@@ -85383,7 +85480,7 @@ const languages = [
85383
85480
  alias: ["json5"],
85384
85481
  extensions: ["json", "map"],
85385
85482
  load() {
85386
- return import('./index-BlPNVFW_.js').then(m => m.json());
85483
+ return import('./index-BZ8z044k.js').then(m => m.json());
85387
85484
  }
85388
85485
  }),
85389
85486
  /*@__PURE__*/LanguageDescription.of({
@@ -85397,14 +85494,14 @@ const languages = [
85397
85494
  name: "LESS",
85398
85495
  extensions: ["less"],
85399
85496
  load() {
85400
- return import('./index-D3DkLyZA.js').then(m => m.less());
85497
+ return import('./index-B1pNpslP.js').then(m => m.less());
85401
85498
  }
85402
85499
  }),
85403
85500
  /*@__PURE__*/LanguageDescription.of({
85404
85501
  name: "Liquid",
85405
85502
  extensions: ["liquid"],
85406
85503
  load() {
85407
- return import('./index-BshEtuHO.js').then(m => m.liquid());
85504
+ return import('./index-CLPc3bUH.js').then(m => m.liquid());
85408
85505
  }
85409
85506
  }),
85410
85507
  /*@__PURE__*/LanguageDescription.of({
@@ -85430,7 +85527,7 @@ const languages = [
85430
85527
  name: "PHP",
85431
85528
  extensions: ["php", "php3", "php4", "php5", "php7", "phtml"],
85432
85529
  load() {
85433
- return import('./index-F42wp6uI.js').then(m => m.php());
85530
+ return import('./index-DsO3GPWF.js').then(m => m.php());
85434
85531
  }
85435
85532
  }),
85436
85533
  /*@__PURE__*/LanguageDescription.of({
@@ -85447,28 +85544,28 @@ const languages = [
85447
85544
  extensions: ["BUILD", "bzl", "py", "pyw"],
85448
85545
  filename: /^(BUCK|BUILD)$/,
85449
85546
  load() {
85450
- return import('./index-DFjClLW-.js').then(m => m.python());
85547
+ return import('./index-BNXdmaeO.js').then(m => m.python());
85451
85548
  }
85452
85549
  }),
85453
85550
  /*@__PURE__*/LanguageDescription.of({
85454
85551
  name: "Rust",
85455
85552
  extensions: ["rs"],
85456
85553
  load() {
85457
- return import('./index-DWrX4gRf.js').then(m => m.rust());
85554
+ return import('./index-B5_Aa-W3.js').then(m => m.rust());
85458
85555
  }
85459
85556
  }),
85460
85557
  /*@__PURE__*/LanguageDescription.of({
85461
85558
  name: "Sass",
85462
85559
  extensions: ["sass"],
85463
85560
  load() {
85464
- return import('./index-9gGX6Zvk.js').then(m => m.sass({ indented: true }));
85561
+ return import('./index-CGXxFWjz.js').then(m => m.sass({ indented: true }));
85465
85562
  }
85466
85563
  }),
85467
85564
  /*@__PURE__*/LanguageDescription.of({
85468
85565
  name: "SCSS",
85469
85566
  extensions: ["scss"],
85470
85567
  load() {
85471
- return import('./index-9gGX6Zvk.js').then(m => m.sass());
85568
+ return import('./index-CGXxFWjz.js').then(m => m.sass());
85472
85569
  }
85473
85570
  }),
85474
85571
  /*@__PURE__*/LanguageDescription.of({
@@ -85499,7 +85596,7 @@ const languages = [
85499
85596
  name: "WebAssembly",
85500
85597
  extensions: ["wat", "wast"],
85501
85598
  load() {
85502
- return import('./index-3GQM86WK.js').then(m => m.wast());
85599
+ return import('./index-CIHmVsn2.js').then(m => m.wast());
85503
85600
  }
85504
85601
  }),
85505
85602
  /*@__PURE__*/LanguageDescription.of({
@@ -85507,7 +85604,7 @@ const languages = [
85507
85604
  alias: ["rss", "wsdl", "xsd"],
85508
85605
  extensions: ["xml", "xsl", "xsd", "svg"],
85509
85606
  load() {
85510
- return import('./index-Yd8mYo4X.js').then(m => m.xml());
85607
+ return import('./index-B4d7dS8a.js').then(m => m.xml());
85511
85608
  }
85512
85609
  }),
85513
85610
  /*@__PURE__*/LanguageDescription.of({
@@ -85515,7 +85612,7 @@ const languages = [
85515
85612
  alias: ["yml"],
85516
85613
  extensions: ["yaml", "yml"],
85517
85614
  load() {
85518
- return import('./index-XeyUYY6F.js').then(m => m.yaml());
85615
+ return import('./index-DbT8vr6l.js').then(m => m.yaml());
85519
85616
  }
85520
85617
  }),
85521
85618
  // Legacy modes ported from CodeMirror 5
@@ -86311,13 +86408,13 @@ const languages = [
86311
86408
  name: "Vue",
86312
86409
  extensions: ["vue"],
86313
86410
  load() {
86314
- return import('./index-DuCWx5b9.js').then(m => m.vue());
86411
+ return import('./index-CXdNn-IZ.js').then(m => m.vue());
86315
86412
  }
86316
86413
  }),
86317
86414
  /*@__PURE__*/LanguageDescription.of({
86318
86415
  name: "Angular Template",
86319
86416
  load() {
86320
- return import('./index-CHN-su-T.js').then(m => m.angular());
86417
+ return import('./index-LmBY2nOo.js').then(m => m.angular());
86321
86418
  }
86322
86419
  })
86323
86420
  ];
@@ -162087,6 +162184,7 @@ function RiNumbersFill (props) {
162087
162184
 
162088
162185
  function PanelToolbarMetrics({
162089
162186
  renderedFps,
162187
+ annotationsFps,
162090
162188
  targetFps,
162091
162189
  metrics
162092
162190
  }) {
@@ -162108,7 +162206,7 @@ function PanelToolbarMetrics({
162108
162206
  ref: descriptionRef,
162109
162207
  width: "full"
162110
162208
  }, variant === "compact" ? /*#__PURE__*/React__default.createElement(Tooltip, {
162111
- content: /*#__PURE__*/React__default.createElement("ul", null, /*#__PURE__*/React__default.createElement("li", null, "Camera: ", targetFps === 0 ? "-" : targetFps, " FPS"), /*#__PURE__*/React__default.createElement("li", null, "Network:", " ", !metrics || metrics?.incomingMessagesFps === 0 ? "-" : metrics.incomingMessagesFps, " ", "FPS"), /*#__PURE__*/React__default.createElement("li", null, "Decoding:", " ", !metrics || metrics?.decodedMessagesFps === 0 ? "-" : metrics.decodedMessagesFps, " ", "FPS"), /*#__PURE__*/React__default.createElement("li", null, "Rendering: ", renderedFps === 0 ? "-" : renderedFps, " FPS"), /*#__PURE__*/React__default.createElement("li", null, "Throughput:", " ", !metrics || metrics?.messageThroughput === 0 ? "-" : metrics.messageThroughput, " ", "Mbps"), /*#__PURE__*/React__default.createElement("li", null, "Frontend Delay: ", eventLoopDelay.toFixed(2), " ms")),
162209
+ content: /*#__PURE__*/React__default.createElement("ul", null, /*#__PURE__*/React__default.createElement("li", null, "Camera: ", !targetFps || targetFps === 0 ? "-" : targetFps, " FPS"), /*#__PURE__*/React__default.createElement("li", null, "Network:", " ", !metrics || metrics?.incomingMessagesFps === 0 ? "-" : metrics.incomingMessagesFps, " ", "FPS"), /*#__PURE__*/React__default.createElement("li", null, "Decoding:", " ", !metrics || metrics?.decodedMessagesFps === 0 ? "-" : metrics.decodedMessagesFps, " ", "FPS"), /*#__PURE__*/React__default.createElement("li", null, "Rendering: ", !renderedFps || renderedFps === 0 ? "-" : renderedFps, " FPS"), /*#__PURE__*/React__default.createElement("li", null, "Annotations:", " ", !annotationsFps || annotationsFps === 0 || !Number.isFinite(annotationsFps) ? "-" : annotationsFps, " ", "FPS"), /*#__PURE__*/React__default.createElement("li", null, "Throughput:", " ", !metrics || metrics?.messageThroughput === 0 ? "-" : metrics.messageThroughput, " ", "Mbps"), /*#__PURE__*/React__default.createElement("li", null, "Frontend Delay: ", eventLoopDelay.toFixed(2), " ms")),
162112
162210
  direction: "bottom",
162113
162211
  className: "ml-auto"
162114
162212
  }, /*#__PURE__*/React__default.createElement(Button, {
@@ -162125,6 +162223,8 @@ function PanelToolbarMetrics({
162125
162223
  text: `Decoding: ${metrics.decodedMessagesFps === 0 ? "-" : metrics.decodedMessagesFps} FPS`
162126
162224
  }), renderedFps !== undefined && /*#__PURE__*/React__default.createElement(Label$3, {
162127
162225
  text: `Rendering: ${renderedFps === 0 ? "-" : renderedFps} FPS`
162226
+ }), annotationsFps !== undefined && /*#__PURE__*/React__default.createElement(Label$3, {
162227
+ text: `Annotations: ${annotationsFps === 0 || !Number.isFinite(annotationsFps) ? "-" : annotationsFps} FPS`
162128
162228
  }), metrics?.messageThroughput !== undefined && /*#__PURE__*/React__default.createElement(Label$3, {
162129
162229
  text: `Throughput: ${metrics.messageThroughput === 0 ? "-" : metrics.messageThroughput} Mbps`
162130
162230
  }), eventLoopDelay !== undefined && /*#__PURE__*/React__default.createElement(Label$3, {
@@ -162159,6 +162259,7 @@ const PanelToolbar = ({
162159
162259
  targetFps,
162160
162260
  triggerToast,
162161
162261
  renderedFps,
162262
+ annotationsFps,
162162
162263
  toggleTopic
162163
162264
  }) => {
162164
162265
  const [metrics, setMetrics] = React__default.useState();
@@ -162238,6 +162339,7 @@ const PanelToolbar = ({
162238
162339
  className: "text-[14px]/[14px] xl:pb-[2px]"
162239
162340
  })), /*#__PURE__*/React__default.createElement(PanelToolbarMetrics, {
162240
162341
  renderedFps: renderedFps,
162342
+ annotationsFps: annotationsFps,
162241
162343
  targetFps: targetFps,
162242
162344
  metrics: metrics
162243
162345
  }), /*#__PURE__*/React__default.createElement(Flex, {
@@ -162306,10 +162408,10 @@ const useDetections = () => {
162306
162408
  };
162307
162409
  const rawToAnnotations = (rawAnnotations, kind, current) => rawAnnotations.map(annotationTopic => ({
162308
162410
  name: annotationTopic,
162309
- extra: kind === 'extra',
162411
+ extra: kind === "extra",
162310
162412
  enabled: current.find(({
162311
162413
  name
162312
- }) => name === annotationTopic)?.enabled ?? kind === 'main'
162414
+ }) => name === annotationTopic)?.enabled ?? kind === "main"
162313
162415
  }));
162314
162416
  const Panel = ({
162315
162417
  children,
@@ -162320,6 +162422,7 @@ const Panel = ({
162320
162422
  extraAnnotationTopics = [],
162321
162423
  targetFps,
162322
162424
  renderedFps,
162425
+ annotationsFps,
162323
162426
  renderDelay,
162324
162427
  toggleTopic,
162325
162428
  triggerToast
@@ -162327,7 +162430,7 @@ const Panel = ({
162327
162430
  const [detections, setDetections] = React__default.useState([]);
162328
162431
  React__default.useEffect(() => {
162329
162432
  if (!disableAnnotations) {
162330
- setDetections(current => [...rawToAnnotations(annotationTopics, 'main', current), ...rawToAnnotations(extraAnnotationTopics, 'extra', current)]);
162433
+ setDetections(current => [...rawToAnnotations(annotationTopics, "main", current), ...rawToAnnotations(extraAnnotationTopics, "extra", current)]);
162331
162434
  }
162332
162435
  // eslint-disable-next-line react-hooks/exhaustive-deps
162333
162436
  }, [JSON.stringify(annotationTopics), JSON.stringify(extraAnnotationTopics)]);
@@ -162351,6 +162454,7 @@ const Panel = ({
162351
162454
  disableAnnotations: disableAnnotations,
162352
162455
  targetFps: targetFps,
162353
162456
  renderedFps: renderedFps,
162457
+ annotationsFps: annotationsFps,
162354
162458
  renderDelay: renderDelay,
162355
162459
  toggleTopic: toggleTopic,
162356
162460
  triggerToast: triggerToast
@@ -162387,10 +162491,11 @@ function createRenderDelaySampler() {
162387
162491
  };
162388
162492
  }
162389
162493
 
162390
- const ImagePanelComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-C4kNkDQc.js'));
162494
+ const ImagePanelComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-CJSOG1CX.js'));
162391
162495
  const ImagePanelBody = ({
162392
162496
  topic,
162393
- frameRenderedEvent
162497
+ frameRenderedEvent,
162498
+ annotationsFpsUpdateHandler
162394
162499
  }) => {
162395
162500
  const {
162396
162501
  detections
@@ -162409,12 +162514,14 @@ const ImagePanelBody = ({
162409
162514
  }), [detections, topic]);
162410
162515
  return /*#__PURE__*/React__default.createElement(ImagePanelComponent, {
162411
162516
  overrideConfig: defaultConfig,
162412
- frameRenderedEvent: frameRenderedEvent
162517
+ frameRenderedEvent: frameRenderedEvent,
162518
+ annotationsFpsUpdateHandler: annotationsFpsUpdateHandler
162413
162519
  });
162414
162520
  };
162415
162521
  const ImagePanel = /*#__PURE__*/React__default.memo(function ImagePanel(props) {
162416
162522
  const renderedFpsMetricsManagerRef = React__default.useRef(null);
162417
162523
  const [renderedFps, setRenderedFps] = React__default.useState(undefined);
162524
+ const [annotationsFps, setAnnotationsFps] = React__default.useState(undefined);
162418
162525
  const {
162419
162526
  averageFrameDelay,
162420
162527
  addFrameTime
@@ -162440,15 +162547,20 @@ const ImagePanel = /*#__PURE__*/React__default.memo(function ImagePanel(props) {
162440
162547
  renderedFpsMetricsManagerRef.current?.registerEvent('render');
162441
162548
  addFrameTime(frameTime);
162442
162549
  }, [addFrameTime]);
162550
+ const handleAnnotationsFpsUpdate = React__default.useCallback(fps => {
162551
+ setAnnotationsFps(fps);
162552
+ }, []);
162443
162553
  return /*#__PURE__*/React__default.createElement(Panel, _extends$3({
162444
162554
  kind: "image"
162445
162555
  }, props, {
162446
162556
  toggleTopic: props.toggleTopic,
162447
162557
  renderedFps: renderedFps,
162558
+ annotationsFps: annotationsFps,
162448
162559
  renderDelay: averageFrameDelay
162449
162560
  }), /*#__PURE__*/React__default.createElement(ImagePanelBody, {
162450
162561
  topic: props.topic,
162451
- frameRenderedEvent: handleFrameRendered
162562
+ frameRenderedEvent: handleFrameRendered,
162563
+ annotationsFpsUpdateHandler: handleAnnotationsFpsUpdate
162452
162564
  }));
162453
162565
  });
162454
162566
 
@@ -162456,7 +162568,7 @@ const ImagePanel = /*#__PURE__*/React__default.memo(function ImagePanel(props) {
162456
162568
  // License, v2.0. If a copy of the MPL was not distributed with this
162457
162569
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
162458
162570
 
162459
- const ThreeDeeRenderComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-CWe6_z0e.js'));
162571
+ const ThreeDeeRenderComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-CdXrBVPC.js'));
162460
162572
  const PointCloudPanelBody = ({
162461
162573
  topic,
162462
162574
  frameRenderedEvent
@@ -162494,7 +162606,7 @@ const PointCloudPanelBody = ({
162494
162606
  thetaOffset: 180,
162495
162607
  fovy: getFovy(),
162496
162608
  near: 5,
162497
- far: 10000
162609
+ far: 20000
162498
162610
  },
162499
162611
  imageMode: {
162500
162612
  colorMode: "rgba-fields"
@@ -162551,4 +162663,4 @@ const PointCloudPanel = /*#__PURE__*/React__default.memo(function PointCloudPane
162551
162663
  }));
162552
162664
  });
162553
162665
 
162554
- export { flatIndent as $, AnalyticsContext as A, PlayerCapabilities as B, assertNever as C, PlayerPresence as D, ErrorDisplay as E, isEqual as F, isDesktopApp as G, createTheme$1 as H, propTypesExports as I, indentNodeProp as J, continuedIndent as K, LeftSidebarItemKeys as L, foldNodeProp as M, styleTags as N, tags$1 as O, PropTypes as P, LRLanguage as Q, RightSidebarItemKeys as R, Stack$1 as S, LanguageSupport as T, ExternalTokenizer as U, LRParser as V, WorkspaceContext as W, ifNotIn as X, completeFromList as Y, syntaxTree as Z, _extends$3 as _, AppEvent as a, delimitedIndent as a0, foldInside as a1, ContextTracker as a2, LocalTokenGroup as a3, snippetCompletion as a4, IterMode as a5, NodeWeakMap as a6, defineCSSCompletionSource as a7, EditorView as a8, EditorSelection as a9, html$4 as aa, parseMixed as ab, bracketMatchingHandle as ac, javascriptLanguage as ad, VisualizerConnection as ae, VisualizerContext as af, PanelLayout as ag, ImagePanel as ah, PointCloudPanel as ai, baseSet as b, createAggregator as c, useTranslation as d, usePanelCatalog as e, flatRest as f, generateUtilityClass as g, EmptyState as h, isEmpty as i, PanelContext as j, PanelCatalogContext as k, usePanelStateStore as l, makeStyles as m, useDefaultPanelTitle as n, useWorkspaceStore as o, WorkspaceStoreSelectors as p, difference as q, usePanelContext as r, useMessagePipeline as s, useHoverValue as t, useAnalytics as u, v4 as v, useSetHoverValue as w, useClearHoverValue as x, useMessagePipelineGetter as y, usePanelSettingsTreeUpdate as z };
162666
+ export { flatIndent as $, AnalyticsContext as A, PlayerCapabilities as B, assertNever as C, PlayerPresence as D, ErrorDisplay as E, isEqual as F, isDesktopApp as G, createTheme$1 as H, propTypesExports as I, indentNodeProp as J, continuedIndent as K, LeftSidebarItemKeys as L, foldNodeProp as M, styleTags as N, tags$1 as O, PropTypes as P, LRLanguage as Q, RightSidebarItemKeys as R, Stack$1 as S, LanguageSupport as T, ExternalTokenizer as U, LRParser as V, WorkspaceContext as W, ifNotIn as X, completeFromList as Y, syntaxTree as Z, _extends$3 as _, AppEvent as a, delimitedIndent as a0, foldInside as a1, ContextTracker as a2, LocalTokenGroup as a3, snippetCompletion as a4, IterMode as a5, NodeWeakMap as a6, defineCSSCompletionSource as a7, EditorView as a8, EditorSelection as a9, html$4 as aa, parseMixed as ab, bracketMatchingHandle as ac, javascriptLanguage as ad, VisualizerConnection as ae, VisualizerContext as af, PanelLayout as ag, ImagePanel as ah, PointCloudPanel as ai, EventMetricsManager as aj, ThroughputMetricsManager as ak, baseSet as b, createAggregator as c, useTranslation as d, usePanelCatalog as e, flatRest as f, generateUtilityClass as g, EmptyState as h, isEmpty as i, PanelContext as j, PanelCatalogContext as k, usePanelStateStore as l, makeStyles as m, useDefaultPanelTitle as n, useWorkspaceStore as o, WorkspaceStoreSelectors as p, difference as q, usePanelContext as r, useMessagePipeline as s, useHoverValue as t, useAnalytics as u, v4 as v, useSetHoverValue as w, useClearHoverValue as x, useMessagePipelineGetter as y, usePanelSettingsTreeUpdate as z };