Compare commits

..
6 Commits
Author SHA1 Message Date
rUv 08210b02c9 Update README.md
removed promo imgs.
2026-08-31 12:42:10 -04:00
ruv 27f5540663 feat(server): advertise local RuView installations 2026-08-27 15:52:10 -04:00
rUv b742eae7d6 fix(sensing): fuse only coherent frame cohorts (#1726) 2026-08-27 10:10:31 -04:00
rUv d42c5581f3 feat(rufield): ultrasonic as the field surface's second modality (#1716)
ADR-262 §8 question 5 left the second modality open, asking whether it should
be rvcsi. This answers ultrasonic instead, because the cost collapsed:
rufield-adapters now ships UltrasonicReplayAdapter, the first adapter for
Modality::Ultrasonic (registry code 7, empty since v0.1), which parses,
validates and signs BatVu range profiles upstream. RuView only has to decide
what it will put on a wire.

Bumps vendor/rufield 43b1df3 -> 9955672. Two struct literals in bridge.rs gain
fields added upstream (Observation: track_id, attributes, identity_evidence,
channel_sounding_provenance; SensorDescriptor: coordinate_frame, position_m,
orientation_xyzw). All left empty, each for a stated reason rather than a
convenient default — the pose fields in particular, because a CSI link has no
boresight and §6 makes no validated room-coordinate claim. The nine existing
P1 gates pass unchanged.

The decision this module makes is structural rather than a runtime refusal.
The adapter's full per-bin frame is P0 and would be dropped by the egress gate
after all the work of parsing and signing it; its 32-bin coarse reduction is
P1 and egress-safe. So the module does not offer the choice — it configures
the coarse mode, because a consumer cannot un-coarsen a coarse profile whereas
a check can be reordered. The gate still runs and is asserted to drop nothing.

12 gates in tests/ultrasonic_gates.rs, including the honest negative result: an
ultrasonic scan produces no fused inferences at all, and both independent
reasons are pinned. The adapter declines to populate `presence` — one
transducer pair cannot distinguish a person from a coat over the back of a
chair — and the engine's feature vocabulary is entirely statements about a
body, so range_m has nothing to drive.

The fixture is BatVu's own emitter output, byte-identical to the one in
ruvnet/rufield, so schema drift fails a build in one of three repositories
rather than an ingest in a deployment.

Not wired into the running server; P1 shipped as a library before P3 wired it
in, and this follows the same staging.
2026-08-25 21:40:53 -04:00
rUv 0df48df7b2 feat: add native iPhone LiDAR sensor and web viewer (#1684)
* feat(ios): add RuView LiDAR frame protocol

* feat(ios): capture ARKit scene depth for RuView

* feat(ios): stream compact LiDAR frames over websocket

* feat(ios): add native LiDAR capture UI

* feat(ios): add RuView LiDAR app entrypoint

* feat(web): add LiDAR bridge web package

* feat(web): decode RuView LiDAR wire frames

* feat(web): add local LiDAR websocket relay

* feat(web): add LiDAR browser viewer

* feat(web): render live LiDAR point cloud

* fix(ios): use wall clock time for LiDAR provenance

* feat(web): style LiDAR viewer

* test(web): add LiDAR codec tests

* docs: add iPhone LiDAR integration guide

* docs(adr): define iPhone LiDAR sensor bridge

* fix(ios): harden and validate LiDAR bridge

* fix(ios): qualify LiDAR wire depth type
2026-08-22 18:06:16 -04:00
rUv bd110e0eac fix(homecore): enable standalone Arc serialization (#1682) 2026-08-22 15:55:36 -04:00
38 changed files with 2506 additions and 79 deletions

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
name: iPhone LiDAR integration
on:
push:
branches: [main]
paths:
- 'integrations/iphone-lidar/**'
- 'docs/adr/ADR-340-iphone-lidar-sensor-bridge.md'
- '.github/workflows/iphone-lidar.yml'
pull_request:
paths:
- 'integrations/iphone-lidar/**'
- 'docs/adr/ADR-340-iphone-lidar-sensor-bridge.md'
- '.github/workflows/iphone-lidar.yml'
permissions:
contents: read
jobs:
web:
name: Node relay and codec
runs-on: ubuntu-latest
defaults:
run:
working-directory: integrations/iphone-lidar/web
steps:
- name: Checkout code
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: '22'
cache: npm
cache-dependency-path: integrations/iphone-lidar/web/package-lock.json
- name: Install dependencies
run: npm ci --ignore-scripts
- name: Run tests
run: npm test
- name: Audit runtime dependencies
run: npm audit --omit=optional --audit-level=high
ios:
name: iOS 17 compile
runs-on: macos-15
steps:
- name: Checkout code
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- name: Compile native sources with strict concurrency
shell: bash
run: |
set -euo pipefail
sdk="$(xcrun --sdk iphoneos --show-sdk-path)"
build_dir="$RUNNER_TEMP/ruview-lidar-build"
mkdir -p "$build_dir"
cd "$build_dir"
xcrun swiftc \
-parse-as-library \
-target arm64-apple-ios17.0 \
-sdk "$sdk" \
-module-name RuViewLiDAR \
-strict-concurrency=complete \
-warnings-as-errors \
-emit-module \
-emit-module-path "$build_dir/RuViewLiDAR.swiftmodule" \
-c "$GITHUB_WORKSPACE"/integrations/iphone-lidar/native/RuViewLiDAR/*.swift
@@ -28,6 +28,7 @@ on:
- 'v2/crates/wifi-densepose-wifiscan/**'
- 'v2/crates/wifi-densepose-bfld/**'
- 'v2/crates/cog-ha-matter/**'
- 'v2/crates/homecore*/**'
- 'v2/Cargo.toml'
- 'v2/Cargo.lock'
- 'ui/**'
+1 -10
View File
@@ -5,16 +5,7 @@
<img src="assets/ruview-seed.png" alt="RuView - WiFi DensePose" width="100%">
</a>
</p>
<p align="center">
<a href="https://cognitum.one/marketplace">
<img src="assets/musica-promo.png" alt="Cognitum Musica" width="100%">
</a>
</p>
<p align="center">
<a href="https://github.com/ruvnet/RuCelium">
<img src="assets/rucelium-hero.png" alt="RuCelium — environmental intelligence" width="100%">
</a>
</p>
## **See through walls with WiFi** ##
@@ -139,6 +139,32 @@ Implement the §3.3 mapping: `effective_class → PrivacyClass`, `cog-ha-matter`
Add an opt-in `/ws/field` endpoint (or a `field_events` array on `SensingUpdate` behind a flag) carrying the signed `FieldEvent` + a privacy badge. Add an ingest route to `rufield-viewer` (it has none today — `server.rs:63-72`) so it can replay RuView's live feed instead of only `SyntheticSim`. **Gate:** a WS integration test asserting a connected client receives a privacy-badged, signature-verifiable `FieldEvent`; a viewer test asserting the new ingest route renders a live event. The `cognitum` appliance can speak RuField by consuming this endpoint (it already runs `ruview-vitals-worker`); deferred to its own ADR.
**P4 — fusion composition + multi-modality (ARCHITECTURE, optional).**
> **Update — second modality landed as a library.** Open question 5 below asked
> whether the second modality should be `rvcsi`. It is **ultrasonic**, because
> the cost collapsed: `rufield-adapters` now ships `UltrasonicReplayAdapter`,
> the first adapter for `Modality::Ultrasonic` (registry code 7, empty since
> v0.1), which parses, validates and signs [BatVu](https://github.com/ruvnet/batvu)
> range profiles upstream. RuView only has to decide what it will put on a wire.
>
> `wifi-densepose-rufield::ultrasonic` is that decision, and it is expressed
> structurally: the adapter is configured for its 32-bin coarse output (`P1`,
> egress-safe) rather than its full per-bin frame (`P0`, edge-local), because a
> consumer cannot un-coarsen a coarse profile whereas a runtime check can be
> reordered. The `network_egress_allowed` gate still runs and is asserted to
> drop nothing.
>
> Gates: `tests/ultrasonic_gates.rs`, 12 tests — round-trip, signature-verify,
> fusion ingest, P1 on **both** tensor and observation, structural unreachability
> of P4/P5, trust-tier refusal in both directions, determinism, whole-file
> rejection of a malformed recording. Plus one asserting the honest negative
> result: **an ultrasonic scan produces no fused inferences at all**, because the
> adapter declines to populate `presence` (one transducer pair cannot tell a
> person from a coat on a chair) and the engine's feature vocabulary is entirely
> statements about a body. RuField v0.1 has no predicate for static geometry.
>
> Not wired into the running server. P1 shipped as a library before P3 wired it
> in; this follows the same staging.
Wire a second modality (cheapest: an `rvcsi`-sourced event, or recorded mmWave) into `RuFieldFusion` alongside the WiFi event, proving cross-modality fusion above ruvsense. **Gate:** a fusion test with two modalities producing ≥1 cross-modal inference, with provenance coverage 100%.
---
@@ -0,0 +1,59 @@
# ADR 340: iPhone LiDAR Sensor Bridge
Status: Proposed
## Context
RuView needs a low cost mobile geometry sensor that can contribute calibrated spatial observations without coupling the perception substrate to Apple frameworks.
ARKit exposes rear LiDAR scene depth through `ARFrame.sceneDepth` and `smoothedSceneDepth` on supported devices. Ordinary mobile web pages do not receive this ARKit depth surface directly, so native capture and web visualization must be separated.
## Decision
Use a two layer architecture.
1. Native Swift and ARKit perform acquisition.
2. A modality neutral wire frame transports geometry into browser tools and, next, the RuView HAL.
The native client will capture depth, confidence, camera intrinsics, and world tracking pose. RGB imagery is excluded from the default transport.
The protocol identifier is `ruview.lidar.depth.v1`.
Depth samples are quantized to UInt16 millimeters for transport. Confidence remains UInt8. The default sender downsamples by two spatially and caps transmission at 15 FPS. Full fidelity depth remains available locally for future on device inference.
## RuView integration boundary
The transport must not become a second world model. The production receiver converts each packet into the canonical `ruview-hal::Observation`, then passes it through authenticated sensor identity, provenance, OOD gating, uncertainty aware fusion, spatial memory, and WorldGraph adapters.
Rules:
1. `source=live` is valid only for frames produced by an active ARKit session.
2. Sequence numbers are monotonic per sensor session.
3. Wall clock timestamp is separate from ARKit monotonic frame timing.
4. RGB is off by default and requires an explicit higher privacy capability.
5. Browser clients consume geometry but are not treated as authoritative sensors.
6. Unsupported devices fail closed rather than substituting simulated depth.
## Performance target
`[SYNTHETIC]` A 256 x 192 Float32 depth map is about 196 KB before confidence and metadata. Downsampling to 128 x 96 and encoding each sample as two byte depth plus one byte confidence yields about 36.9 KB raw. At 15 FPS the raw sensor payload is about 553 KB/s. Base64 raises this to roughly 737 KB/s before JSON metadata. These values are arithmetic sizing estimates, not device measurements.
The `[CLAIMED target]` for local network latency is below 150 ms p95. A later binary WebSocket or QUIC transport can remove base64 overhead; the exact end-to-end reduction must be measured before it is claimed.
## Security
The development relay is LAN-facing, requires a random per-run bearer token, bounds message size, and restricts the files it serves. Its default `ws://` transport is not encrypted, so it is not a production trust boundary.
Production requires WSS, authenticated sensor identity, replay protection, message size limits, per tenant authorization, provenance receipts, and explicit retention policy before persistence.
## Consequences
Benefits include commodity hardware, metric depth, tracked camera pose, rapid room scanning, calibration support for RF sensing, and a practical ground truth source for RuView experiments.
The main limitation is that Apple provides processed scene depth rather than the underlying raw transient LiDAR waveform. Therefore this implementation supports direct geometry and sensor fusion now, but does not reproduce research systems that require raw multipath time of flight transients for non line of sight reconstruction.
## Acceptance criteria
A physical LiDAR capable iPhone must stream live geometry to the browser viewer with monotonically increasing sequence numbers, no RGB payload, valid confidence maps, and below 150 ms p95 local network latency over a 60 second run.
CI type-checking and simulator runs do not satisfy this criterion. Until a captured physical-device run records the environment and results, the hardware behavior and latency remain unverified.
@@ -0,0 +1,93 @@
# ADR-344: Adaptive local installation discovery
## Status
Accepted — local advertisement and mobile discovery implemented; physical
peer-link and hosted-relay qualification pending.
## Context
RuView installations previously depended on a manually stored IP address.
DHCP changes, access-point changes, and client isolation could therefore leave
a healthy sensing installation unreachable from the mobile app. Repeated
authentication-policy log entries did not prove that the selected endpoint was
reachable.
Discovery must make commissioning recoverable without turning a service name
into authentication, leaking sensor data, scanning arbitrary subnets, or
silently moving private spatial data to a hosted service.
## Decision
The sensing server advertises one bounded `_ruview._tcp.local.` service when it
is bound to a routable interface. Loopback-only instances do not advertise,
and operators can disable advertisement with `--no-mdns`.
The TXT contract is deliberately small:
| Key | Required | Meaning |
|---|---:|---|
| `schema=ruview.installation.v1` | yes | Fail-closed protocol discriminator |
| `tls=0|1` | yes | HTTP or HTTPS origin construction |
| `installation=<opaque id>` | no | Bounded routing hint, never authentication |
The advertisement contains no node inventory, room identifier, SSID,
credentials, CSI, vital estimates, pose, identity, or learning data. The
hostname is bounded and sanitized before registration. Advertisement failure
is recoverable and does not stop sensing.
RuView Mobile resolves only the matching service and schema, validates the
resulting origin under its private-LAN/HTTPS policy, and requires an application
health probe before selection. Its adaptive broker retains the configured
origin preference and requires two failed configured probes plus two healthy
fallback probes before switching. Credentials remain scoped to their saved
origin.
The recovery ladder is:
1. configured private-LAN or HTTPS origin;
2. verified Bonjour local origin;
3. physically qualified Apple peer-to-peer local path;
4. explicit, authenticated HTTPS relay for bounded derived frames only;
5. optional administrator-managed WireGuard/Tailscale access.
Only levels 1 and 2 are implemented and software-validated by this decision.
Peer-to-peer browsing is enabled on Apple platforms, but it is not a qualified
peer-link data plane. This repository does not provide a hosted relay and must
fail closed when no local endpoint is healthy.
## Security and privacy consequences
- Service discovery is routing evidence, not installation authentication.
- Public HTTP origins, credentials in URLs, malformed records, and records with
the wrong schema are rejected before use.
- Raw CSI, RSSI streams, camera/LiDAR frames, room geometry, pose labels,
identity data, and training examples remain local.
- Future relay work requires a separate consent, authentication, revocation,
minimization, and physical evidence review.
- ESP32-S3/C6 nodes remain provisioned to the sensing installation. This ADR
does not claim direct phone-to-node discovery or invent a firmware protocol.
## Validation
Software acceptance requires:
- unit tests for bounded advertisement construction and hostname sanitation;
- mobile parser rejection, route scoring, anti-flapping, and Settings UI tests;
- Rust, TypeScript, lint, security, metaharness, Expo, and native compile gates;
- a real Bonjour resolve of the TXT contract followed by a successful
`/api/v1/status` probe.
Physical qualification additionally requires installation discovery on an
iPhone, live frame and node-inventory receipt, DHCP-change recovery without
flapping, and a five-to-ten-minute zero-fusion-error burn-in. Simulator and
host-only results remain `MEASURED_SOFTWARE`; peer-link, relay, and physical
reconnection claims remain `NOT_MEASURED` until those captures exist.
## Implementation references
- `v2/crates/wifi-densepose-sensing-server/src/discovery.rs`
- `v2/crates/wifi-densepose-sensing-server/src/main.rs`
- Mobile companion decision: `cognitum-one/ruview-mobile`,
`docs/adr/ADR-026-adaptive-local-installation-discovery-and-transport-recovery.md`
- Related decisions: ADR-034, ADR-054, ADR-296
+1
View File
@@ -105,6 +105,7 @@ Statuses: **Proposed** (under discussion), **Accepted** (approved and/or impleme
| [ADR-035](ADR-035-live-sensing-ui-accuracy.md) | Live Sensing UI Accuracy and Data Transparency | Accepted |
| [ADR-036](ADR-036-rvf-training-pipeline-ui.md) | Training Pipeline UI Integration | Proposed |
| [ADR-043](ADR-043-sensing-server-ui-api-completion.md) | Sensing Server UI API Completion (14 endpoints) | Accepted |
| [ADR-344](ADR-344-adaptive-local-installation-discovery.md) | Adaptive Local Installation Discovery | Accepted (local software path) |
| [ADR-115](ADR-115-home-assistant-integration.md) | Home Assistant integration via MQTT auto-discovery + Matter bridge (HA-DISCO + HA-FABRIC + HA-MIND) | Accepted (MQTT track) / Proposed (Matter SDK P8b) |
| [ADR-169](ADR-169-adam-mode-light-theme.md) | adam-mode — light theme toggle for the three.js realtime demo | Proposed |
| [ADR-170](ADR-170-yoga-mode-pose-system.md) | yoga-mode — yoga pose detection, classification, and scoring for the three.js realtime demo | Proposed |
+78
View File
@@ -0,0 +1,78 @@
# RuView iPhone LiDAR
This experimental integration provides the native and browser components needed to use a LiDAR-capable iPhone as a RuView geometry sensor. The native source is type-checked against the iOS SDK in CI; physical-device validation is tracked separately below.
## Architecture
```text
iPhone LiDAR
-> ARKit sceneDepth
-> depth + confidence + camera intrinsics + device pose
-> compact u16 millimeter wire frame
-> WebSocket relay
-> browser point cloud
-> future RuView HAL / fusion ingest
```
The native path is the sensor. The web path is a receiver and visualization surface. Mobile Safari does not expose ARKit scene depth directly to ordinary web pages, so the browser cannot replace the native capture layer on iPhone today.
## Native iPhone path
Create an iOS SwiftUI app target in Xcode, deployment target iOS 17 or newer, then add the files under `native/RuViewLiDAR/` to the target.
Add this Info.plist value:
```xml
<key>NSCameraUsageDescription</key>
<string>RuView uses the camera and LiDAR scanner to capture local depth geometry.</string>
```
Run on a physical LiDAR capable iPhone or iPad. The simulator does not provide LiDAR scene depth.
The app requests `ARWorldTrackingConfiguration` with `.sceneDepth`, checks `supportsFrameSemantics`, extracts `ARDepthData.depthMap` and `confidenceMap`, and never transmits RGB camera frames.
## Browser path
```bash
cd integrations/iphone-lidar/web
npm ci
npm test
npm start
```
The relay prints a random per-run access token. Open the printed browser URL and set the iPhone endpoint to the printed native URL. They have this form:
```text
http://HOST:8787/?token=TOKEN
ws://HOST:8787/ws/lidar?token=TOKEN
```
Set `RUVIEW_LIDAR_TOKEN` to supply the token explicitly. The token only prevents unauthenticated peers from joining the development relay; because `ws://` does not encrypt it, production use requires TLS and `wss://`.
## Wire format
Schema: `ruview.lidar.depth.v1`
Depth is downsampled by 2 in each dimension by default and streamed at a maximum of 15 FPS. Each depth sample is encoded as little endian UInt16 millimeters plus one UInt8 confidence value. `[SYNTHETIC]` Arithmetic sizing reduces the depth payload from roughly 196 KB per 256 x 192 Float32 frame to roughly 37 KB per 128 x 96 frame before base64 and JSON overhead.
`[SYNTHETIC]` At 15 FPS that is approximately 0.75 MB/s after base64 overhead, versus roughly 8 MB/s for uncompressed Float32 JSON at full resolution. These are sizing estimates, not device or network measurements.
## Privacy and governance
The initial implementation labels provenance as `source=live` and `privacyClass=geometry-only`. It sends depth geometry, confidence, camera intrinsics, pose, sequence, and wall clock timestamp. It does not send RGB imagery.
The development relay requires an ephemeral token and bounds each WebSocket message, but it is not a production trust boundary. Production integration should terminate the WebSocket inside RuView, authenticate the device using the existing sensor identity path, convert each frame into `ruview-hal::Observation`, and attach witness receipts before fusion or persistence.
## Validation status
- `[MEASURED]` The committed Node tests cover wire decoding, malformed inputs, relay authentication, static-file restrictions, and live WebSocket forwarding.
- `[MEASURED]` GitHub Actions type-checks the native sources with strict concurrency against the iOS 17 SDK.
- Physical iPhone capture, end-to-end rendering, confidence-map behavior, and the latency target are not yet measured. A simulator or CI compile does not satisfy the hardware acceptance test.
## Acceptance test
1. Run the relay and browser viewer.
2. Run the native app on a LiDAR capable iPhone.
3. Start LiDAR capture and enable streaming.
4. Move the phone through a room.
5. Verify the browser shows a changing point cloud, sequence increases monotonically, latency stays below the `[CLAIMED target]` of 150 ms p95 on a local WiFi network, and no RGB payload is present in captured WebSocket frames.
@@ -0,0 +1,121 @@
import SwiftUI
struct ContentView: View {
@StateObject private var capture = LiDARCaptureManager()
@State private var endpoint = "ws://HOST:8787/ws/lidar?token=TOKEN"
@State private var streaming = false
@State private var status = "Idle"
private let streamer = WebSocketStreamer()
var body: some View {
NavigationStack {
Form {
Section("Sensor") {
HStack {
Text("State")
Spacer()
Text(stateText)
.foregroundStyle(stateColor)
}
HStack {
Text("Capture FPS")
Spacer()
Text(capture.framesPerSecond.formatted(.number.precision(.fractionLength(1))))
}
if let frame = capture.lastFrame {
HStack {
Text("Depth")
Spacer()
Text("\(frame.depth.width) x \(frame.depth.height)")
}
HStack {
Text("Sequence")
Spacer()
Text("\(frame.provenance.sequence)")
}
}
Button("Start LiDAR") {
capture.start(smoothed: false)
}
.disabled(capture.state == .running)
Button("Stop") {
capture.stop()
}
.disabled(capture.state != .running)
}
Section("RuView Stream") {
TextField("ws://host:port/ws/lidar", text: $endpoint)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
Toggle("Stream geometry", isOn: $streaming)
.onChange(of: streaming) { _, enabled in
Task {
if enabled {
do {
try await streamer.connect(to: endpoint)
status = "Connected"
} catch {
streaming = false
status = error.localizedDescription
}
} else {
await streamer.disconnect()
status = "Disconnected"
}
}
}
Text(status)
.font(.caption)
.foregroundStyle(.secondary)
}
Section("Privacy") {
Text("This implementation transmits depth geometry, confidence, camera intrinsics, and device pose. RGB camera frames are not transmitted.")
.font(.footnote)
}
}
.navigationTitle("RuView LiDAR")
.onAppear {
capture.onFrame = { frame in
guard streaming else { return }
Task {
do {
try await streamer.send(frame, maxFPS: 15, sampleStep: 2)
} catch {
await MainActor.run {
status = error.localizedDescription
}
}
}
}
}
.onDisappear {
capture.stop()
Task { await streamer.disconnect() }
}
}
}
private var stateText: String {
switch capture.state {
case .idle: return "Idle"
case .unsupported: return "No LiDAR"
case .running: return "Live"
case .failed(let message): return "Error: \(message)"
}
}
private var stateColor: Color {
switch capture.state {
case .running: return .green
case .failed, .unsupported: return .red
case .idle: return .secondary
}
}
}
@@ -0,0 +1,138 @@
import ARKit
import CoreVideo
import Foundation
@MainActor
final class LiDARCaptureManager: NSObject, ObservableObject {
enum State: Equatable {
case idle
case unsupported
case running
case failed(String)
}
@Published private(set) var state: State = .idle
@Published private(set) var lastFrame: RuViewLiDARFrame?
@Published private(set) var framesPerSecond: Double = 0
let session = ARSession()
var onFrame: (@MainActor @Sendable (RuViewLiDARFrame) -> Void)?
private var sequence: UInt64 = 0
private var lastTimestamp: TimeInterval?
private let processingQueue = DispatchQueue(label: "one.ruv.lidar.capture", qos: .userInitiated)
override init() {
super.init()
session.delegate = self
session.delegateQueue = processingQueue
}
func start(smoothed: Bool = false) {
let configuration = ARWorldTrackingConfiguration()
let semantic: ARConfiguration.FrameSemantics = smoothed ? .smoothedSceneDepth : .sceneDepth
guard ARWorldTrackingConfiguration.supportsFrameSemantics(semantic) else {
state = .unsupported
return
}
configuration.frameSemantics.insert(semantic)
configuration.worldAlignment = .gravity
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
state = .running
}
func stop() {
session.pause()
state = .idle
}
nonisolated private func makeFrame(from frame: ARFrame) -> RuViewLiDARFrame? {
guard let sceneDepth = frame.sceneDepth ?? frame.smoothedSceneDepth else { return nil }
let depthMap = sceneDepth.depthMap
let confidenceMap = sceneDepth.confidenceMap
guard CVPixelBufferLockBaseAddress(depthMap, .readOnly) == kCVReturnSuccess else {
return nil
}
defer { CVPixelBufferUnlockBaseAddress(depthMap, .readOnly) }
guard CVPixelBufferGetPixelFormatType(depthMap) == kCVPixelFormatType_DepthFloat32,
let depthBase = CVPixelBufferGetBaseAddress(depthMap) else {
return nil
}
let width = CVPixelBufferGetWidth(depthMap)
let height = CVPixelBufferGetHeight(depthMap)
let stride = CVPixelBufferGetBytesPerRow(depthMap) / MemoryLayout<Float>.size
let pointer = depthBase.assumingMemoryBound(to: Float.self)
var meters = [Float]()
meters.reserveCapacity(width * height)
for y in 0..<height {
let row = pointer.advanced(by: y * stride)
for x in 0..<width {
let value = row[x]
meters.append(value.isFinite && value > 0 ? value : 0)
}
}
var confidence = [UInt8](repeating: 0, count: width * height)
if let confidenceMap,
CVPixelBufferGetPixelFormatType(confidenceMap) == kCVPixelFormatType_OneComponent8,
CVPixelBufferGetWidth(confidenceMap) == width,
CVPixelBufferGetHeight(confidenceMap) == height,
CVPixelBufferLockBaseAddress(confidenceMap, .readOnly) == kCVReturnSuccess {
defer { CVPixelBufferUnlockBaseAddress(confidenceMap, .readOnly) }
if let confidenceBase = CVPixelBufferGetBaseAddress(confidenceMap) {
let confidenceStride = CVPixelBufferGetBytesPerRow(confidenceMap)
let confidencePointer = confidenceBase.assumingMemoryBound(to: UInt8.self)
for y in 0..<height {
let row = confidencePointer.advanced(by: y * confidenceStride)
for x in 0..<width {
confidence[y * width + x] = row[x]
}
}
}
}
return RuViewLiDARFrame(
intrinsics: frame.camera.intrinsics,
imageResolution: frame.camera.imageResolution,
cameraTransform: frame.camera.transform,
depthWidth: width,
depthHeight: height,
depthMeters: meters,
confidence: confidence,
sequence: 0,
timestamp: Date().timeIntervalSince1970
)
}
}
extension LiDARCaptureManager: ARSessionDelegate {
nonisolated func session(_ session: ARSession, didUpdate frame: ARFrame) {
guard let base = makeFrame(from: frame) else { return }
let frameTimestamp = frame.timestamp
Task { @MainActor in
sequence &+= 1
let corrected = base.assigningSequence(sequence)
if let previous = lastTimestamp {
let delta = frameTimestamp - previous
if delta > 0 { framesPerSecond = 1.0 / delta }
}
lastTimestamp = frameTimestamp
lastFrame = corrected
onFrame?(corrected)
}
}
nonisolated func session(_ session: ARSession, didFailWithError error: Error) {
Task { @MainActor in
state = .failed(error.localizedDescription)
}
}
}
@@ -0,0 +1,118 @@
import Foundation
import simd
struct RuViewLiDARFrame: Codable, Sendable {
struct Intrinsics: Codable, Sendable {
let fx: Float
let fy: Float
let cx: Float
let cy: Float
let imageWidth: Int
let imageHeight: Int
}
struct Pose: Codable, Sendable {
let matrix: [Float]
}
struct Depth: Codable, Sendable {
let width: Int
let height: Int
let meters: [Float]
let confidence: [UInt8]
}
struct Provenance: Codable, Sendable {
let sensor: String
let source: String
let privacyClass: String
let sequence: UInt64
let timestampNs: UInt64
let schema: String
}
let type: String
let intrinsics: Intrinsics
let pose: Pose
let depth: Depth
let provenance: Provenance
init(
intrinsics: simd_float3x3,
imageResolution: CGSize,
cameraTransform: simd_float4x4,
depthWidth: Int,
depthHeight: Int,
depthMeters: [Float],
confidence: [UInt8],
sequence: UInt64,
timestamp: TimeInterval
) {
self.type = "ruview.lidar.depth.v1"
self.intrinsics = Intrinsics(
fx: intrinsics.columns.0.x,
fy: intrinsics.columns.1.y,
cx: intrinsics.columns.2.x,
cy: intrinsics.columns.2.y,
imageWidth: Int(imageResolution.width),
imageHeight: Int(imageResolution.height)
)
self.pose = Pose(matrix: cameraTransform.columnMajorArray)
self.depth = Depth(
width: depthWidth,
height: depthHeight,
meters: depthMeters,
confidence: confidence
)
self.provenance = Provenance(
sensor: "apple-arkit-scene-depth",
source: "live",
privacyClass: "geometry-only",
sequence: sequence,
timestampNs: UInt64(max(0, timestamp) * 1_000_000_000),
schema: "ruview.lidar.depth.v1"
)
}
func assigningSequence(_ sequence: UInt64) -> RuViewLiDARFrame {
RuViewLiDARFrame(
type: type,
intrinsics: intrinsics,
pose: pose,
depth: depth,
provenance: Provenance(
sensor: provenance.sensor,
source: provenance.source,
privacyClass: provenance.privacyClass,
sequence: sequence,
timestampNs: provenance.timestampNs,
schema: provenance.schema
)
)
}
private init(
type: String,
intrinsics: Intrinsics,
pose: Pose,
depth: Depth,
provenance: Provenance
) {
self.type = type
self.intrinsics = intrinsics
self.pose = pose
self.depth = depth
self.provenance = provenance
}
}
private extension simd_float4x4 {
var columnMajorArray: [Float] {
[
columns.0.x, columns.0.y, columns.0.z, columns.0.w,
columns.1.x, columns.1.y, columns.1.z, columns.1.w,
columns.2.x, columns.2.y, columns.2.z, columns.2.w,
columns.3.x, columns.3.y, columns.3.z, columns.3.w
]
}
}
@@ -0,0 +1,10 @@
import SwiftUI
@main
struct RuViewLiDARApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
@@ -0,0 +1,93 @@
import Foundation
actor WebSocketStreamer {
enum StreamError: Error {
case invalidURL
}
struct WirePacket: Codable {
struct Depth: Codable {
let width: Int
let height: Int
let encoding: String
let millimetersBase64: String
let confidenceBase64: String
}
let type: String
let intrinsics: RuViewLiDARFrame.Intrinsics
let pose: RuViewLiDARFrame.Pose
let depth: Depth
let provenance: RuViewLiDARFrame.Provenance
}
private var task: URLSessionWebSocketTask?
private let encoder = JSONEncoder()
private var lastSentNs: UInt64 = 0
func connect(to endpoint: String) throws {
guard let url = URL(string: endpoint),
url.scheme == "ws" || url.scheme == "wss" else {
throw StreamError.invalidURL
}
task?.cancel(with: .goingAway, reason: nil)
let socket = URLSession.shared.webSocketTask(with: url)
socket.resume()
task = socket
}
func disconnect() {
task?.cancel(with: .goingAway, reason: nil)
task = nil
}
func send(_ frame: RuViewLiDARFrame, maxFPS: UInt64 = 15, sampleStep: Int = 2) async throws {
guard let task else { return }
let timestamp = frame.provenance.timestampNs
let minDelta = 1_000_000_000 / max(1, maxFPS)
guard timestamp >= lastSentNs + minDelta else { return }
lastSentNs = timestamp
let packet = Self.makeWirePacket(frame, sampleStep: max(1, sampleStep))
let data = try encoder.encode(packet)
guard let string = String(data: data, encoding: .utf8) else { return }
try await task.send(.string(string))
}
static func makeWirePacket(_ frame: RuViewLiDARFrame, sampleStep: Int) -> WirePacket {
let step = max(1, sampleStep)
let sourceWidth = frame.depth.width
let sourceHeight = frame.depth.height
let width = (sourceWidth + step - 1) / step
let height = (sourceHeight + step - 1) / step
var millimeters = Data(capacity: width * height * 2)
var confidence = Data(capacity: width * height)
for y in stride(from: 0, to: sourceHeight, by: step) {
for x in stride(from: 0, to: sourceWidth, by: step) {
let index = y * sourceWidth + x
let meters = frame.depth.meters[index]
let mm = UInt16(clamping: Int((meters * 1000).rounded()))
var littleEndian = mm.littleEndian
withUnsafeBytes(of: &littleEndian) { millimeters.append(contentsOf: $0) }
confidence.append(frame.depth.confidence[index])
}
}
return WirePacket(
type: frame.type,
intrinsics: frame.intrinsics,
pose: frame.pose,
depth: WirePacket.Depth(
width: width,
height: height,
encoding: "u16le-mm+u8-confidence",
millimetersBase64: millimeters.base64EncodedString(),
confidenceBase64: confidence.base64EncodedString()
),
provenance: frame.provenance
)
}
}
+108
View File
@@ -0,0 +1,108 @@
import { decodeLiDARPacket, depthToPointCloud } from './codec.mjs';
const canvas = document.querySelector('#view');
const ctx = canvas.getContext('2d');
const status = document.querySelector('#status');
const fpsEl = document.querySelector('#fps');
const pointsEl = document.querySelector('#points');
const seqEl = document.querySelector('#seq');
const latencyEl = document.querySelector('#latency');
const sensorEl = document.querySelector('#sensor');
let lastFrameAt = performance.now();
let yaw = 0.3;
let pitch = -0.15;
let scale = 120;
function connect() {
const token = new URLSearchParams(location.search).get('token');
if (!token) {
status.textContent = 'TOKEN REQUIRED';
status.dataset.state = 'warn';
return;
}
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const socket = new WebSocket(`${protocol}//${location.host}/ws/lidar?token=${encodeURIComponent(token)}`);
socket.addEventListener('open', () => {
status.textContent = 'LIVE';
status.dataset.state = 'live';
});
socket.addEventListener('close', () => {
status.textContent = 'RECONNECTING';
status.dataset.state = 'warn';
setTimeout(connect, 1000);
});
socket.addEventListener('message', (event) => {
try {
const raw = JSON.parse(event.data);
const frame = decodeLiDARPacket(raw);
const points = depthToPointCloud(frame, 1);
render(points);
const now = performance.now();
const delta = now - lastFrameAt;
lastFrameAt = now;
fpsEl.textContent = delta > 0 ? (1000 / delta).toFixed(1) : '0.0';
pointsEl.textContent = points.length.toLocaleString();
seqEl.textContent = frame.provenance.sequence;
latencyEl.textContent = Math.max(0, Date.now() - Number(frame.provenance.timestampNs / 1_000_000)).toFixed(0);
sensorEl.textContent = frame.provenance.sensor;
} catch (error) {
console.error(error);
status.textContent = 'FRAME ERROR';
status.dataset.state = 'warn';
}
});
}
function resize() {
const dpr = Math.min(devicePixelRatio || 1, 2);
const rect = canvas.getBoundingClientRect();
canvas.width = Math.max(1, Math.floor(rect.width * dpr));
canvas.height = Math.max(1, Math.floor(rect.height * dpr));
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
function render(points) {
resize();
const w = canvas.clientWidth;
const h = canvas.clientHeight;
ctx.clearRect(0, 0, w, h);
ctx.fillStyle = '#091018';
ctx.fillRect(0, 0, w, h);
const cy = Math.cos(yaw);
const sy = Math.sin(yaw);
const cp = Math.cos(pitch);
const sp = Math.sin(pitch);
ctx.fillStyle = '#58e0d2';
for (let i = 0; i < points.length; i += 1) {
let [x, y, z] = points[i];
const rx = x * cy - z * sy;
const rz = x * sy + z * cy;
const ry = y * cp - rz * sp;
const rz2 = y * sp + rz * cp;
const perspective = 1 / Math.max(0.35, 1.8 - rz2 * 0.12);
const px = w / 2 + rx * scale * perspective;
const py = h / 2 + ry * scale * perspective;
if (px >= 0 && px < w && py >= 0 && py < h) ctx.fillRect(px, py, 1.4, 1.4);
}
}
canvas.addEventListener('pointermove', (event) => {
if (!event.buttons) return;
yaw += event.movementX * 0.006;
pitch += event.movementY * 0.006;
});
canvas.addEventListener('wheel', (event) => {
event.preventDefault();
scale = Math.max(40, Math.min(400, scale - event.deltaY * 0.2));
}, { passive: false });
connect();
+121
View File
@@ -0,0 +1,121 @@
export function decodeLiDARPacket(packet) {
if (!packet || packet.type !== 'ruview.lidar.depth.v1') {
throw new Error('Unsupported LiDAR packet type');
}
const { depth } = packet;
if (!depth || depth.encoding !== 'u16le-mm+u8-confidence') {
throw new Error('Unsupported depth encoding');
}
assertPositiveInteger(depth.width, 'depth.width');
assertPositiveInteger(depth.height, 'depth.height');
assertIntrinsics(packet.intrinsics);
if (!packet.pose || !Array.isArray(packet.pose.matrix) || packet.pose.matrix.length !== 16
|| packet.pose.matrix.some((value) => !Number.isFinite(value))) {
throw new Error('Invalid camera pose');
}
const mmBytes = base64ToBytes(depth.millimetersBase64, 'millimetersBase64');
const confidence = base64ToBytes(depth.confidenceBase64, 'confidenceBase64');
const expectedPixels = depth.width * depth.height;
if (!Number.isSafeInteger(expectedPixels) || expectedPixels > 1_000_000) {
throw new Error('Depth dimensions exceed the supported pixel limit');
}
if (mmBytes.byteLength !== expectedPixels * 2) {
throw new Error(`Depth payload length mismatch: expected ${expectedPixels * 2}, got ${mmBytes.byteLength}`);
}
if (confidence.byteLength !== expectedPixels) {
throw new Error(`Confidence payload length mismatch: expected ${expectedPixels}, got ${confidence.byteLength}`);
}
const view = new DataView(mmBytes.buffer, mmBytes.byteOffset, mmBytes.byteLength);
const meters = new Float32Array(expectedPixels);
for (let i = 0; i < expectedPixels; i += 1) {
meters[i] = view.getUint16(i * 2, true) / 1000;
}
return {
...packet,
depth: {
width: depth.width,
height: depth.height,
meters,
confidence,
},
};
}
export function depthToPointCloud(frame, confidenceThreshold = 1) {
const { width, height, meters, confidence } = frame.depth;
const { fx, fy, cx, cy, imageWidth, imageHeight } = frame.intrinsics;
assertPositiveInteger(width, 'depth.width');
assertPositiveInteger(height, 'depth.height');
assertIntrinsics(frame.intrinsics);
if (meters.length !== width * height || confidence.length !== width * height) {
throw new Error('Decoded depth array length mismatch');
}
if (!Number.isFinite(confidenceThreshold) || confidenceThreshold < 0 || confidenceThreshold > 255) {
throw new Error('Invalid confidence threshold');
}
const sx = width / imageWidth;
const sy = height / imageHeight;
const scaledFx = fx * sx;
const scaledFy = fy * sy;
const scaledCx = cx * sx;
const scaledCy = cy * sy;
const points = [];
for (let v = 0; v < height; v += 1) {
for (let u = 0; u < width; u += 1) {
const index = v * width + u;
const z = meters[index];
if (!Number.isFinite(z) || z <= 0 || confidence[index] < confidenceThreshold) continue;
const x = ((u - scaledCx) / scaledFx) * z;
const y = ((v - scaledCy) / scaledFy) * z;
points.push([x, y === 0 ? 0 : -y, -z]);
}
}
return points;
}
function assertPositiveInteger(value, name) {
if (!Number.isSafeInteger(value) || value <= 0) {
throw new Error(`${name} must be a positive integer`);
}
}
function assertIntrinsics(intrinsics) {
if (!intrinsics
|| !Number.isFinite(intrinsics.fx) || intrinsics.fx <= 0
|| !Number.isFinite(intrinsics.fy) || intrinsics.fy <= 0
|| !Number.isFinite(intrinsics.cx)
|| !Number.isFinite(intrinsics.cy)) {
throw new Error('Invalid camera intrinsics');
}
assertPositiveInteger(intrinsics.imageWidth, 'intrinsics.imageWidth');
assertPositiveInteger(intrinsics.imageHeight, 'intrinsics.imageHeight');
}
function base64ToBytes(value, name) {
if (typeof value !== 'string' || value.length === 0 || value.length % 4 !== 0
|| !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
throw new Error(`${name} must be canonical base64`);
}
if (typeof Buffer !== 'undefined') {
return Uint8Array.from(Buffer.from(value, 'base64'));
}
const binary = atob(value);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i += 1) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
@@ -0,0 +1,69 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { decodeLiDARPacket, depthToPointCloud } from './codec.mjs';
function b64(bytes) {
return Buffer.from(bytes).toString('base64');
}
test('decodes u16 millimeter depth and confidence', () => {
const packet = {
type: 'ruview.lidar.depth.v1',
intrinsics: { fx: 100, fy: 100, cx: 1, cy: 1, imageWidth: 2, imageHeight: 2 },
pose: { matrix: Array(16).fill(0) },
depth: {
width: 2,
height: 2,
encoding: 'u16le-mm+u8-confidence',
millimetersBase64: b64([0xe8,0x03,0xd0,0x07,0xb8,0x0b,0xa0,0x0f]),
confidenceBase64: b64([2,2,1,0]),
},
provenance: { sensor: 'test', source: 'live', privacyClass: 'geometry-only', sequence: 1, timestampNs: 1, schema: 'ruview.lidar.depth.v1' },
};
const frame = decodeLiDARPacket(packet);
assert.deepEqual(Array.from(frame.depth.meters), [1,2,3,4]);
assert.deepEqual(Array.from(frame.depth.confidence), [2,2,1,0]);
});
test('rejects malformed payload length', () => {
assert.throws(() => decodeLiDARPacket({
type: 'ruview.lidar.depth.v1',
intrinsics: { fx: 100, fy: 100, cx: 1, cy: 1, imageWidth: 2, imageHeight: 2 },
pose: { matrix: Array(16).fill(0) },
depth: { width: 2, height: 2, encoding: 'u16le-mm+u8-confidence', millimetersBase64: b64([1,2]), confidenceBase64: b64([1,1,1,1]) },
}), /length mismatch/);
});
test('rejects invalid dimensions, intrinsics, pose, and base64', () => {
const valid = {
type: 'ruview.lidar.depth.v1',
intrinsics: { fx: 100, fy: 100, cx: 0, cy: 0, imageWidth: 1, imageHeight: 1 },
pose: { matrix: Array(16).fill(0) },
depth: {
width: 1,
height: 1,
encoding: 'u16le-mm+u8-confidence',
millimetersBase64: b64([0xe8, 0x03]),
confidenceBase64: b64([2]),
},
};
assert.throws(() => decodeLiDARPacket({ ...valid, depth: { ...valid.depth, width: 0 } }), /positive integer/);
assert.throws(() => decodeLiDARPacket({ ...valid, intrinsics: { ...valid.intrinsics, fx: 0 } }), /intrinsics/);
assert.throws(() => decodeLiDARPacket({ ...valid, pose: { matrix: [1] } }), /pose/);
assert.throws(() => decodeLiDARPacket({
...valid,
depth: { ...valid.depth, millimetersBase64: '!!!!' },
}), /canonical base64/);
});
test('projects depth into a point cloud and honors confidence', () => {
const frame = {
intrinsics: { fx: 100, fy: 100, cx: 0, cy: 0, imageWidth: 2, imageHeight: 2 },
depth: { width: 2, height: 2, meters: Float32Array.from([1,1,1,1]), confidence: Uint8Array.from([2,0,2,0]) },
};
const points = depthToPointCloud(frame, 1);
assert.equal(points.length, 2);
assert.deepEqual(points[0], [0, 0, -1]);
});
+36
View File
@@ -0,0 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<title>RuView iPhone LiDAR</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<header>
<div>
<p class="eyebrow">RUVIEW SENSOR BRIDGE</p>
<h1>iPhone LiDAR</h1>
</div>
<span id="status">CONNECTING</span>
</header>
<section class="metrics">
<div><strong id="fps">0.0</strong><span>FPS</span></div>
<div><strong id="points">0</strong><span>POINTS</span></div>
<div><strong id="seq">0</strong><span>SEQ</span></div>
<div><strong id="latency">0</strong><span>MS</span></div>
</section>
<canvas id="view"></canvas>
<footer>
<span>Geometry only</span>
<span>No RGB upload</span>
<span id="sensor">Waiting for sensor</span>
</footer>
</main>
<script type="module" src="./app.mjs"></script>
</body>
</html>
+39
View File
@@ -0,0 +1,39 @@
{
"name": "@ruview/iphone-lidar-web",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@ruview/iphone-lidar-web",
"version": "0.1.0",
"dependencies": {
"ws": "^8.18.3"
},
"engines": {
"node": ">=20"
}
},
"node_modules/ws": {
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
@@ -0,0 +1,16 @@
{
"name": "@ruview/iphone-lidar-web",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"start": "node relay.mjs",
"test": "node --test"
},
"engines": {
"node": ">=20"
},
"dependencies": {
"ws": "^8.18.3"
}
}
+166
View File
@@ -0,0 +1,166 @@
import { randomBytes, timingSafeEqual } from 'node:crypto';
import http from 'node:http';
import { readFile } from 'node:fs/promises';
import { extname, join } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { WebSocket, WebSocketServer } from 'ws';
const root = fileURLToPath(new URL('.', import.meta.url));
const staticFiles = new Set(['index.html', 'app.mjs', 'codec.mjs', 'styles.css']);
const maxPayloadBytes = 2_000_000;
function constantTimeEqual(left, right) {
const leftBytes = Buffer.from(left, 'utf8');
const rightBytes = Buffer.from(right, 'utf8');
return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);
}
function rejectUpgrade(socket, status, message) {
const body = `${message}\n`;
socket.end(
`HTTP/1.1 ${status}\r\nConnection: close\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`,
);
}
export function createLiDARRelay({ token, rootDirectory = root } = {}) {
const accessToken = token || randomBytes(24).toString('hex');
const clients = new Set();
const server = http.createServer(async (req, res) => {
if (req.method !== 'GET' && req.method !== 'HEAD') {
res.writeHead(405, { allow: 'GET, HEAD' }).end();
return;
}
let pathname;
try {
pathname = decodeURIComponent(new URL(req.url || '/', 'http://localhost').pathname);
} catch {
res.writeHead(400).end('bad path');
return;
}
const filename = pathname === '/' ? 'index.html' : pathname.slice(1);
if (!staticFiles.has(filename)) {
res.writeHead(404).end('not found');
return;
}
try {
const data = await readFile(join(rootDirectory, filename));
const contentType = {
'.html': 'text/html; charset=utf-8',
'.mjs': 'text/javascript; charset=utf-8',
'.css': 'text/css; charset=utf-8',
}[extname(filename)] || 'application/octet-stream';
res.writeHead(200, {
'content-type': contentType,
'cache-control': 'no-store',
'content-security-policy': "default-src 'self'; connect-src 'self' ws: wss:; img-src 'self'; style-src 'self'; base-uri 'none'; frame-ancestors 'none'",
'referrer-policy': 'no-referrer',
'x-content-type-options': 'nosniff',
});
if (req.method === 'HEAD') res.end();
else res.end(data);
} catch {
res.writeHead(404).end('not found');
}
});
const wss = new WebSocketServer({ noServer: true, maxPayload: maxPayloadBytes });
server.on('upgrade', (req, socket, head) => {
let url;
try {
url = new URL(req.url || '/', 'http://localhost');
} catch {
rejectUpgrade(socket, '400 Bad Request', 'bad websocket URL');
return;
}
if (url.pathname !== '/ws/lidar') {
rejectUpgrade(socket, '404 Not Found', 'not found');
return;
}
const suppliedToken = url.searchParams.get('token') || '';
if (!constantTimeEqual(suppliedToken, accessToken)) {
rejectUpgrade(socket, '401 Unauthorized', 'valid LiDAR relay token required');
return;
}
wss.handleUpgrade(req, socket, head, (websocket) => {
wss.emit('connection', websocket, req);
});
});
wss.on('connection', (socket) => {
clients.add(socket);
socket.on('close', () => clients.delete(socket));
socket.on('error', () => socket.terminate());
socket.on('message', (data, isBinary) => {
if (isBinary) return;
let packet;
try {
packet = JSON.parse(data.toString());
} catch {
return;
}
if (packet?.type !== 'ruview.lidar.depth.v1') return;
for (const peer of clients) {
if (peer !== socket && peer.readyState === WebSocket.OPEN) {
peer.send(data.toString());
}
}
});
});
return {
accessToken,
server,
async listen(port = 0, host = '127.0.0.1') {
await new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(port, host, () => {
server.off('error', reject);
resolve();
});
});
return server.address();
},
async close() {
for (const peer of clients) peer.terminate();
await new Promise((resolve) => wss.close(resolve));
if (server.listening) {
await new Promise((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
}
},
};
}
function configuredPort(value) {
const parsed = Number(value);
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 65_535) {
throw new Error(`PORT must be an integer from 1 to 65535; received ${value}`);
}
return parsed;
}
const directInvocation = process.argv[1]
&& pathToFileURL(process.argv[1]).href === import.meta.url;
if (directInvocation) {
const port = configuredPort(process.env.PORT || '8787');
const host = process.env.HOST || '0.0.0.0';
const relay = createLiDARRelay({ token: process.env.RUVIEW_LIDAR_TOKEN });
await relay.listen(port, host);
const encodedToken = encodeURIComponent(relay.accessToken);
console.log(`RuView iPhone LiDAR relay listening on ${host}:${port}`);
console.log(`Browser: http://<host>:${port}/?token=${encodedToken}`);
console.log(`Native endpoint: ws://<host>:${port}/ws/lidar?token=${encodedToken}`);
}
@@ -0,0 +1,73 @@
import assert from 'node:assert/strict';
import http from 'node:http';
import test from 'node:test';
import { WebSocket } from 'ws';
import { createLiDARRelay } from './relay.mjs';
function connect(url) {
return new Promise((resolve, reject) => {
const socket = new WebSocket(url);
socket.once('open', () => resolve(socket));
socket.once('error', reject);
});
}
function request(url) {
return new Promise((resolve, reject) => {
http.get(url, (response) => {
response.resume();
response.once('end', () => resolve(response));
}).once('error', reject);
});
}
test('relay requires a token, limits static files, and forwards LiDAR frames', async (t) => {
const token = 'test-token-for-relay';
const relay = createLiDARRelay({ token });
const address = await relay.listen(0, '127.0.0.1');
const httpBase = `http://127.0.0.1:${address.port}`;
const wsBase = `ws://127.0.0.1:${address.port}/ws/lidar`;
const sockets = [];
t.after(async () => {
for (const socket of sockets) socket.terminate();
await relay.close();
});
const indexResponse = await request(`${httpBase}/?token=${token}`);
assert.equal(indexResponse.statusCode, 200);
assert.match(indexResponse.headers['content-security-policy'], /frame-ancestors 'none'/);
const sourceResponse = await request(`${httpBase}/relay.mjs`);
assert.equal(sourceResponse.statusCode, 404);
await new Promise((resolve, reject) => {
const unauthorized = new WebSocket(wsBase);
unauthorized.once('unexpected-response', (_request, response) => {
assert.equal(response.statusCode, 401);
response.resume();
resolve();
});
unauthorized.once('open', () => reject(new Error('unauthorized websocket opened')));
unauthorized.once('error', () => {});
});
const sender = await connect(`${wsBase}?token=${encodeURIComponent(token)}`);
const receiver = await connect(`${wsBase}?token=${encodeURIComponent(token)}`);
sockets.push(sender, receiver);
const received = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('timed out waiting for relayed frame')), 2_000);
receiver.once('message', (data, isBinary) => {
clearTimeout(timer);
resolve({ data, isBinary });
});
});
const frame = { type: 'ruview.lidar.depth.v1', provenance: { sequence: 7 } };
sender.send(JSON.stringify(frame));
const message = await received;
assert.equal(message.isBinary, false);
assert.deepEqual(JSON.parse(message.data.toString()), frame);
});
+1
View File
@@ -0,0 +1 @@
*{box-sizing:border-box}body{margin:0;background:#05080d;color:#e8f1f5;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}main{min-height:100vh;padding:18px;display:grid;grid-template-rows:auto auto 1fr auto;gap:14px}header{display:flex;align-items:end;justify-content:space-between}h1{margin:0;font-size:clamp(28px,6vw,54px)}.eyebrow{margin:0 0 6px;color:#58e0d2;font-size:11px;letter-spacing:.16em}#status{border:1px solid #2a3946;border-radius:999px;padding:7px 11px;font-size:11px}#status[data-state=live]{color:#58e0d2;border-color:#58e0d2}.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.metrics div{background:#0b1219;border:1px solid #17222d;border-radius:10px;padding:10px}.metrics strong{display:block;font-size:18px}.metrics span,footer{font-size:10px;color:#8aa0af}canvas{width:100%;height:100%;min-height:55vh;border-radius:14px;border:1px solid #17222d;background:#091018;touch-action:none}footer{display:flex;gap:16px;flex-wrap:wrap}@media(max-width:640px){.metrics{grid-template-columns:repeat(2,1fr)}canvas{min-height:58vh}}
Generated
+13
View File
@@ -8968,6 +8968,17 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "rufield-adapters"
version = "0.1.0"
dependencies = [
"rufield-core",
"rufield-provenance",
"serde",
"serde_json",
"sha2 0.10.9",
]
[[package]]
name = "rufield-core"
version = "0.1.0"
@@ -13377,6 +13388,7 @@ version = "0.1.0"
name = "wifi-densepose-rufield"
version = "0.3.0"
dependencies = [
"rufield-adapters",
"rufield-core",
"rufield-fusion",
"rufield-privacy",
@@ -13430,6 +13442,7 @@ dependencies = [
"futures-util",
"hmac",
"jsonwebtoken",
"mdns-sd",
"midstreamer-attractor",
"midstreamer-temporal-compare",
"opentelemetry-appender-tracing",
+1 -1
View File
@@ -50,7 +50,7 @@ tower-http = { version = "0.6", features = ["fs", "trace", "cors"] }
# requires every crate that pulls reqwest to align on rustls-only (tracked in
# CHANGELOG / ADR-131 security note).
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1", features = ["derive"] }
serde = { version = "1", features = ["derive", "rc"] }
serde_yaml = "0.9"
# Concurrent fan-out of per-bank RoomState fetches in the gateway (§11 perf).
futures = "0.3"
@@ -19,6 +19,10 @@ rufield-core = { version = "0.1.0", path = "../../../vendor/rufield/crates/rufie
rufield-provenance = { version = "0.1.0", path = "../../../vendor/rufield/crates/rufield-provenance" }
rufield-privacy = { version = "0.1.0", path = "../../../vendor/rufield/crates/rufield-privacy" }
rufield-fusion = { version = "0.1.0", path = "../../../vendor/rufield/crates/rufield-fusion" }
# ADR-262 P4 second modality: UltrasonicReplayAdapter parses, validates and
# signs BatVu range profiles upstream, so RuView only has to decide what it is
# willing to put on a wire. Same pure-Rust constraint as the four above.
rufield-adapters = { version = "0.1.0", path = "../../../vendor/rufield/crates/rufield-adapters" }
serde = { workspace = true }
serde_json = { workspace = true }
@@ -145,6 +145,21 @@ pub fn snapshot_to_field_event(snap: &SensingSnapshot, signer: &Signer) -> Field
features: build_features(snap, range_m),
labels: build_labels(snap),
privacy_class: class,
// ── fields added upstream since the previous submodule pin ─────────
//
// Each empty for its own reason rather than because a default was
// convenient. `track_id`: this bridge emits per-cycle snapshots, not
// tracks, and a stable per-person identifier is exactly what §3.3
// warns about. `attributes`: nothing `features` and `labels` do not
// already carry, and an empty map is omitted from the wire.
// `identity_evidence` / `channel_sounding_provenance`: both are
// structurally BLE-only — `validate_evidence_at` rejects either on any
// other modality — so for `wifi_csi` they are not unset, they are
// unrepresentable.
track_id: None,
attributes: Default::default(),
identity_evidence: None,
channel_sounding_provenance: None,
};
// ── 3. Provenance (real sha256 over the tensor bytes) ───────────────────
@@ -166,6 +181,15 @@ pub fn snapshot_to_field_event(snap: &SensingSnapshot, signer: &Signer) -> Field
vendor: "esp32".to_string(),
device_id: snap.node_id.clone(),
placement: "unknown".to_string(),
// Optional sensor pose, added upstream. Left unset on purpose: a CSI
// link has no boresight and no surveyed position here, and §6 is
// explicit that this surface makes no validated room-coordinate claim
// (`field_localize`). A placeholder pose would be inventing exactly
// that claim. The ultrasonic path DOES set these, because a handheld
// scanner genuinely knows where it was pointing.
coordinate_frame: None,
position_m: None,
orientation_xyzw: None,
clock_domain: "local".to_string(),
};
@@ -71,12 +71,14 @@
pub mod bridge;
pub mod privacy;
pub mod snapshot;
pub mod ultrasonic;
pub use bridge::{snapshot_egress_class, snapshot_to_field_event};
pub use privacy::{apply_demotion_floor, egress_class, map_privacy};
pub use snapshot::{
RuViewPrivacyClass, SensingClass, SensingFeatures, SensingSnapshot, SignalField,
};
pub use ultrasonic::{ScanError, ScanSource, UltrasonicScan, ULTRASONIC_EGRESS_CLASS};
// Re-export the rufield surface a bridge consumer needs, so callers depend on
// one crate.
@@ -0,0 +1,233 @@
//! ADR-262 **P4, second modality**: ultrasonic range profiles on the field
//! surface.
//!
//! Until now RuView's `/api/field` and `/ws/field` have carried exactly one
//! modality — WiFi CSI, through [`crate::bridge`]. ADR-262 §4 lists multi-
//! modality as P4 and leaves the choice of the second one open (§8 question 5
//! asks whether it should be `rvcsi`, "making RuField the convergence point for
//! both vendored sensing runtimes").
//!
//! This is a different answer to that question, and the reason is that it costs
//! almost nothing: `rufield-adapters` now ships
//! [`UltrasonicReplayAdapter`](rufield_adapters::UltrasonicReplayAdapter), the
//! first adapter for `Modality::Ultrasonic` — registry code 7, which had sat in
//! the §8 registry since v0.1 with nothing implementing it. It parses, validates
//! and **signs** BatVu recordings upstream. RuView does not have to build any of
//! that; it has to decide what it is willing to put on a wire.
//!
//! # What BatVu is, in one paragraph
//!
//! [BatVu](https://github.com/ruvnet/batvu) is a handheld sonar that runs in a
//! phone browser: a 17.5–20.5 kHz chirp out of the speaker, a matched filter
//! over the microphone, and a **range profile** — echo amplitude against
//! distance along one beam. One microphone, so it measures range and infers
//! bearing only from where the operator was pointing. That asymmetry is why the
//! beam is carried as sensor *pose* rather than as an angle axis.
//!
//! # Why this module exists at all, given the adapter does the work
//!
//! Because RuView's egress rule is **stricter** than RuField's default guard,
//! and the difference has to be structural rather than a runtime refusal.
//!
//! The adapter offers two output modes. [`UltrasonicOutput::RangeProfile`] is
//! the full per-bin frame, classified `P0`, which
//! [`network_egress_allowed`](crate::network_egress_allowed) holds edge-local —
//! correctly, but *silently*, as a dropped event at the end of a pipeline that
//! did all the parsing and signing first.
//! [`UltrasonicOutput::CoarseProfile`] is a 32-bin max-pooled reduction,
//! classified `P1`, which is egress-safe.
//!
//! So this module does not offer the choice. It configures the adapter for the
//! coarse mode and says why, because a consumer cannot un-coarsen a coarse
//! profile and a policy expressed in the *shape of the data* cannot be
//! misconfigured later. The egress gate still runs — belt and braces, and it is
//! asserted by a test — but by then there is nothing left for it to catch.
//!
//! # Honesty (ADR-262 §0 / §6)
//!
//! Same posture as P1, plus one more caveat that is BatVu's rather than ours:
//!
//! 1. **Replay, not live.** A file, not a streaming phone.
//! 2. **Every current BatVu recording is its own simulator's output**, so the
//! events carry `synthetic: true` and are fusable only under
//! [`TrustPolicy::simulation`](rufield_provenance::TrustPolicy::simulation).
//! `captured_replay()` and `production()` reject them outright, as they
//! should. When a real device recording exists it declares
//! `device_capture` and this module refuses it unless the caller has asked
//! for that source explicitly — a recording cannot talk its way up a trust
//! tier by relabelling itself.
//! 3. **No accuracy is claimed.** The detections are CFAR outputs at a
//! documented false-alarm rate. That is an operating point, not validated
//! accuracy against surveyed ground truth.
//! 4. **Nothing here says a person is present.** The adapter deliberately
//! declines to populate the `presence` feature that would light up the
//! shipped `person_present` rule: one transducer pair cannot distinguish a
//! person from a coat over the back of a chair. The visible consequence is
//! that ultrasonic events currently produce no fused inferences at all, and
//! `ultrasonic_gates.rs` asserts that rather than papering over it.
//!
//! # What this does NOT do
//!
//! It does not touch the running server. P1 shipped as a library before P3
//! wired it in, and this follows the same staging: a tested translation with
//! its own gates, reviewable on its own, with the surface change as a separate
//! change once the shape is agreed. [`UltrasonicScan::egress_events`] returns
//! exactly what `FieldSurface::emit` would need to broadcast.
use rufield_adapters::{
UltrasonicConfig, UltrasonicOutput, UltrasonicReplayAdapter, UltrasonicSource,
};
use rufield_core::{FieldEvent, PrivacyClass};
use crate::network_egress_allowed;
/// Which recordings a deployment is willing to accept.
///
/// Mirrors [`UltrasonicSource`] rather than re-exporting it, so a caller does
/// not have to depend on `rufield-adapters` to make the choice — the bridge
/// stays the single coupling point (ADR-262 §5.4).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScanSource {
/// Rendered by BatVu's acoustic simulator. Events are `synthetic: true`.
/// The safe default: it cannot be mistaken for a measurement.
Simulated,
/// Captured from a real phone microphone. Events are `synthetic: false`
/// and are eligible for captured-replay trust once the sensor key is
/// enrolled.
DeviceCapture,
}
impl From<ScanSource> for UltrasonicSource {
fn from(s: ScanSource) -> Self {
match s {
ScanSource::Simulated => UltrasonicSource::Simulated,
ScanSource::DeviceCapture => UltrasonicSource::DeviceCapture,
}
}
}
/// Errors from loading a BatVu recording.
#[derive(Debug, Clone, PartialEq)]
pub enum ScanError {
/// The recording failed the adapter's parser. Carries its message, which
/// names the offending line.
Parse(String),
/// Calibration could not be established.
Calibrate(String),
}
impl std::fmt::Display for ScanError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ScanError::Parse(m) => write!(f, "ultrasonic recording rejected: {m}"),
ScanError::Calibrate(m) => write!(f, "ultrasonic calibration failed: {m}"),
}
}
}
impl std::error::Error for ScanError {}
/// A loaded BatVu scan, ready to put on the field surface.
#[derive(Debug)]
pub struct UltrasonicScan {
adapter: UltrasonicReplayAdapter,
calibration_id: String,
}
impl UltrasonicScan {
/// Load a `.ultrasonic.jsonl` recording.
///
/// `zone_id` is the room the scan was taken in and lands on every
/// observation. `accept` declares which source the deployment will take; a
/// recording declaring anything else is **refused**, in both directions, so
/// neither is a silent reinterpretation.
///
/// Calibration runs here rather than being optional. The receipt id ends up
/// on every tensor, so an event that skipped it would be one nobody could
/// later ask "under what calibration was this measured".
pub fn load(text: &str, zone_id: &str, accept: ScanSource) -> Result<Self, ScanError> {
let config = UltrasonicConfig {
accept: accept.into(),
zone_id: zone_id.to_string(),
placement: "handheld".to_string(),
// Not a caller's choice. See the module docs: the raw per-bin frame
// is P0 and would be dropped by the egress gate after all the work
// of parsing and signing it. Coarsening at the source makes the
// policy a property of the data instead of a property of a check
// somebody could later reorder.
output: UltrasonicOutput::CoarseProfile,
};
let mut adapter = UltrasonicReplayAdapter::from_jsonl_with(text, config)
.map_err(|e| ScanError::Parse(e.to_string()))?;
let receipt = adapter
.calibrate(zone_id)
.map_err(|e| ScanError::Calibrate(e.to_string()))?;
Ok(UltrasonicScan {
adapter,
calibration_id: receipt.calibration_id,
})
}
/// Pings in the recording.
#[must_use]
pub fn ping_count(&self) -> usize {
self.adapter.ping_count()
}
/// The sensor identity the whole recording belongs to.
///
/// This is the key RuField's replay watermark and trust registry are both
/// keyed on, so it has to be stable across scans — the adapter refuses a
/// recording whose device changes midway.
#[must_use]
pub fn device_id(&self) -> &str {
self.adapter.device_id()
}
/// The calibration receipt every tensor in this scan cites.
#[must_use]
pub fn calibration_id(&self) -> &str {
&self.calibration_id
}
/// Every event in the recording, signed and validated by the adapter.
///
/// Includes events that the egress gate would refuse. Use this for an
/// edge-local consumer; use [`egress_events`](Self::egress_events) for
/// anything that reaches a network.
pub fn events(&mut self) -> Result<Vec<FieldEvent>, ScanError> {
self.adapter
.collect_events()
.map_err(|e| ScanError::Parse(e.to_string()))
}
/// Only the events RuView will put on the wire.
///
/// Runs the same [`network_egress_allowed`] gate the CSI path runs, with
/// `identity_bound: false` — an ultrasonic scan has no identity to bind, and
/// hard-coding it rather than plumbing a flag means there is no argument a
/// caller can pass that turns the P4/P5 consent exception on. There is no
/// consent story for a room scan.
///
/// In the coarse mode configured by [`load`](Self::load) this should drop
/// nothing, and `coarse_scan_passes_the_egress_gate_intact` asserts it. The
/// gate stays because a policy that is only enforced where it never fires
/// is a policy nobody notices removing.
pub fn egress_events(&mut self) -> Result<Vec<FieldEvent>, ScanError> {
Ok(self
.events()?
.into_iter()
.filter(|e| network_egress_allowed(e.observation.privacy_class, false))
.filter(|e| network_egress_allowed(e.tensor.privacy_class, false))
.collect())
}
}
/// The privacy class every event from [`UltrasonicScan`] carries.
///
/// `P1` — a derived non-identity feature. Stated as a constant so a test can
/// pin it: if the adapter's default output mode ever changes upstream, that is
/// a submodule bump which silently moves data from edge-local to network-eligible
/// or back, and it should fail a build here rather than change behaviour in a
/// deployment.
pub const ULTRASONIC_EGRESS_CLASS: PrivacyClass = PrivacyClass::P1;
@@ -0,0 +1,72 @@
{"timestamp":1756162800,"source":"simulated","device_id":"batvu-reference-01","beam":[0,-0.9063078,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000181,0.0000199,0.0000296,0.0000423,0.0000753,0.0000649,0.0000353,0.0000546,0.0000678,0.0000341,0.0000214,0.0000261,0.0000025,0,0.0000408,0.0000561,0.0000694,0.000075,0.0000335,0.0000171,0.0000264,0.0000162,0.0000437,0.0000641,0.0000422,0.0000274,0.0000622,0.0000561,0.0000389,0.0000256,0.0000256,0.0000336,0.0000499,0.0000442,0.000032,0.0000312,0.000026,1e-7,0.0000226,0.0000252,0.0000028,0.0000261,0.0000394,0.0000286,0.0000096,0.0000236,0.0000383,0.0000509,0.0000553,0.0000331,0.0000366,0.0000671,0.0000645,0.0000557,0.0000436,0.0000296,0.000048,0.0000668,0.000063,0.0000546,0.0000595,0.0000492,0.0000152,0.0000373,0.0000449,0.0000455,0.0000443,0.0000361,0,0,0.0000078,0.0000151,0.0000314,0.000043,0.0000475,0.0000642,0.0000715,0.0000608,0.0000681,0.0000857,0.0000821,0.000071,0.0000648,0.0000468,0.000028,0.0000339,0.0000276,0.0000145,0.0000421,0.0000414,0.0000401,0.0000571,0.0000586,0.000055,0.0000516,0.0000447,0.0000028,0.0000136,0.0000216,0.0000224,0.0000319,0.000039,0.0000351,0.0000387,0.0000407,0.0000267,0.0000305,0.0000395,0.0000837,0.0002284,0.0005318,0.0008717,0.0012896,0.0017333,0.0021146,0.0023917,0.002502,0.0024966,0.0022837,0.0019285,0.0014871,0.0010271,0.0006496,0.0003871,0.0002045,0.0001008,0.000048,0.0000215,0.0000333,0.000042,0.0000393,0.0000339,0.0000273,0.0000061,0.0000087,0.0000163,0.0000142,0.000024,0.0000383,0.0000374,0.0000325,0.0000312,0.0000253,0.000021,0.000034,0.0000338,0.0000267,0.0000299,0.0000287,0.0000189,0.0000248,0.0000286,0.0000259,0.0000201,0.0000126,0.0000194,0.000028,0.0000307,0.0000208,0.0000246,0.0000386,0.0000424,0.0000538,0.0000652,0.0000682,0.000071,0.0000711,0.0000604,0.0000396,0.0000518,0.0000507,0.0000421,0.0000445,0.0000523,0.0000613,0.0000637,0.0000625,0.000031,0.0000224,0.0000334,0.0000361,0.000036,0.0000328,0.0000176,0.0000346,0.0000436,0.0000489,0.0000621,0.0000721,0.0000706,0.0000654,0.0000587,0.0000371,0.0000126,0.0000276,0.0000282,0.0000264,0.0000287,0.0000309,0.0000343,0.0000343,0.0000291,0.0000099,0.0000091,0.0000197,0.00004,0.0000807,0.0001038,0.0001159,0.0001184,0.0001168,0.0000931,0.000065,0.0000468,0.0000272,0.0000153,0.0000089,0.0000039,0.0000154,0.0000304,0.0000358,0.0000466,0.0000534,0.0000501,0.0000388,0.0000299,0.000022,0.0000039,0.000011,0.0000115,0.0000082,0.0000154,0.0000285,0.0000404,0.0000538,0.0000608,0.0000715,0.0000906,0.0001001,0.0000993],"detections":[{"range_m":2.738708,"snr_db":27.6382,"width_m":0.171607}],"noise_floor":0.000035574,"blast_amplitude":0.2699276,"saturated":false}
{"timestamp":1756162800.0666666,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.2345697,-0.8754261,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000015,0.0000089,0,0,0.000089,0.0000914,0.0000789,0.0000676,0.0000659,0.0000243,0.0000868,0.0001153,0.000114,0.0001099,0.000106,0.0000423,0.0000332,0.0000434,0.0000195,0.0000231,0.0000387,0.0000207,0.0000158,0.0000348,0.0000244,0.000021,0.0000282,0.0000132,0.0000135,0.0000372,0.0000279,0.0000311,0.0000595,0.0000549,0.000041,0.0000647,0.0000696,0.0000486,0.0000368,0.0000261,0,0.000009,0.0000247,0.0000214,0.0000195,0.0000208,3e-7,0.0000031,0.0000266,0.0000293,0.0000309,0.0000322,0.0000096,0.0000074,0.0000165,0.0000075,0,0.000014,0.0000135,0.0000094,0.0000145,0.0000164,0.0000259,0.0000441,0.0000457,0.000042,0.0000543,0.0000535,0.00003,0.0000227,0.0000283,0.0000249,0.0000316,0.0000368,0.0000249,0.0000226,0.0000224,0.0000139,0.0000704,0.0001232,0.0001372,0.0001373,0.0001306,0.0001013,0.0000682,0.0000659,0.0000625,0.0000553,0.0000557,0.0000444,0.0000153,0.0000205,0.0000213,0.0000153,0.0000236,0.0000257,0.0000023,0.0000282,0.0000495,0.000053,0.0000524,0.0000455,0.0000169,0.0000103,0.0000215,0.0000288,0.0000394,0.0000453,0.0000356,0.0000184,0.0000387,0.0001307,0.000308,0.0005791,0.000915,0.0013178,0.001738,0.0021372,0.0023362,0.0023766,0.002347,0.0021355,0.0017912,0.0013838,0.0009609,0.0006085,0.0003179,0.0001483,0.0000463,0.0000625,0.0000754,0.0000766,0.000074,0.0000525,0.0000623,0.0000756,0.0000733,0.0000667,0.0000621,0.0000499,0.0000173,0.0000342,0.0000408,0.0000422,0.000045,0.0000433,0.0000375,0.0000514,0.0000515,0.0000467,0.0000439,0.0000416,0.0000231,0.0000308,0.0000393,0.0000365,0.0000301,0.0000232,0.0000115,0.0000125,0.0000128,0.0000031,0.0000106,0.0000192,0.0000168,0.0000104,0.0000114,0.000015,0.0000168,0.0000167,0.0000096,0.0000121,0.0000199,0.0000185,0.0000086,0.000019,0.0000235,0.0000232,0.0000212,0.0000162,0,0,0.0000065,0.0000182,0.0000374,0.0000434,0.0000399,0.0000356,0.0000352,0.0000236,0.0000175,0.000039,0.0000387,0.0000281,0.0000186,0.0000464,0.0000682,0.0000816,0.0000806,0.00007,0.0000621,0.0000568,0.0000361,0.0000274,0.0000427,0.0000524,0.0000542,0.0000517,0.0000304,0.000031,0.0000406,0.0000476,0.0000588,0.0000662,0.0000636,0.0000658,0.0000712,0.0000694,0.0000719,0.0000738,0.0000683,0.0000537,0.0000446,0.000036,0.0000185,0.000034,0.0000521,0.0000737,0.0001029,0.0001097,0.0001134,0.0001164,0.0001167,0.0001012,0.0000801,0.000053,0.0000265,0.000049,0.0000546,0.0000478],"detections":[{"range_m":2.789841,"snr_db":24.6641,"width_m":0.175182}],"noise_floor":0.000036094,"blast_amplitude":0.2699713,"saturated":false}
{"timestamp":1756162800.1333332,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.4531539,-0.7848856,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000107,0.0000092,0.0000054,0.0000319,0.0000529,0.0000336,0.0000449,0.0000597,0.0000454,0.0000401,0.000043,0,0,0.0000292,0.0000302,0.0000299,0.0000274,0,0,0.000014,8e-7,0,0.0000325,0.000039,0.0000403,0.0000393,0.0000075,0.0000057,0.0000261,0.0000191,0.0000126,0.0000664,0.000079,0.000078,0.0000689,0.0000493,0,0.0000153,0.000019,0,0.0000342,0.0000674,0.0000892,0.0001157,0.0001282,0.0001137,0.0001122,0.0001335,0.0001255,0.0001118,0.0000959,0.0000562,0.0000098,0.000025,0.0000228,0.0000331,0.0000731,0.0000778,0.0000782,0.0000753,0.0000614,0.0000131,0.0000275,0.0000358,0.0000444,0.0000561,0.0000588,0.000043,0.000052,0.0000589,0.0000449,0.0000388,0.0000413,0.0000237,0.0000217,0.0000372,0.0000333,0.0000229,0.0000342,0.0000412,0.0000566,0.0000728,0.0000704,0.0000707,0.0000838,0.0000782,0.0000584,0.0000621,0.0000617,0.0000469,0.0000328,0.0000216,0.0000049,0.0000102,0.0000112,0,0.0000096,0.0000256,0.0000288,0.0000363,0.0000415,0.0000355,0.0000397,0.0000463,0.0000396,0.0000304,0.0000322,0.0000244,0.0000394,0.0000893,0.000175,0.0003531,0.0006367,0.0010626,0.0014721,0.0018693,0.0021585,0.0023104,0.0023256,0.0022716,0.0020312,0.0016707,0.0011803,0.0007773,0.0004581,0.0002469,0.000115,0.0000542,0.0000392,0.0000269,0.0000174,0.0000149,0.000013,0.0000306,0.000053,0.0000531,0.0000464,0.0000314,0.0000103,0.0000248,0.0000304,0.0000274,0.0000101,0.0000289,0.0000291,0.0000235,0.0000273,0.0000287,0.000017,0.0000193,0.0000246,0.0000178,0.0000099,0.0000147,0.0000209,0.0000316,0.0000399,0.0000377,0.0000526,0.0000684,0.0000689,0.0000678,0.0000634,0.000051,0.0000343,0.0000511,0.0000521,0.0000523,0.0000521,0.0000483,0.0000339,0.0000492,0.0000545,0.0000544,0.0000532,0.0000516,0.0000331,0.0000192,0.000009,0.0000197,0.0000524,0.0000672,0.0000673,0.0000621,0.000049,0.0000233,0.0000015,0.0000075,0.0000162,0.0000336,0.0000514,0.0000519,0.0000516,0.0000505,0.0000463,0.0000303,0.0000298,0.0000294,0.0000366,0.0000527,0.0000569,0.0000561,0.0000535,0.000047,0.0000228,0.0000187,0.0000312,0.0000341,0.0000399,0.0000501,0.0000566,0.0000621,0.0000627,0.0000511,0.0000294,0.0000211,0.0000385,0.000067,0.0000843,0.0000838,0.0000753,0.0000635,0.0000583,0.000073,0.0000972,0.0000997,0.0001034,0.000113,0.0001155,0.0001154,0.0001202,0.0001221,0.000113,0.000096,0.0000862,0.0000761],"detections":[{"range_m":2.839001,"snr_db":26.9682,"width_m":0.171607}],"noise_floor":0.000039797,"blast_amplitude":0.2699136,"saturated":false}
{"timestamp":1756162800.1999998,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.6408564,-0.6408564,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000059,0.000016,0.0000391,0.0000304,0.0000275,0.0000405,0.000048,0.0000092,0.0000051,0.0000066,0,0.0000055,0.0000304,0.0000319,0.0000407,0.0000451,3e-7,0.0000369,0.0000846,0.0000844,0.0000774,0.0000648,0.0000099,0,0.00002,0.0000104,0,0.0000102,0.0000085,2e-7,0.0000284,0.0000443,0.000056,0.0000602,0.000058,0.0000048,0.0000181,0.0000194,0,0.0000252,0.0000429,0.0000409,0.0000365,0.0000312,0,0.0000189,0.0000338,0.0000216,0.0000338,0.0000826,0.000098,0.0001114,0.0001178,0.0001017,0.0000797,0.0000945,0.0000892,0.0000525,0.0000229,0.0000059,0.0000072,0.0000175,0.0000204,0.000022,0.0000273,0.0000273,0.0000273,0.0000342,0.0000354,0.0000102,0.0000249,0.0000448,0.0000448,0.0000432,0.000039,0.0000135,0.0000305,0.0000573,0.0000639,0.0000747,0.0000839,0.000077,0.0000657,0.0000614,0.0000493,0.0000233,0.0000468,0.0000464,0.000045,0.0000457,0.0000426,0.0000261,0.0000548,0.0000645,0.0000598,0.0000451,0.0000241,0.0000105,0.0000201,0.0000226,0.0000128,0.0000289,0.0000381,0.0000341,0.0000409,0.0000601,0.0000702,0.0000791,0.0000799,0.0000692,0.0001842,0.0004023,0.000701,0.0011004,0.0015592,0.0020509,0.0023468,0.0024764,0.0024758,0.002352,0.0020757,0.0017056,0.0012796,0.0008843,0.0005136,0.0002869,0.0001566,0.0000978,0.0000556,0.000042,0.0000503,0.0000451,0.0000501,0.0000558,0.0000467,0.0000262,0.0000108,0.0000227,0.0000289,0.0000303,0.0000224,0.0000043,0.0000173,0.0000172,0.0000087,0.0000096,0.0000207,0.0000358,0.0000543,0.000058,0.0000518,0.0000429,0.0000407,0.0000408,0.0000493,0.0000521,0.0000413,0.0000354,0.0000405,0.0000344,0.0000235,0.0000409,0.0000549,0.0000699,0.0000794,0.0000756,0.0000604,0.0000456,0.0000257,0.0000083,0.0000085,0.0000142,0.0000285,0.0000431,0.0000453,0.000032,0.0000254,0.0000276,0.0000318,0.0000433,0.0000512,0.0000554,0.0000614,0.0000619,0.0000464,0.0000273,0.0000166,0.0000114,0.0000275,0.0000437,0.0000424,0.0000355,0.0000273,0.000019,0.0000143,0.0000168,0.0000146,0.000001,0.0000028,0.0000024,0,0.0000174,0.0000235,0.0000234,0.0000203,0.0000184,0.0000159,0.0000256,0.0000324,0.000037,0.0000502,0.0000657,0.0000689,0.0000689,0.0000647,0.0000445,0.0000181,0.0000122,0.0000264,0.0000448,0.0000553,0.0000538,0.0000478,0.0000516,0.0000509,0.0000509,0.0000625,0.0000625,0.0000623,0.0000666,0.0000674,0.0000574,0.0000558,0.0000597,0.0000654,0.0000764,0.0000807,0.0000761],"detections":[{"range_m":2.797382,"snr_db":24.5471,"width_m":0.175182}],"noise_floor":0.000036665,"blast_amplitude":0.2699939,"saturated":false}
{"timestamp":1756162800.2666664,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7848856,-0.4531539,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000405,0.0000231,0.0000103,0.0000028,0.0000041,0.0000017,0,0.0000034,0.0000293,0.0000222,0.0000178,0.0000242,0.0000077,0,0.0000552,0.000076,0.0000849,0.0000848,0.0000213,0,0.0000214,0.000009,0,0.0000174,0.0000185,0.0000219,0.0000331,0.00002,0.0000323,0.0000675,0.0000642,0.0000616,0.0000635,0.0000518,0.0000168,0.0000491,0.0000584,0.000075,0.0001006,0.0001033,0.0000741,0.0000642,0.0000677,0.0000406,0.0000064,0.0000445,0.0000639,0.0000773,0.0000807,0.000053,0.000022,0.0000346,0.0000334,0.0000402,0.0000523,0.0000466,0.0000554,0.0000668,0.0000606,0.0000492,0.0000742,0.000072,0.0000618,0.0000683,0.0000684,0.0000527,0.0000467,0.0000431,0.0000118,0.000024,0.0000317,0.0000222,0.0000089,0.000025,0.0000304,0.0000314,0.0000312,0.0000105,0.0000197,0.0000338,0.0000299,0.0000422,0.000056,0.0000502,0.0000317,0.0000157,0.0000346,0.0000485,0.0000514,0.0000372,7e-7,0.0000405,0.0000515,0.0000675,0.0000931,0.0000997,0.0000903,0.0000864,0.000088,0.0000721,0.0000858,0.0001071,0.0001094,0.0001033,0.0000795,0.0001798,0.0003957,0.0007041,0.0010949,0.0015653,0.0021246,0.002463,0.0026268,0.0026347,0.0025376,0.0022396,0.0018326,0.0013884,0.0008683,0.0005239,0.0002748,0.0001002,0.0000493,0.0000559,0.0000494,0.0000388,0.0000329,0.0000086,0.0000336,0.0000601,0.0000669,0.0000671,0.0000633,0.000037,0.0000306,0.0000409,0.000038,0.0000391,0.0000605,0.0000635,0.0000623,0.0000514,0.0000224,0.000021,0.0000405,0.00004,0.0000279,0.0000247,0.0000227,0.0000077,0,0.0000012,0.0000069,0.0000337,0.0000526,0.0000531,0.0000503,0.000042,0.0000182,0.000005,0.0000157,0.0000158,0.0000158,0.0000166,0.0000098,0.0000129,0.0000215,0.0000201,0.0000246,0.0000409,0.0000407,0.0000443,0.0000547,0.0000545,0.0000509,0.0000552,0.0000573,0.0000645,0.0000759,0.000078,0.0000703,0.0000651,0.0000619,0.0000409,0.0000154,0.0000106,0.0000115,0.0000111,0.0000148,0.0000149,0.0000265,0.0000444,0.0000451,0.0000443,0.0000406,0.0000312,0.0000191,0.0000212,0.0000204,0.0000229,0.0000319,0.0000311,0.0000224,0.0000142,0.0000099,0.0000075,0.0000259,0.0000382,0.0000448,0.0000464,0.0000463,0.0000392,0.0000515,0.0000587,0.0000527,0.0000476,0.000058,0.0000638,0.0000718,0.0000799,0.0000789,0.0000866,0.0001,0.0001043,0.0001094,0.0001105,0.0001067,0.000087,0.0000742,0.0000669,0.000048,0.00003,0.0000198,0.0000291,0.0000408,0.0000454,0.0000567,0.0000821,0.0001006,0.0001033],"detections":[{"range_m":2.672119,"snr_db":22.7478,"width_m":0.171607}],"noise_floor":0.000041468,"blast_amplitude":0.2700291,"saturated":false}
{"timestamp":1756162800.333333,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8754261,-0.2345697,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000563,0.0000578,0.000044,0.0000295,0.0000313,0.0000237,0.0000392,0.0000435,0.0000057,0.0000116,0.0000399,0.0000364,0.0000344,0.0000486,0.0000576,0.0000779,0.0000925,0.0000674,0.0000542,0.0000651,0.0000383,0.0000125,0.0000111,0.0000016,0.0000089,0.0000346,0.0000246,0.0000092,0.000031,0.0000265,0.0000068,0.0000284,0.0000578,0.0000677,0.0000727,0.0000714,0.0000348,0.0000561,0.0000682,0.0000589,0.0000535,0.0000532,0.0000168,0.0000267,0.000047,0.000042,0.0000348,0.0000347,0.0000202,0.0000217,0.000032,0.0000242,0.0000148,0.000015,0.0000071,0.0000178,0.0000556,0.0000605,0.000065,0.0000685,0.0000656,0.0000385,0.0000675,0.0000707,0.000062,0.0000498,0.0000368,0.000009,0.0000328,0.0000477,0.0000429,0.0000371,0.000034,0.0000297,0.0000481,0.0000615,0.0000564,0.0000707,0.0000894,0.0000869,0.0000808,0.0000763,0.000063,0.0000368,0.0000444,0.0000401,0.0000356,0.0000795,0.0000975,0.0000997,0.0000947,0.0000684,0.0000912,0.0002457,0.0004662,0.0007986,0.0012554,0.0017706,0.0023533,0.0027192,0.0028794,0.0028824,0.0027701,0.0024729,0.0020279,0.0015114,0.0010175,0.00052,0.0002222,0.000065,0.0000863,0.0000996,0.0001088,0.0001068,0.0000827,0.0000711,0.0000641,0.0000403,0.0000384,0.0000432,0.0000479,0.0000577,0.0000593,0.0000454,0.0000503,0.0000573,0.000053,0.0000465,0.0000514,0.0000549,0.0000641,0.0000689,0.0000602,0.000047,0.000045,0.0000391,0.000028,0.0000362,0.0000343,0.0000454,0.0000655,0.0000661,0.0000587,0.0000501,0.000041,0.0000286,0.0000529,0.00006,0.0000573,0.0000437,0.0000246,0.0000126,0.0000164,0.0000186,0.0000248,0.0000374,0.0000438,0.0000384,0.0000447,0.0000603,0.0000658,0.0000725,0.0000761,0.0000697,0.000049,0.0000314,0.0000226,0.0000425,0.0000716,0.0000842,0.0000954,0.0001046,0.000106,0.0000927,0.0000948,0.0000963,0.0000852,0.0000725,0.0000603,0.0000365,0.0000238,0.00003,0.0000386,0.0000583,0.0000731,0.0000728,0.000066,0.0000526,0.0000244,0.0000032,0.0000131,0.0000125,0.0000099,0.0000096,0.0000157,0.0000293,0.0000395,0.0000385,0.0000307,0.0000378,0.00004,0.0000339,0.000025,0.0000235,0.00004,0.0000513,0.0000523,0.0000356,0.0000105,0.0000268,0.0000342,0.0000393,0.0000406,0.0000318,0.000021,0.0000292,0.0000277,0.0000204,0.0000139,0.0000089,1e-7,0.0000082,0.0000079,0.0000019,0.0000208,0.0000284,0.0000374,0.0000503,0.0000549,0.000062,0.0000767,0.0000841,0.0000841,0.0000893,0.0000932,0.0000916],"detections":[{"range_m":2.523483,"snr_db":23.0173,"width_m":0.171607}],"noise_floor":0.000043196,"blast_amplitude":0.2700235,"saturated":false}
{"timestamp":1756162800.3999996,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.9063078,0,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000048,0.0000161,0.000028,0.0000519,0.0000378,0,0.0000459,0.0000792,0.0000638,0.0000399,0.000042,0.000055,0.0000621,0.0000623,0,0.0000502,0.0000767,0.0000709,0.0000859,0.0001049,0.0000837,0.0000495,0.000024,0.0000267,0.0000541,0.0000746,0.0000596,0.0000723,0.0001127,0.00011,0.0001169,0.0001289,0.0001188,0.0000697,0.0000364,0.0000378,0.0000422,0.0000699,0.0000751,0.0000653,0.0000665,0.0000672,0.0000293,0.0000143,0.0000262,0.0000211,0.0000262,0.0000396,0.0000346,0.0000328,0.0000309,4e-7,0,0.0000042,1e-7,0.0000065,0.0000157,0.0000111,0.0000163,0.0000382,0.0000353,0.0000326,0.0000596,0.0000626,0.0000527,0.0000405,0.0000312,0.0000024,0.000028,0.0000385,0.0000349,0.0000275,0.0000204,0.0000166,0.0000351,0.0000491,0.0000545,0.0000708,0.0000835,0.0000768,0.0000564,0.0000403,0.0000109,0.0000141,0.000032,0.0000305,0.0000373,0.0000502,0.0000453,0.000046,0.0000766,0.000081,0.0001334,0.0003069,0.0006491,0.0010525,0.0015427,0.0020397,0.0024858,0.0028079,0.0029123,0.0029008,0.0026483,0.0022399,0.00172,0.0012037,0.0007759,0.0004453,0.0002076,0.0000613,0.0000752,0.000095,0.0001005,0.000092,0.000069,0.0000682,0.0000662,0.000039,0.0000157,0.0000122,0.0000193,0.0000268,0.0000288,0.0000189,0.0000412,0.0000547,0.000057,0.0000564,0.0000521,0.0000454,0.0000743,0.000104,0.0001103,0.0001111,0.0001091,0.0000872,0.0000564,0.0000387,0.000025,0.000005,0.0000037,0,0.0000038,0.0000272,0.0000302,0.0000299,0.0000319,0.0000381,0.0000669,0.0001117,0.0001414,0.0001557,0.0001576,0.000154,0.0001145,0.0000837,0.0000751,0.0000674,0.0000631,0.0000616,0.0000484,0.0000346,0.0000424,0.0000396,0.0000307,0.0000206,0.0000125,0.0000246,0.0000537,0.0000647,0.0000735,0.0000819,0.0000812,0.0000787,0.0000817,0.000082,0.0000618,0.000051,0.0000445,0.0000211,0.0000049,0.0000097,0.0000197,0.0000432,0.0000555,0.0000571,0.0000571,0.0000553,0.0000398,0.0000192,0.0000134,0.0000209,0.0000413,0.0000648,0.0000689,0.0000689,0.0000648,0.0000532,0.0000339,0.0000425,0.000041,0.0000256,0.0000132,0.0000168,0.0000164,0.0000119,0.0000071,0.0000108,0.0000175,0.0000276,0.000037,0.0000439,0.0000448,0.0000303,0.000027,0.0000406,0.0000435,0.0000468,0.0000507,0.0000472,0.0000387,0.0000327,0.000024,0.0000107,0.0000071,0.0000048,0,0.0000128,0.0000143,0.0000247,0.0000423,0.0000466,0.000045,0.0000394,0.0000357,0.0000269,0.000035,0.0000458,0.0000541],"detections":[{"range_m":2.461116,"snr_db":25.0505,"width_m":0.171607}],"noise_floor":0.000041282,"blast_amplitude":0.2699688,"saturated":false}
{"timestamp":1756162800.4666662,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8754261,0.2345697,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0001007,0.0000987,0.0000863,0.0000664,0.0000462,0.0000233,0.000014,0.0000355,0.0000505,0.0000225,0.0000574,0.0000811,0.0000748,0.0000674,0.0000721,0.0000359,0.0000279,0.0000252,0,0,0.0000171,0.0000287,0.0000334,0.0000335,0,0,0.0000156,0.0000138,0.0000228,0.0000401,0.0000254,0.0000021,0.0000262,0.0000278,0.000028,0.0000266,0.0000229,0.0000187,0.0000321,0.0000328,0.0000129,0.0000322,0.0000392,0.000023,0.0000597,0.0000762,0.0000726,0.0000639,0.0000518,0.0000103,0.0000154,0.0000309,0.0000185,0.0000383,0.0000663,0.0000626,0.0000502,0.0000658,0.0000714,0.0000785,0.0000822,0.0000719,0.0000444,0.0000501,0.0000493,0.0000259,0.0000577,0.0000703,0.0000764,0.0000806,0.0000814,0.0000564,0.000048,0.0000512,0.0000283,0.0000093,0.0000202,0.0000317,0.000041,0.0000445,0.0000293,0.000005,0.0000072,0.0000016,0,0.0000518,0.0001501,0.0003633,0.0007963,0.0012585,0.0017948,0.0023257,0.0027246,0.0029443,0.0029718,0.0029149,0.0025351,0.0020552,0.0015256,0.0010027,0.0005828,0.0002979,0.0001144,0.0000195,0.000023,0.0000117,0.0000076,0.0000454,0.0000672,0.0000908,0.0001135,0.0001143,0.0001181,0.0001189,0.000107,0.0000708,0.0000399,0.0000183,0.0000111,0.000021,0.0000201,0.0000156,0.0000345,0.0000428,0.0000455,0.0000506,0.0000517,0.0000375,0.0000402,0.0000447,0.0000351,0.0000199,0.0000275,0.0000462,0.0000667,0.0000795,0.0000783,0.000089,0.0001034,0.0001022,0.0000989,0.0001091,0.000108,0.0001048,0.0001032,0.0000984,0.0000762,0.0000626,0.0000538,0.0000339,0.0000272,0.0000286,0.0000185,0.0000298,0.0000573,0.0000733,0.0000842,0.0000869,0.0000755,0.0000655,0.0000631,0.0000504,0.0000307,0.0000195,0.0000106,0.0000035,0.0000053,7e-7,0.0000022,0.000021,0.0000362,0.0000724,0.0001204,0.0001428,0.0001485,0.0001474,0.0001341,0.0000883,0.0000644,0.0000613,0.0000497,0.0000403,0.0000339,0.0000185,0.0000276,0.0000417,0.0000463,0.0000475,0.0000473,0.0000359,0.0000257,0.0000362,0.0000353,0.0000325,0.0000273,0.0000146,0,0.0000145,0.0000239,0.0000357,0.0000405,0.0000381,0.0000219,0.0000202,0.0000221,0.0000185,0.000024,0.0000252,0.0000157,0.0000086,0.0000049,0.0000092,0.0000199,0.0000264,0.0000215,0.0000203,0.0000301,0.0000359,0.0000443,0.000051,0.0000483,0.000044,0.0000488,0.0000451,0.0000321,0.0000288,0.0000343,0.0000425,0.0000535,0.0000531,0.0000524,0.0000588,0.0000601,0.0000501,0.0000384,0.0000284,0.0000297,0.0000517,0.0000616,0.0000608],"detections":[{"range_m":2.325592,"snr_db":24.8955,"width_m":0.171607}],"noise_floor":0.000040942,"blast_amplitude":0.2700495,"saturated":false}
{"timestamp":1756162800.5333328,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7848856,0.4531539,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000015,0,4e-7,0.0000093,0.0000231,0.0000069,0,0,0.000029,0.0000325,0.0000378,0.0000391,0,0.0000227,0.0000617,0.0000691,0.0000763,0.0000785,0.0000259,0.0000252,0.0000582,0.0000476,0.0000217,0.0000349,0.0000511,0.0000657,0.000074,0.000052,0.0000216,0.0000521,0.0000434,0.0000286,0.0000362,0.0000344,0.000063,0.0001062,0.0001126,0.0000889,0.0000725,0.0000611,0.0000074,0.0000146,0.0000344,0.0000323,0.0000211,0.0000245,0.0000323,0.0000386,0.0000396,0.0000091,0,0.0000081,0,0.0000106,0.0000498,0.0000529,0.0000527,0.000049,0.0000318,0,0.0000018,0,0,0.000023,0.0000426,0.0000644,0.0000845,0.000085,0.0000693,0.0000757,0.0000774,0.0000475,0.0000147,0.0000487,0.0000679,0.0000868,0.0000938,0.0000795,0.000057,0.0000913,0.0002564,0.0005318,0.0009276,0.0014055,0.0019416,0.0024494,0.0028096,0.0029862,0.0029954,0.0028453,0.0024681,0.0019665,0.0014301,0.0009187,0.0005256,0.0002656,0.0000589,0.0000545,0.0000766,0.000077,0.0000729,0.0000626,0.0000304,0.0000129,0.0000177,0.0000125,0.0000446,0.000079,0.0000853,0.000085,0.0000749,0.0000339,0.0000344,0.0000609,0.0000604,0.0000557,0.0000569,0.0000539,0.000036,0.0000662,0.0000709,0.0000701,0.0000639,0.0000576,0.000037,0.000047,0.0000508,0.0000453,0.0000425,0.0000465,0.0000493,0.0000676,0.0000832,0.000082,0.0000822,0.0000871,0.0000816,0.0000739,0.0000677,0.0000517,0.0000213,0.000025,0.0000242,0.0000216,0.0000202,0.0000173,0.0000095,0.0000373,0.0000395,0.0000371,0.000026,0.0000086,0.0000214,0.0000265,0.0000265,0.000011,0.0000218,0.0000258,0.0000168,0.0000087,0.0000177,0.0000209,0.0000267,0.000029,0.0000198,0.0000125,0.0000313,0.0000368,0.0000413,0.0000451,0.0000406,0.0000397,0.0000496,0.0000486,0.0000389,0.0000423,0.0000446,0.0000411,0.0000408,0.0000394,0.0000177,0.0000283,0.00005,0.0000625,0.000075,0.0000782,0.0000701,0.0000626,0.0000627,0.000055,0.0000497,0.0000589,0.0000613,0.0000727,0.0000828,0.0000798,0.0000632,0.000042,0.00004,0.0000668,0.000085,0.000085,0.0000773,0.0000679,0.0000568,0.0000269,0.0000254,0.0000333,0.0000333,0.0000335,0.0000354,0.0000279,0.0000178,0.0000081,0.0000022,0.0000017,0.0000136,0.000025,0.0000351,0.0000405,0.0000367,0.0000301,0.0000359,0.0000327,0.0000211,0.0000246,0.0000295,0.0000304,0.0000292,0.0000183,0,0.0000065,0.0000077,0.0000039,0.0000126,0.0000166,0.0000163,0.0000313,0.0000417,0.0000426],"detections":[{"range_m":2.211216,"snr_db":24.445,"width_m":0.175182}],"noise_floor":0.000037341,"blast_amplitude":0.2700116,"saturated":false}
{"timestamp":1756162800.5999994,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.6408564,0.6408564,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000077,0.0000774,0.0000539,0.0000356,0.0000518,0.0000537,0.0000735,0.0000783,0.0000395,0.0000436,0.0000563,0.0000131,0.0000342,0.0000668,0.0000634,0.0000477,0.0000287,0.0000554,0.0000808,0.0000915,0.0000581,0.0000258,0.0000518,0.0000413,0.0000187,0.0000031,0,0,0.0000574,0.0000707,0.0000767,0.0000769,0.0000725,0.0000139,0.0000462,0.0000531,0.0000444,0.0000404,0.0000454,0.0000324,0.0000324,0.0000346,0.0000261,0.0000373,0.0000415,0.0000185,0.0000191,0.0000472,0.0000436,0.0000362,0.000028,4e-7,1e-7,0.0000254,0.0000269,0.0000333,0.0000392,0.0000303,0.0000136,0.0000469,0.0000533,0.0000591,0.0000661,0.0000639,0.000037,0.0000453,0.000051,0.0000412,0.000056,0.0000701,0.000065,0.0000589,0.0000548,0.0000294,0.000017,0.00005,0.0000639,0.00007,0.0000707,0.0000532,0.0000385,0.0000837,0.000169,0.000367,0.0007705,0.0011934,0.0016805,0.0021657,0.0025404,0.0027689,0.0028171,0.0027894,0.0024745,0.0020375,0.0015322,0.0010193,0.0006042,0.0003234,0.0001384,0.0000265,0.0000519,0.0000531,0.0000508,0.0000451,0.0000323,0.0000367,0.0000542,0.0000525,0.0000494,0.0000475,0.0000383,0.0000218,0.0000378,0.0000392,0.0000431,0.0000493,0.0000476,0.0000425,0.0000593,0.0000632,0.0000549,0.0000421,0.000027,0.0000146,0.0000277,0.0000328,0.0000259,0.0000358,0.0000458,0.0000401,0.0000317,0.0000386,0.0000369,0.0000353,0.000033,0.0000204,0,0.000003,7e-7,0.000013,0.0000434,0.0000532,0.0000564,0.000057,0.0000545,0.0000472,0.0000547,0.0000559,0.0000414,0.0000456,0.0000515,0.0000457,0.0000395,0.0000369,0.0000222,0.0000269,0.0000397,0.0000384,0.0000325,0.0000417,0.0000469,0.0000515,0.0000534,0.0000472,0.0000365,0.0000509,0.0000502,0.0000451,0.0000373,0.0000255,0.000005,0.0000077,0.0000167,0.0000301,0.0000464,0.0000496,0.0000464,0.0000516,0.0000538,0.0000411,0.0000194,0.0000212,0.0000319,0.0000365,0.0000378,0.0000295,0.000019,0.0000183,0.00003,0.0000526,0.0000748,0.0000766,0.0000759,0.0000703,0.0000576,0.000032,0.0000312,0.0000408,0.0000546,0.000065,0.0000661,0.0000515,0.0000519,0.0000558,0.0000542,0.000048,0.0000386,0.0000185,0.0000095,0.000013,0.0000073,0.0000053,0.000008,0.0000053,0.0000119,0.0000192,0.0000171,0.000015,0.000023,0.0000215,0.0000146,0.0000073,0.0000017,0,0.0000274,0.0000523,0.0000796,0.0001026,0.0001064,0.0001017,0.0000916,0.000081,0.0000522,0.0000302,0.0000338,0.0000388],"detections":[{"range_m":2.328964,"snr_db":25.6745,"width_m":0.171607}],"noise_floor":0.000037396,"blast_amplitude":0.269958,"saturated":false}
{"timestamp":1756162800.666666,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.4531539,0.7848856,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000223,0.0000222,0.0000191,0.0000163,0.0000189,0.0000106,0.0000046,0.0000086,0.0000323,0.0000401,0.0000561,0.0000623,0.0000353,0.0000418,0.0000479,0,0.0000179,0.0000599,0.0000685,0.0000752,0.0000779,0.0000388,0.0000346,0.0000668,0.0000577,0.0000416,0.0000261,0.0000049,0.0000219,0.0000433,0.0000298,0.0000247,0.000063,0.0000602,0.0000461,0.0000322,0.0000412,0.0000749,0.0001205,0.0001274,0.0001166,0.0001093,0.0001075,0.0000635,0.0000197,0.000036,0.0000565,0.0000785,0.0000878,0.0000696,0.0000467,0.0000483,0.0000357,0.0000218,0.0000087,0.0000159,0.0000226,0.0000241,0.0000139,0.0000202,0.000038,0.000034,0.0000169,0.0000095,0.0000153,0.0000297,0.0000438,0.0000429,0.0000275,0.0000569,0.0000674,0.0000606,0.0000447,0.0000251,0.0000169,0.0000284,0.0000328,0.0000201,0.0000379,0.0000675,0.0000819,0.0000951,0.0001018,0.0000906,0.0000799,0.0000913,0.0000866,0.0000657,0.0000481,0.0000285,0.0000025,0.0000318,0.0000532,0.0000655,0.0000663,0.0000555,0.0001433,0.0003896,0.0007306,0.0011688,0.0016709,0.0021404,0.0025433,0.0026819,0.0026838,0.0025411,0.0022067,0.0017629,0.0012745,0.0008196,0.0004659,0.000175,0.0000294,0.0000558,0.0000554,0.0000438,0.0000278,0.0000185,0.0000532,0.0000947,0.0001053,0.0001072,0.0001069,0.0001021,0.0000665,0.0000291,0.0000327,0.0000577,0.0000806,0.000089,0.0000837,0.0000734,0.0000617,0.000027,0.0000139,0.0000269,0.0000251,0.0000362,0.0000556,0.0000554,0.0000507,0.0000443,0.0000316,0.0000138,0.0000127,0.0000107,0.0000045,0.0000232,0.0000288,0.0000423,0.0000602,0.0000633,0.0000535,0.0000389,0.0000301,0.0000177,0.0000138,0.0000121,0.0000049,0.0000169,0.000028,0.0000278,0.0000376,0.0000472,0.000046,0.0000443,0.0000465,0.0000418,0.0000404,0.0000534,0.0000514,0.000041,0.0000366,0.0000413,0.0000534,0.0000656,0.0000676,0.0000566,0.000055,0.000056,0.000043,0.0000285,0.0000139,0.000014,0.0000353,0.0000476,0.0000548,0.0000633,0.0000673,0.0000603,0.0000516,0.0000601,0.0000586,0.0000561,0.0000562,0.0000511,0.0000451,0.0000588,0.0000595,0.0000588,0.0000573,0.0000531,0.0000395,0.000044,0.0000457,0.0000397,0.0000495,0.0000519,0.0000474,0.0000443,0.0000469,0.000045,0.0000507,0.0000558,0.0000521,0.0000567,0.0000594,0.0000513,0.0000339,0.0000184,0.0000189,0.0000322,0.0000407,0.0000386,0.0000316,0.0000348,0.0000343,0.0000303,0.0000291,0.0000271,0.0000172,0.0000224,0.0000245,0.0000209,0.0000213,0.0000312,0.0000365,0.000038,0.0000375,0.0000231],"detections":[{"range_m":2.505157,"snr_db":22.8011,"width_m":0.171607}],"noise_floor":0.000042351,"blast_amplitude":0.2700065,"saturated":false}
{"timestamp":1756162800.7333326,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.2345697,0.8754261,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000646,0.0000708,0.0000702,0.0000625,0.0000487,0,0.0000278,0.0000379,0.0000119,0.0000468,0.0000708,0.0000532,0.0000471,0.0000603,0.0000502,0.0000693,0.0000868,0.0000632,0.0000677,0.0001022,0.0000973,0.0000858,0.0000704,0.000029,0,0.0000409,0.0000407,0.0000392,0.0000402,0.0000319,0.000024,0.0000555,0.0000628,0.0000677,0.0000779,0.0000776,0.0000407,0.0000584,0.0000723,0.0000655,0.0000597,0.0000593,0.0000255,0.0000511,0.0000801,0.0000803,0.0000768,0.0000661,0.0000246,0.0000281,0.00004,0.0000291,0.000014,0.000035,0.0000322,0.0000214,0.0000391,0.0000366,0.000025,0.0000107,0.0000264,0.0000506,0.0000678,0.0000672,0.0000469,0.0000675,0.0000761,0.0000708,0.000068,0.0000686,0.0000388,0.0000225,0.0000265,0.0000137,0.0000458,0.0000834,0.0000873,0.0000853,0.0000748,0.0000429,0.0000096,0.0000257,0.0000232,0.0000084,0.0000219,0.0000255,0.0000251,0.0000181,0.0000084,0.0000217,0.0000313,0.0000327,0.00001,0.0000304,0.0000398,0.0000398,0.0000383,0.0000346,0.0000091,0.0000689,0.0001882,0.0003849,0.0006922,0.0010882,0.0015227,0.0019577,0.0023614,0.0025066,0.0025136,0.0024362,0.0021764,0.0017757,0.0013307,0.000907,0.0004715,0.000226,0.0000787,0.0000342,0.000051,0.0000528,0.0000347,0.0000194,0.0000175,0.0000186,0.0000283,0.0000339,0.0000303,0.0000323,0.0000333,0.0000167,0.0000111,0.0000217,0.0000215,0.000035,0.0000571,0.0000625,0.0000677,0.0000711,0.0000647,0.00005,0.0000604,0.0000595,0.0000454,0.0000286,0.0000113,0.0000096,0.0000183,0.000021,0.0000189,0.0000199,0.0000205,0.0000073,0.0000112,0.0000156,0.0000116,0.0000157,0.0000227,0.0000207,0.0000248,0.0000299,0.000026,0.0000369,0.0000535,0.0000533,0.0000493,0.0000418,0.0000236,5e-7,0.0000033,0.0000032,0.0000055,0.000028,0.0000422,0.0000475,0.0000501,0.0000502,0.0000334,0.0000312,0.0000403,0.000046,0.0000544,0.0000569,0.0000483,0.000049,0.0000562,0.000054,0.0000487,0.0000435,0.0000262,0.0000228,0.0000364,0.0000356,0.0000285,0.0000278,0.0000266,0.0000178,0.0000327,0.0000423,0.0000478,0.0000489,0.0000486,0.0000334,0.0000521,0.0000643,0.0000688,0.0000692,0.0000676,0.0000504,0.0000342,0.000026,0.0000091,0.000012,0.0000218,0.0000205,0.0000145,0.0000084,0.0000072,0.0000177,0.0000311,0.0000312,0.0000292,0.000023,0.0000129,0.0000167,0.000036,0.0000378,0.0000403,0.0000456,0.0000469,0.0000393,0.0000319,0.0000243,0.0000079,0.0000077,0.000017,0.0000293],"detections":[{"range_m":2.654324,"snr_db":29.6705,"width_m":0.171607}],"noise_floor":0.000034262,"blast_amplitude":0.2699895,"saturated":false}
{"timestamp":1756162800.7999992,"source":"simulated","device_id":"batvu-reference-01","beam":[0,0.9063078,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000114,0.0000655,0.0000602,0.0000322,0.0000366,0.0000486,0.0000144,0.0000124,0.0000438,0.0000467,0.0000465,0.0000418,0,0,0.0000047,0,0.0000313,0.0000683,0.0000651,0.00006,0.0000588,0.0000249,0.000016,0.0000315,0.0000168,0.0000307,0.0000814,0.000077,0.000063,0.0000555,0.0000479,0.0000353,0.0000529,0.0000563,0.000034,0.0000279,0.0000238,0,0.0000045,0.0000137,0.0000072,0.00001,0.0000118,0.000002,0.0000112,0.0000162,0,0.0000093,0.0000394,0.0000363,0.0000469,0.0000712,0.000069,0.0000632,0.0000557,0.0000405,0.0000176,0.0000291,0.0000255,0.00002,0.0000294,0.0000283,0.0000016,0.0000329,0.0000524,0.0000653,0.0000793,0.0000826,0.0000707,0.0000844,0.0000918,0.0000743,0.0000525,0.0000338,0.0000097,0.0000189,0.0000243,0.0000142,0.0000214,0.000037,0.0000342,0.0000382,0.000054,0.0000524,0.0000529,0.0000639,0.0000606,0.0000576,0.0000689,0.0000682,0.0000583,0.0000668,0.0000686,0.0000465,0.000064,0.0000722,0.0000738,0.0000939,0.0001544,0.0003357,0.000616,0.0009919,0.0014357,0.0019098,0.002325,0.0025929,0.0026825,0.0026763,0.0024565,0.0020777,0.0016175,0.001148,0.0007292,0.0004237,0.0002268,0.0000729,0.0000324,0.0000358,0.0000332,0.0000253,0.0000441,0.0000644,0.00008,0.0000811,0.0000607,0.0000513,0.0000551,0.0000449,0.0000293,0.0000229,0.0000448,0.0000728,0.0000922,0.000096,0.0001054,0.0001124,0.0001055,0.0000687,0.0000334,0.0000236,0.0000376,0.0000487,0.000048,0.0000416,0.0000408,0.0000375,0.0000188,0.0000159,0.0000175,0.0000104,0.0000181,0.0000232,0.0000298,0.000051,0.0000641,0.0000645,0.0000639,0.0000621,0.0000512,0.0000404,0.0000381,0.000022,0.0000186,0.0000556,0.0000681,0.0000703,0.0000687,0.0000495,0.0000222,0.0000181,0.0000169,0.0000115,0.0000253,0.0000294,0.0000272,0.0000242,0.0000202,0.0000221,0.0000527,0.0000764,0.0000895,0.0000998,0.0001002,0.0000802,0.0000454,0.0000209,0.0000446,0.0000579,0.000063,0.0000588,0.000078,0.0001001,0.0001011,0.0000988,0.000091,0.0000795,0.0000594,0.0000719,0.0000772,0.0000779,0.0000748,0.0000595,0.0000196,0.0000324,0.0000386,0.0000376,0.0000354,0.0000368,0.0000307,0.0000453,0.0000633,0.0000699,0.0000771,0.0000813,0.0000761,0.0000686,0.0000685,0.0000637,0.0000489,0.0000304,0.0000148,0.0000247,0.0000312,0.0000291,0.0000144,0.0000355,0.0000404,0.0000404,0.000036,0.0000273,0.0000466,0.0000784,0.0000972,0.0001037,0.0001045,0.0001029,0.0000813],"detections":[{"range_m":2.608981,"snr_db":23.7218,"width_m":0.171607}],"noise_floor":0.000045694,"blast_amplitude":0.2700531,"saturated":false}
{"timestamp":1756162800.8666658,"source":"simulated","device_id":"batvu-reference-01","beam":[0.2345697,0.8754261,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000024,0.0000115,0.0000208,0.0000283,0.0000384,0.0000206,0,0,0.0000202,0.0000123,0.0000089,0.0000179,0.0000088,0.0000037,0.0000163,0.0000308,0.0000562,0.0000728,0.0000569,0.0000539,0.000054,0.00001,0.0000119,0.0000454,0.000038,0.0000286,0.0000252,0,4e-7,0.0000496,0.0000457,0.0000316,0.0000411,0.0000546,0.0000698,0.0000766,0.0000749,0.0000268,0.0000553,0.0000595,0.0000386,0.0000263,0.000026,0.0000024,0.0000068,0.0000136,0,0.0000069,0.0000404,0.0000463,0.0000492,0.0000508,0.000026,0.0000122,0.00002,0.00001,0,0.0000367,0.0000453,0.0000487,0.000049,0.000037,0.0000073,0.0000273,0.0000297,0.0000191,0.0000076,0.0000065,0.0000117,0.0000223,0.000029,0.0000391,0.0000568,0.0000653,0.0000529,0.000048,0.0000516,0.0000385,0.0000348,0.0000408,0.0000306,0.000012,0.0000054,0.000002,0.0000133,0.000044,0.0000563,0.0000709,0.000082,0.0000745,0.000052,0.0000518,0.0000498,0.0000246,0.0000252,0.0000543,0.0000703,0.0000836,0.0000858,0.0000706,0.0000768,0.000085,0.0001454,0.000315,0.0005826,0.0009421,0.0013838,0.0018382,0.0022176,0.0024715,0.0025457,0.0025016,0.002276,0.0019127,0.0014712,0.0010164,0.0006324,0.0003449,0.0001056,0.0000441,0.0000519,0.0000508,0.0000424,0.0000318,0.0000066,0.0000422,0.0000589,0.0000666,0.000072,0.0000735,0.0000598,0.0000647,0.0000794,0.0000784,0.0000744,0.0000662,0.0000413,0.0000183,0.0000381,0.0000387,0.0000417,0.0000504,0.0000493,0.0000505,0.0000513,0.0000475,0.0000251,0.00002,0.0000197,0.0000273,0.0000428,0.0000462,0.0000413,0.0000409,0.0000436,0.0000361,0.0000529,0.0000685,0.0000773,0.0000879,0.0000944,0.0000899,0.0000936,0.0001005,0.0000942,0.0000748,0.0000476,0.0000249,0.0000491,0.0000633,0.0000585,0.0000413,0.0000335,0.000032,0.0000241,0.0000276,0.0000289,0.0000199,0.0000261,0.0000275,0.0000157,0.0000046,0.0000152,0.0000313,0.0000593,0.0000691,0.0000663,0.0000519,0.0000304,0.0000261,0.0000369,0.0000379,0.0000226,0.0000021,0.0000152,0.0000175,0.0000255,0.0000335,0.0000319,0.0000189,0.0000174,0.000017,0.0000254,0.0000443,0.0000547,0.0000659,0.0000853,0.0000887,0.0000852,0.0000799,0.0000767,0.0000638,0.0000529,0.0000476,0.0000269,0.0000155,0.0000373,0.0000427,0.000043,0.0000421,0.0000351,0.0000231,0.0000172,0.0000102,0.0000203,0.0000445,0.0000548,0.000063,0.0000702,0.0000687,0.0000589,0.0000588,0.0000593,0.0000438,0.000023,0.0000235,0.0000448,0.000055,0.0000565,0.0000447],"detections":[{"range_m":2.624386,"snr_db":22.9517,"width_m":0.175182}],"noise_floor":0.000038604,"blast_amplitude":0.2700422,"saturated":false}
{"timestamp":1756162800.9333324,"source":"simulated","device_id":"batvu-reference-01","beam":[0.4531539,0.7848856,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000026,0,0,0,0.0000225,0.0000271,0.0000224,0.0000159,0.0000119,0,0,0.0000127,0.0000126,0.0000103,0.0000098,0.0000049,0.0000161,0.0000348,0.0000432,0.0000526,0.000056,0.0000178,0,0.0000118,0.0000076,0.0000331,0.0000706,0.0000655,0.000068,0.0000908,0.000078,0.0000563,0.0000495,0.0000371,0,0.0000261,0.0000348,0.0000259,0.0000306,0.0000355,0.0000318,0.0000342,0.0000361,0.0000198,0.0000261,0.0000275,0,0.0000016,0.0000176,0.0000126,0.0000139,0.0000369,0.0000423,0.0000474,0.0000487,0.0000276,0,0.0000216,0.0000252,0.0000438,0.0000737,0.0000727,0.0000776,0.0000886,0.000087,0.000055,0.0000301,0.0000282,0.000011,6e-7,0.0000203,0.0000278,0.0000302,0.0000299,0,0.0000213,0.0000344,0.0000374,0.0000645,0.0000883,0.0000856,0.0000656,0.0000402,0.000007,0.0000255,0.000037,0.0000329,0.0000395,0.000065,0.0000631,0.000053,0.0000511,0.0000493,0.0000357,0.0000531,0.0000595,0.0000554,0.0000584,0.0000595,0.0000405,0.0000314,0.0000349,0.0000243,0.0000146,0.0000172,0.0000186,0.0000467,0.0000744,0.000076,0.0000736,0.000086,0.0001982,0.0004095,0.0007136,0.0010783,0.0015014,0.0019219,0.0022778,0.0024012,0.0024036,0.0022981,0.0020036,0.0016099,0.001189,0.0007758,0.000441,0.0001793,0.000064,0.0000474,0.0000405,0.0000063,0.0000219,0.0000304,0.0000207,0.000018,0.000026,0.0000218,0.000014,0.0000153,0.0000105,0,0.0000179,0.0000181,0.0000162,0.0000192,0.0000261,0.0000413,0.0000645,0.000065,0.0000595,0.0000534,0.0000475,0.0000219,0.000014,0.0000363,0.0000476,0.0000577,0.000061,0.000051,0.0000408,0.0000372,0.0000232,0.0000314,0.0000559,0.0000573,0.0000531,0.0000374,0.0000156,0.0000193,0.0000197,0.0000061,0.0000168,0.0000335,0.0000335,0.000028,0.0000283,0.0000294,0.0000198,0.0000176,0.0000168,8e-7,0,0.0000022,0.0000073,0.0000225,0.0000303,0.0000329,0.00004,0.000046,0.0000428,0.0000412,0.0000438,0.0000354,0.0000263,0.0000432,0.0000488,0.0000527,0.0000551,0.0000528,0.0000394,0.0000438,0.0000432,0.0000335,0.0000184,0.0000241,0.0000427,0.0000556,0.0000568,0.0000479,0.0000566,0.0000606,0.0000545,0.0000485,0.0000535,0.0000525,0.0000562,0.0000588,0.0000527,0.0000493,0.0000572,0.000056,0.0000537,0.0000577,0.0000544,0.0000455,0.0000374,0.0000256,0.0000098,0.0000314,0.0000325,0.000035,0.0000465,0.0000533,0.0000586,0.000064,0.0000659,0.0000589,0.0000688,0.0000776,0.0000808],"detections":[{"range_m":2.78081,"snr_db":26.2487,"width_m":0.171607}],"noise_floor":0.000034262,"blast_amplitude":0.269969,"saturated":false}
{"timestamp":1756162800.999999,"source":"simulated","device_id":"batvu-reference-01","beam":[0.6408564,0.6408564,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000813,0.0000769,0.0000585,0.000039,0.0000726,0.0000664,0.0000402,0.0000452,0.0000583,0.0000287,0.0000308,0.0000457,0.0000338,0.0000275,0.0000322,0.0000259,0.0000431,0.0000514,0.0000133,0,0.0000264,0.0000328,0.0000476,0.0000635,0.0000417,0.0000168,0.0000168,0.0000208,0.0000243,0.0000298,0.0000146,0.0000143,0.0000311,0.0000245,0.0000061,0.0000267,0.000032,0.0000149,0.0000117,0.0000295,0.000046,0.0000632,0.0000669,0.0000397,0.0000642,0.0000863,0.0000929,0.0000992,0.0001013,0.0000753,0.0000702,0.000092,0.0000832,0.0000698,0.0000632,0.000048,0.00005,0.0000733,0.0000704,0.0000648,0.0000817,0.0000779,0.0000605,0.0000456,0.0000291,0,0.0000087,0.0000077,0,0.0000266,0.0000389,0.0000375,0.0000416,0.000048,0.0000357,0.0000259,0.0000352,0.00004,0.0000501,0.0000598,0.0000542,0.0000503,0.0000547,0.0000429,0.0000222,0.0000075,0.0000211,0.000031,0.0000394,0.0000344,0.0000333,0.0000417,0.0000396,0.0000213,0.0000387,0.0000427,0.0000255,0.0000169,0.0000352,0.0000458,0.0000543,0.0000574,0.0000442,0.0000652,0.0000807,0.0000802,0.0000742,0.0000623,0.0000341,0.0000073,0.000012,0.000055,0.0001692,0.0003761,0.0006684,0.0010684,0.0015341,0.0020401,0.0023499,0.0024909,0.0024918,0.0023697,0.0020836,0.0016931,0.001242,0.0008239,0.0004343,0.0001976,0.000063,0.0000426,0.0000519,0.000072,0.0000907,0.0000909,0.0000921,0.0000942,0.0000847,0.0000724,0.0000696,0.000063,0.0000452,0.0000398,0.0000361,0.0000527,0.000075,0.0000759,0.0000711,0.0000666,0.0000605,0.0000371,0.000034,0.000041,0.0000427,0.0000449,0.0000471,0.0000407,0.000052,0.0000587,0.0000565,0.0000541,0.0000523,0.0000398,0.0000289,0.0000386,0.0000397,0.0000404,0.0000401,0.0000302,0.0000124,0.0000251,0.0000252,0.0000271,0.0000272,0.0000229,0.0000306,0.0000628,0.0000792,0.0000847,0.0000893,0.0000899,0.0000735,0.0000578,0.0000466,0.0000246,0.0000091,0.0000288,0.000041,0.0000536,0.0000604,0.0000561,0.000048,0.0000456,0.0000383,0.0000371,0.00005,0.0000524,0.0000586,0.0000667,0.0000655,0.000055,0.0000476,0.0000434,0.0000249,0.0000085,0.0000151,0.0000221,0.0000355,0.0000406,0.0000492,0.0000668,0.0000779,0.0000789,0.0000786,0.0000756,0.0000567,0.0000398,0.0000402,0.0000417,0.0000431,0.000043,0.0000345,0.0000169,0.0000076,0.0000012,0.0000168,0.000038,0.0000394,0.0000363,0.0000267,0.0000247,0.0000297,0.0000363,0.0000404,0.0000475,0.0000532,0.0000539,0.0000417,0.0000251,0.0000227,0.0000269],"detections":[{"range_m":2.79791,"snr_db":23.0872,"width_m":0.175182}],"noise_floor":0.000038573,"blast_amplitude":0.2700266,"saturated":false}
{"timestamp":1756162801.0666656,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7848856,0.4531539,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000372,0.0000365,0.0000382,0.0000425,0.0000496,0.0000298,0,0.0000137,0.0000379,0.0000219,0.0000079,0.0000244,0.0000283,0.0000382,0.0000473,0.0000154,0.000019,0.0000358,0.0000325,0.0000366,0.0000377,0,0,0.0000287,0.0000226,0.000038,0.0000681,0.0000596,0.0000483,0.0000714,0.0000635,0.0000493,0.0000409,0.000048,0.0000762,0.0001014,0.0001032,0.0000606,0.0000645,0.0000658,0.0000302,0.0000013,0.0000219,0.0000222,0.0000183,0.0000233,0.0000183,0.0000207,0.000027,0.0000255,0.0000349,0.0000392,0.0000124,0.0000027,0.0000294,0.0000268,0.0000261,0.000044,0.0000407,0.0000227,0.000041,0.0000497,0.0000536,0.0000531,0.0000411,0,0.0000178,0.0000186,0.0000119,0.0000423,0.0000534,0.0000486,0.0000358,0.0000237,0.0000358,0.0000466,0.0000498,0.0000327,0.0000228,0.0000251,0.0000093,0.0000098,0.0000396,0.0000424,0.0000423,0.0000378,0.000016,0.0000125,0.0000385,0.0000379,0.0000568,0.0000886,0.0000912,0.0000843,0.0000714,0.0000621,0.0000603,0.0000778,0.0000806,0.0000655,0.0000749,0.0000862,0.0000813,0.0000566,0.0000701,0.0002105,0.0004354,0.0007465,0.0011345,0.001597,0.0021432,0.0024714,0.0026279,0.0026347,0.002533,0.0022302,0.0018162,0.0013626,0.0008314,0.0004821,0.0002353,0.0000687,0.0000213,0.0000321,0.0000407,0.0000535,0.0000552,0.0000395,0.0000455,0.0000546,0.0000512,0.0000413,0.0000272,0.0000162,0.0000314,0.0000396,0.0000348,0.0000429,0.0000664,0.0000761,0.0000853,0.0000912,0.0000856,0.00007,0.0000639,0.0000592,0.0000297,0.0000344,0.0000583,0.0000689,0.0000695,0.0000651,0.0000341,0.0000124,0.0000106,0.0000056,0.0000131,0.0000176,0.0000121,0.0000121,0.0000228,0.0000225,0.0000197,0.0000099,0.0000339,0.0000632,0.0000875,0.0000895,0.0000919,0.0000942,0.0000867,0.0000612,0.0000348,0.000012,0.0000101,0.0000103,0.0000107,0.0000185,0.0000219,0.0000218,0.000003,0,0.0000085,0.0000178,0.0000322,0.000036,0.0000275,0.0000172,0.0000159,0.0000184,0.0000421,0.0000712,0.0000756,0.0000754,0.0000703,0.000053,0.0000335,0.0000605,0.0000743,0.0000836,0.0000845,0.0000794,0.0000529,0.0000272,0.0000114,0.0000317,0.0000578,0.0000667,0.0000746,0.0000857,0.0000895,0.0000815,0.0000669,0.0000534,0.0000313,0.000018,0.0000359,0.0000528,0.0000705,0.0000831,0.0000825,0.0000803,0.0000798,0.0000692,0.0000438,0.0000517,0.0000749,0.0000944,0.0001023,0.0000985,0.0000706,0.0000391,0.0000138,0.0000364,0.0000629,0.0000786,0.0000795,0.0000784,0.0000738,0.0000577],"detections":[{"range_m":2.671687,"snr_db":24.1381,"width_m":0.175182}],"noise_floor":0.000039462,"blast_amplitude":0.2699971,"saturated":false}
{"timestamp":1756162801.1333323,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8754261,0.2345697,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000076,0.0000163,0.0000241,0.0000026,0,0,0.000004,0,0.0000258,0.0000574,0.0000596,0.0000596,0.0000572,0,0.0000349,0.000058,0.0000424,0.0000243,0.0000149,0,0.0000449,0.0000914,0.0000934,0.000093,0.0000887,0.0000553,0.0000406,0.000089,0.0000887,0.000084,0.0000749,0.0000541,0.0000179,0.0000315,0.0000325,0.0000097,0.0000574,0.0000657,0.0000583,0.0000431,0.0000312,0.0000283,0.0000339,0.0000344,0,0.0000115,0.0000327,0.0000295,0.0000256,0.0000229,0,0.0000036,0.0000199,0.0000132,0.0000153,0.0000567,0.0000593,0.0000576,0.0000481,0.0000226,0,0.0000124,0.0000171,0.0000229,0.0000307,0.0000294,0.0000128,0.0000313,0.0000392,0.0000332,0.0000285,0.0000327,0.0000255,0.0000268,0.0000275,0.0000092,0.0000298,0.0000575,0.0000602,0.00006,0.0000557,0.0000302,0.000002,0.0000085,0.0000069,0.0000069,0.0000127,0.0000058,0.0000033,0.000038,0.0000441,0.0000436,0.0000519,0.0001603,0.0003423,0.0006287,0.001004,0.0014732,0.0019973,0.0024653,0.0028171,0.002881,0.002856,0.0026166,0.0022054,0.0017232,0.001234,0.0007997,0.0004696,0.0001975,0.000058,0.0000214,0.0000222,0.0000327,0.0000553,0.0000566,0.0000501,0.0000461,0.0000451,0.0000556,0.0000691,0.000071,0.0000534,0.0000393,0.0000365,0.0000175,0.0000246,0.0000359,0.0000355,0.0000341,0.0000362,0.0000266,0.0000282,0.000033,0.0000264,0.0000356,0.0000599,0.0000657,0.000067,0.0000664,0.0000529,0.0000267,0.000039,0.0000435,0.0000505,0.0000618,0.0000601,0.0000433,0.0000381,0.0000434,0.0000462,0.0000468,0.0000462,0.0000256,0.0000188,0.0000203,0.0000075,0.0000044,0.00002,0.0000244,0.0000344,0.000039,0.0000297,0.000008,0.000032,0.0000438,0.0000491,0.0000524,0.0000479,0.0000404,0.0000397,0.0000353,0.0000142,0.0000119,0.0000146,0.0000138,0.0000306,0.0000408,0.0000459,0.0000488,0.0000495,0.000038,0.000038,0.0000407,0.0000308,0.0000166,0.0000056,0.0000061,0.0000115,0.0000168,0.0000119,0.0000118,0.0000222,0.0000218,0.0000206,0.0000208,0.0000182,0.0000034,0.0000098,0.0000102,0.0000092,0.0000164,0.000019,0.0000246,0.0000461,0.0000558,0.0000591,0.0000594,0.0000583,0.0000434,0.0000353,0.0000408,0.0000361,0.0000259,0.0000119,0.0000401,0.0000671,0.0000814,0.0000793,0.0000647,0.0000437,0.0000267,0.0000422,0.0000673,0.0000708,0.0000702,0.0000653,0.000053,0.0000304,0.000016,0.0000073,0.0000205,0.0000442,0.0000534,0.0000506,0.0000412,0.0000458,0.0000531],"detections":[{"range_m":2.49792,"snr_db":27.1549,"width_m":0.171607}],"noise_floor":0.000031168,"blast_amplitude":0.270043,"saturated":false}
{"timestamp":1756162801.1999989,"source":"simulated","device_id":"batvu-reference-01","beam":[0.9063078,0,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8e-7,0,0,0.0000014,0.0000921,0.0000951,0.0000991,0.0001027,0.0001033,0.0000388,0.0000728,0.0001004,0.0000973,0.0000904,0.0000824,0.0000067,0.0000118,0.0000362,0.0000279,0.0000152,0.000012,0.0000208,0.0000245,0.0000275,0.0000021,0.0000043,0.0000093,0,0,0.0000395,0.0000397,0.0000385,0.0000333,0.000015,0.0000095,0.0000351,0.000041,0.0000485,0.0000704,0.0000734,0.0000547,0.0000662,0.0000692,0.0000385,0.0000052,0.0000249,0.0000305,0.0000347,0.0000371,0.0000165,0.0000086,0.0000128,0,0,0.0000075,0.0000118,0.0000208,0.0000307,0.0000241,0.0000114,0.0000398,0.0000385,0.0000309,0.0000231,0.0000193,0.0000188,0.0000301,0.0000291,0.0000143,0.0000437,0.0000561,0.0000561,0.0000566,0.000057,0.000028,0.0000259,0.0000398,0.0000374,0.0000337,0.0000307,0.000015,0.0000073,0.0000156,0.0000091,0,0.0000308,0.0000438,0.0000494,0.0000502,0.0001099,0.0002816,0.0005713,0.0009581,0.0014625,0.0020337,0.0026333,0.0029591,0.0030588,0.0030487,0.0028297,0.0024275,0.0019317,0.0014014,0.0008381,0.0004895,0.0002386,0.0000943,0.0000443,0.0000249,0.0000063,0.0000074,0.0000098,0.0000359,0.0000718,0.0000809,0.0000845,0.0000848,0.0000804,0.0000541,0.0000715,0.0000753,0.000082,0.0000906,0.0000922,0.0000772,0.0000691,0.0000688,0.0000427,0.0000241,0.0000342,0.0000341,0.0000359,0.0000522,0.000067,0.0000854,0.0000952,0.0000906,0.000083,0.0000913,0.0000892,0.0000824,0.0000809,0.0000735,0.0000591,0.0000776,0.0000817,0.000085,0.000088,0.0000854,0.0000691,0.0000748,0.0000774,0.0000711,0.0000662,0.0000642,0.0000426,0.0000258,0.0000165,0.0000042,0.000016,0.000025,0.0000276,0.0000498,0.0000634,0.0000611,0.0000482,0.0000303,0.0000109,0.0000109,0.0000146,0.0000094,0.0000046,0.000019,0.0000226,0.0000354,0.0000553,0.0000594,0.0000494,0.0000401,0.0000613,0.00008,0.0000881,0.0000882,0.0000691,0.000047,0.000032,0.0000073,0.0000327,0.0000586,0.0000602,0.0000546,0.0000323,0.0000372,0.0000659,0.0000811,0.0000801,0.0000813,0.0000948,0.0000953,0.0000966,0.0001012,0.0000994,0.000086,0.000076,0.0000698,0.0000501,0.000044,0.0000464,0.0000441,0.0000397,0.0000315,0.0000102,0.0000128,0.0000183,0.000011,0.0000035,0.0000067,0.0000022,0.000001,0.000017,0.0000371,0.0000835,0.0001231,0.0001354,0.0001357,0.0001269,0.0001031,0.0000641,0.0000366,0.0000186,0,0.000018,0.000027,0.0000346,0.0000481,0.0000579,0.0000629,0.0000716,0.0000758,0.000073],"detections":[{"range_m":2.389984,"snr_db":26.5278,"width_m":0.171607}],"noise_floor":0.000036572,"blast_amplitude":0.2700389,"saturated":false}
{"timestamp":1756162801.2666655,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8754261,-0.2345697,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000413,0.0000498,0.0000508,0.0000489,0.0000414,0.000015,0,0,0.0000372,0.0000404,0.0000403,0.0000352,0,0.0000059,0.0000127,0,0.0000029,0.0000079,0,8e-7,0.0000464,0.0000469,0.0000489,0.0000619,0.0000537,0.0000719,0.0000896,0.0000733,0.0000483,0.0000511,0.0000295,0,0.0000367,0.0000329,0.0000089,0.0000338,0.0000634,0.0000686,0.0000683,0.0000589,0.0000023,0.0000071,0.0000208,0.0000182,0.0000276,0.0000319,0.0000158,0.0000277,0.0000407,0.0000314,0.0000229,0.0000195,0,0,0.0000016,0,0,0.000009,0.0000049,0.0000042,0.0000404,0.0000403,0.0000359,0.0000268,0.0000154,0.0000045,0.0000079,0.0000058,0,0.0000015,0.0000066,0.0000105,0.0000237,0.0000333,0.000027,0.00004,0.0000499,0.0000443,0.0000523,0.0000647,0.0000601,0.000066,0.0000776,0.0000711,0.0000531,0.0000388,0.0000433,0.0000589,0.000079,0.0000788,0.0001104,0.000207,0.0003738,0.0006645,0.001086,0.0016886,0.0022178,0.0026817,0.0029551,0.0030048,0.0029674,0.0027241,0.0022836,0.0016488,0.0011477,0.0007086,0.000372,0.0001497,0.000028,0.000049,0.0000492,0.0000206,0.0000075,0.0000255,0.0000261,0.0000375,0.0000525,0.0000517,0.0000319,0.0000166,0.0000137,0.0000228,0.0000282,0.0000287,0.0000088,0.0000134,0.0000177,0.0000214,0.0000405,0.0000598,0.0000773,0.0001021,0.0001184,0.0001157,0.0001081,0.0000993,0.0000752,0.0000435,0.0000389,0.0000508,0.0000644,0.0000745,0.0000711,0.0000627,0.0000747,0.0000743,0.0000617,0.0000405,0.0000227,0.000052,0.0000694,0.000071,0.0000529,0.0000368,0.0000324,0.0000132,0.0000277,0.0000482,0.0000555,0.0000581,0.0000582,0.0000467,0.0000614,0.0000854,0.0000912,0.0000917,0.0000893,0.0000739,0.0000476,0.0000342,0.0000241,0.0000206,0.0000461,0.0000502,0.0000497,0.0000419,0.0000266,0.0000149,0.0000305,0.0000327,0.0000226,0.0000141,0.0000136,0.0000034,0.0000231,0.0000426,0.0000543,0.000065,0.00007,0.0000635,0.0000525,0.0000481,0.00004,0.0000335,0.0000399,0.000037,0.000027,0.000023,0.000022,0.0000152,0.0000276,0.000042,0.0000544,0.0000613,0.000062,0.0000485,0.0000494,0.0000516,0.000047,0.0000403,0.0000308,0.0000083,0,0.0000017,4e-7,0.0000089,0.0000158,0.0000142,0.0000186,0.0000372,0.00005,0.0000653,0.0000708,0.000066,0.000051,0.0000408,0.0000328,0.0000126,0.0000271,0.0000374,0.0000434,0.0000494,0.0000527,0.0000666,0.0000885,0.000103,0.0001096,0.0001177,0.0001202,0.0001111],"detections":[{"range_m":2.421122,"snr_db":25.9909,"width_m":0.171607}],"noise_floor":0.000039479,"blast_amplitude":0.2700178,"saturated":false}
{"timestamp":1756162801.333332,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7848856,-0.4531539,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000178,0.0000242,0.0000253,0.0000249,0.0000216,0.0000018,0.0000159,0.0000339,0.0000417,0.000012,0.0000827,0.0001163,0.000117,0.0001181,0.00012,0.0000605,0.0000689,0.0000842,0.0000574,0.0000364,0.0000545,0.0000407,0.0000231,0.0000082,0.0000171,0.0000238,0.0000251,0.0000025,0.0000093,0.0000219,0.0000055,0,0.0000415,0.0000406,0.0000333,0.0000222,0.000017,0.000028,0.0000381,0.0000382,0.0000127,0.0000222,0.0000242,0,5e-7,0.0000142,0.000007,0.0000222,0.0000447,0.0000452,0.0000474,0.000049,0.0000206,0.0000016,0.0000378,0.0000432,0.0000543,0.0000758,0.0000734,0.0000783,0.0000963,0.0000927,0.0000769,0.0000631,0.0000472,0.0000156,0.0000269,0.0000256,0.0000042,0.0000287,0.0000395,0.0000385,0.000037,0.0000352,0.0000123,0.0000197,0.0000244,0.0000113,0.0000282,0.0000566,0.0000624,0.0000666,0.0000701,0.0000592,0.0000667,0.0000919,0.0000913,0.0000889,0.0000876,0.000075,0.0000496,0.0000646,0.0000653,0.0000563,0.0000578,0.00006,0.0000454,0.0000378,0.0000289,0.0000793,0.0002027,0.0003949,0.0007627,0.001207,0.0017121,0.0022001,0.0025975,0.0028137,0.0028329,0.0027688,0.0025159,0.0020095,0.001501,0.0010163,0.0006052,0.0002919,0.0001058,0.0000276,0.0000346,0.0000423,0.0000399,0.0000168,0.0000223,0.000037,0.0000407,0.0000411,0.0000405,0.0000183,0.0000185,0.0000267,0.0000277,0.0000382,0.000047,0.0000409,0.0000388,0.0000461,0.0000421,0.0000331,0.000024,0.0000089,0.0000192,0.0000429,0.0000486,0.0000559,0.0000656,0.0000646,0.0000547,0.000051,0.0000476,0.0000264,0.0000208,0.0000256,0.00003,0.0000383,0.0000421,0.0000321,0.0000297,0.0000339,0.0000299,0.0000273,0.0000279,0.0000174,0.0000174,0.0000395,0.0000471,0.0000515,0.0000525,0.0000454,0.0000287,0.0000406,0.0000405,0.0000411,0.0000439,0.0000418,0.0000288,0.000026,0.0000283,0.0000458,0.0000752,0.0000898,0.0000933,0.0000933,0.00009,0.0000693,0.0000501,0.0000418,0.0000295,0.0000485,0.0000685,0.0000699,0.0000685,0.0000634,0.0000518,0.0000417,0.0000395,0.0000355,0.0000416,0.000062,0.0000682,0.0000692,0.0000686,0.0000618,0.0000428,0.0000437,0.0000458,0.0000437,0.0000589,0.0000665,0.0000701,0.0000707,0.0000695,0.0000514,0.0000331,0.0000249,0.0000122,0.0000012,0.0000072,0.0000132,0.0000333,0.0000608,0.0000698,0.0000702,0.0000607,0.0000338,0.0000286,0.0000491,0.0000491,0.0000377,0.0000203,0.0000158,0.0000263,0.0000371,0.0000392,0.0000352,0.0000348,0.0000366,0.0000285,0.0000206,0.0000116,0.0000208],"detections":[{"range_m":0.852904,"snr_db":6.1874,"width_m":0.132281},{"range_m":2.581617,"snr_db":25.3381,"width_m":0.171607}],"noise_floor":0.0000376,"blast_amplitude":0.2699973,"saturated":false}
{"timestamp":1756162801.3999987,"source":"simulated","device_id":"batvu-reference-01","beam":[0.6408564,-0.6408564,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8e-7,0.000001,0,0.0000101,0.0000398,0.0000385,0.0000576,0.000071,0.0000659,0.0000786,0.0000831,0.0000203,0.000029,0.0000501,0.0000333,0.0000131,0.0000243,0.0000314,0.0000403,0.0000474,0.0000166,0.000028,0.0000846,0.0000904,0.0000945,0.0000963,0.0000721,0.0000408,0.0000859,0.0000851,0.0000805,0.0000722,0.0000574,0.0000144,0.0000432,0.0000463,0.0000189,0.0000285,0.0000416,0.0000314,0.0000147,0.0000093,0.0000096,0.0000095,0.0000097,0,0,0.000024,0.0000369,0.0000514,0.0000617,0.0000523,0.0000568,0.0000741,0.0000689,0.0000383,0.0000349,0.0000313,0.0000252,0.0000521,0.0000559,0.0000514,0.0000419,0.0000305,0.0000166,0.0000455,0.0000564,0.00006,0.0000768,0.0000895,0.000084,0.0000773,0.0000648,0.0000209,0.0000148,0.0000358,0.0000343,0.0000556,0.0000782,0.0000768,0.0000689,0.0000564,0.0000318,0,0.0000109,0.000007,0,0.000014,0.0000209,0.0000284,0.000041,0.000044,0.0000338,0.0000525,0.0000584,0.0000506,0.0000361,0.0000191,0.0000074,0.0000108,0.0000107,4e-7,0.0000084,0.0000115,0.000015,0.0000765,0.0002316,0.000449,0.0007877,0.0012215,0.0016686,0.0020809,0.0023825,0.0024913,0.002483,0.0023419,0.0020495,0.0016364,0.001198,0.0007999,0.0004627,0.0002355,0.0000988,0.000034,0.000004,0.0000191,0.0000266,0.0000376,0.0000458,0.0000441,0.000062,0.0000776,0.0000761,0.0000669,0.0000517,0.0000255,0.0000111,0.0000306,0.0000302,0.0000368,0.0000573,0.0000603,0.0000606,0.0000602,0.0000528,0.0000265,0.0000093,0.0000088,0.0000307,0.0000629,0.0000784,0.0000765,0.0000639,0.0000522,0.0000589,0.0000745,0.0000834,0.0000811,0.000086,0.0000911,0.0000847,0.0000746,0.0000798,0.0000779,0.0000732,0.0000697,0.0000587,0.0000426,0.0000397,0.0000373,0.0000229,0.0000257,0.0000279,0.0000201,0.0000239,0.0000269,0.0000349,0.0000565,0.0000747,0.0000806,0.0000808,0.0000737,0.0000452,0.0000174,0.0000079,0.000015,0.0000337,0.000058,0.0000628,0.0000648,0.0000657,0.0000605,0.0000543,0.0000597,0.0000575,0.0000392,0.0000173,0.0000109,0.0000132,0.0000158,0.0000169,0.0000137,0.0000286,0.0000356,0.000037,0.0000365,0.0000301,0.0000075,0.0000257,0.000036,0.0000332,0.0000285,0.0000299,0.000024,0.0000226,0.0000342,0.0000347,0.0000396,0.0000476,0.0000468,0.0000445,0.0000459,0.0000445,0.00004,0.0000427,0.0000405,0.0000267,0.00002,0.00002,0.0000068,0.0000334,0.0000703,0.0001007,0.0001298,0.0001404,0.0001389],"detections":[{"range_m":2.757947,"snr_db":26.4476,"width_m":0.175182}],"noise_floor":0.000038272,"blast_amplitude":0.2700154,"saturated":false}
{"timestamp":1756162801.4666653,"source":"simulated","device_id":"batvu-reference-01","beam":[0.4531539,-0.7848856,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000173,0.0000063,0,0,0.000055,0.0000592,0.0000512,0.0000335,0.000015,0.0000135,0.0000221,0.0000231,0,0,0.0000132,0.000008,0.0000097,0.0000184,0.0000065,0.000027,0.0000558,0.0000563,0.0000855,0.0001107,0.0000931,0.0000639,0.0000408,0.0000236,0.0000341,0.0000396,0.0000195,0.0000217,0.0000805,0.0000879,0.0000944,0.0000987,0.000097,0.0000445,0.0000747,0.0000803,0.0000611,0.0000347,0.0000215,0.0000504,0.0000624,0.0000632,0.0000215,0.0000097,0.0000295,0.0000259,0.0000319,0.0000401,0.0000232,0.000012,0.0000321,0.0000291,0.0000234,0.0000193,0.0000103,0.0000065,0.0000312,0.0000317,0.0000372,0.0000443,0.0000422,0.0000135,0.0000283,0.0000298,0.0000141,0.0000272,0.0000527,0.0000666,0.0000775,0.0000809,0.0000573,0.0000716,0.0000909,0.0000909,0.0000871,0.0000755,0.0000397,0.0000016,0.000017,0.0000131,0.0000315,0.0000635,0.0000653,0.0000668,0.0000719,0.000065,0.0000478,0.0000556,0.0000557,0.000047,0.0000447,0.0000443,0.0000109,0.0000094,0.0000216,0.0000249,0.0000337,0.0000403,0.0000359,0.0000384,0.0000412,0.0000302,0.0000315,0.0000353,0.0000227,0.0000075,0.0000269,0.0000231,0.0000043,0.0000762,0.0001693,0.0003327,0.0005886,0.0009894,0.0014031,0.0018314,0.0021677,0.0023661,0.0024007,0.0023664,0.0021422,0.0017866,0.0012878,0.0008633,0.0005092,0.0002557,0.0000834,0.0000211,0.0000378,0.0000337,0.0000251,0.0000161,0.0000018,0.0000101,0.0000168,0.000017,0.0000355,0.0000546,0.0000538,0.0000462,0.0000371,0.0000274,0.0000049,0.0000141,0.0000151,0.0000125,0.0000266,0.0000324,0.0000319,0.0000272,0.0000205,0.0000092,0.0000174,0.0000237,0.0000301,0.0000526,0.0000803,0.0000938,0.0000994,0.0000986,0.000078,0.0000486,0.0000468,0.0000513,0.0000552,0.0000556,0.0000472,0.0000293,0.0000212,0.0000138,0.0000104,0.0000275,0.0000327,0.000041,0.0000554,0.0000581,0.0000496,0.0000351,0.0000215,0.0000329,0.000054,0.0000591,0.0000516,0.0000399,0.0000389,0.0000357,0.0000352,0.0000359,0.0000269,0.0000218,0.0000352,0.000039,0.000047,0.0000573,0.0000566,0.0000496,0.0000525,0.000051,0.000038,0.0000232,0.0000155,0.0000339,0.0000542,0.0000569,0.0000525,0.0000539,0.0000561,0.0000473,0.0000359,0.0000296,0.0000212,0.0000365,0.0000547,0.0000659,0.0000841,0.0001043,0.0001064,0.0001056,0.0000957,0.0000776,0.0000569,0.0000554,0.000054,0.0000454,0.0000492,0.0000489,0.0000501,0.0000571,0.0000588,0.000059,0.0000679,0.0000706,0.0000549,0.0000274,0.0000309,0.0000534],"detections":[{"range_m":2.842285,"snr_db":28.1564,"width_m":0.171607}],"noise_floor":0.00003805,"blast_amplitude":0.2699913,"saturated":false}
{"timestamp":1756162801.5333319,"source":"simulated","device_id":"batvu-reference-01","beam":[0.2345697,-0.8754261,-0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000303,0.0000253,0.0000054,0,0.0000054,0.0000046,0.0000048,0.0000137,0.000014,0.000019,0.000022,0,0.0000073,0.0000141,0,0.0000096,0.000055,0.0000535,0.0000409,0.0000259,6e-7,0.000023,0.0000644,0.0000703,0.0000813,0.0000866,0.0000654,0.0000329,0.0000416,0.0000335,0.0000068,0.0000341,0.0000409,0.0000339,0.000037,0.0000352,0,0.0000384,0.000055,0.0000499,0.000057,0.0000619,0.0000411,0.0000243,0.0000241,0.0000126,0.0000049,0.0000238,0.0000219,0.0000319,0.0000591,0.0000679,0.0000775,0.0000839,0.0000747,0.000044,0.0000402,0.000031,0.0000189,0.000053,0.0000576,0.000056,0.0000501,0.000036,0.0000023,0.0000397,0.0000519,0.0000561,0.000076,0.0000911,0.0000882,0.0000855,0.0000813,0.000051,0.0000328,0.0000461,0.0000414,0.0000294,0.0000237,0.000003,0.0000168,0.0000545,0.0000602,0.000065,0.0000771,0.0000748,0.0000853,0.0001106,0.0001125,0.0001073,0.0001009,0.000092,0.0000472,0.000024,0.000018,0,0.0000217,0.0000506,0.000063,0.0000649,0.0000633,0.0000341,0.000007,0.0000199,0.0000212,0.0000309,0.0000626,0.0001315,0.0002843,0.0005303,0.0008524,0.0012662,0.0017246,0.0021912,0.0024461,0.0025224,0.0025092,0.0023259,0.0019959,0.0015854,0.0011378,0.0007403,0.0003856,0.0001772,0.0000659,0.0000428,0.0000428,0.0000564,0.0000651,0.0000536,0.000031,0.0000304,0.0000388,0.0000414,0.0000412,0.0000312,0.000018,0.0000345,0.0000343,0.0000322,0.0000286,0.0000256,0.0000171,0.0000173,0.0000129,4e-7,0.0000175,0.0000256,0.000032,0.0000408,0.0000446,0.0000389,0.0000561,0.0000683,0.0000699,0.0000718,0.0000747,0.0000694,0.0000873,0.0001006,0.0000999,0.0000972,0.0000953,0.0000874,0.0000705,0.0000629,0.000056,0.0000442,0.0000524,0.0000513,0.0000385,0.0000238,0.0000159,0.000031,0.0000476,0.0000511,0.0000482,0.0000525,0.0000559,0.0000539,0.0000737,0.0000844,0.0000844,0.0000819,0.0000763,0.0000589,0.0000383,0.0000282,0.0000167,0.0000122,0.0000393,0.0000558,0.0000702,0.0000788,0.0000769,0.0000612,0.0000484,0.0000446,0.0000332,0.0000318,0.0000325,0.0000209,0.0000178,0.0000193,0.0000103,0.0000154,0.0000345,0.0000412,0.0000415,0.0000367,0.000006,0.0000319,0.0000497,0.00005,0.0000471,0.0000409,0.0000284,0.0000084,0.0000103,0.0000103,0.0000168,0.000035,0.0000379,0.0000377,0.0000392,0.0000401,0.0000426,0.0000426,0.0000389,0.0000184,0.0000101,0.0000273,0.0000432,0.000061,0.00007,0.0000752],"detections":[{"range_m":2.793585,"snr_db":26.3236,"width_m":0.171607}],"noise_floor":0.000039334,"blast_amplitude":0.2699779,"saturated":false}
{"timestamp":1756162801.5999985,"source":"simulated","device_id":"batvu-reference-01","beam":[0.258819,-0.9659258,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000117,0.0000102,0.0000064,0.0000275,0.0000464,0.0000267,0.0000209,0.0000241,0,0.0000159,0.0000423,0.0000363,0.0000332,0.0000427,0.0000258,0.0000257,0.0000273,0,0,0.0000298,0.000025,0.0000133,0.0000272,0.0000464,0.0000654,0.0000718,0.0000499,0.0000209,0.000049,0.0000435,0.0000166,0.0000236,0.0000477,0.0000524,0.0000523,0.0000436,0,0,0.0000104,0.0000188,0.0000335,0.0000368,0.000011,0.0000092,0.0000285,0.0000255,0.000033,0.000042,0.0000261,0.0000258,0.0000475,0.0000429,0.0000301,0.000018,0.0000063,0.0000017,0.0000119,0.0000212,0.0000322,0.0000401,0.0000375,0.0000045,0.0000097,0.0000109,0,0.0000203,0.0000337,0.0000338,0.0000335,0.000033,0.0000026,6e-7,0.0000099,0.0000102,0.0000446,0.0000809,0.0000839,0.0000821,0.0000758,0.0000567,0.0000367,0.0000432,0.0000558,0.000082,0.0001072,0.0001044,0.0000914,0.0000991,0.0000976,0.0000753,0.0000565,0.0000449,0.0000123,0.0000256,0.000031,0.0000246,0.000019,0.0000195,0.0000076,0.0000334,0.0000475,0.0000441,0.0000316,0.0000173,3e-7,0,0.0000335,0.0000469,0.0000549,0.0000568,0.0000475,0.0000208,0.0000098,0.0000202,0.0000252,0.000027,0.0000238,0.0000043,0.0000118,0.000014,0.0000128,0.0000439,0.000053,0.0000526,0.0000471,0.0000371,0.0000081,0.000012,0.0000256,0.0000311,0.0000517,0.0000653,0.00006,0.0000282,0.0001362,0.000342,0.000586,0.0008849,0.0011987,0.001511,0.0017627,0.0018705,0.0018737,0.0017978,0.0015257,0.0011899,0.0008472,0.0005485,0.0002956,0.0001175,0.0000515,0.0000649,0.0000646,0.000055,0.0000285,0.0000366,0.0000467,0.0000439,0.0000414,0.0000478,0.0000451,0.0000422,0.0000459,0.0000421,0.0000347,0.0000336,0.0000257,0.0000235,0.0000504,0.0000541,0.0000533,0.0000464,0.0000359,0.0000044,0.0000168,0.0000284,0.0000311,0.000031,0.0000271,0.0000092,0.0000364,0.0000521,0.0000596,0.000069,0.0000742,0.0000674,0.0000525,0.0000446,0.0000394,0.0000306,0.0000196,0.0000275,0.000037,0.0000403,0.000038,0.0000408,0.0000596,0.0000617,0.0000642,0.0000686,0.0000695,0.0000579,0.0000501,0.0000481,0.0000345,0.0000366,0.0000425,0.0000413,0.000038,0.000035,0.0000332,0.0000503,0.0000673,0.0000721,0.000073,0.0000716,0.0000583,0.0000341,0.0000245,0.0000221,0.0000146,0.0000095,0.0000198,0.0000293,0.000035,0.0000328,0.0000201,0.0000218,0.0000234,0.0000179,0.0000193,0.0000233,0.0000219,0.0000215,0.0000209,0.0000095],"detections":[{"range_m":3.27492,"snr_db":23.9076,"width_m":0.171607}],"noise_floor":0.000032543,"blast_amplitude":0.2699602,"saturated":false}
{"timestamp":1756162801.666665,"source":"simulated","device_id":"batvu-reference-01","beam":[0.5,-0.8660254,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000019,0,0,0,0.0000652,0.0000679,0.0000514,0.0000287,0.0000146,0.0000044,0.0000127,0.0000193,0.0000025,0,0.0000168,0.0000115,0.0000016,0.0000272,0.0000401,0.000047,0.0000523,0.0000343,0.0000673,0.0000893,0.0000674,0.0000421,0.0000709,0.0000653,0.0000581,0.0000614,0.0000426,0.0000193,0.0000549,0.0000538,0.0000563,0.0000573,0.0000551,0.0000145,0.0000493,0.0000547,0.0000399,0.0000632,0.0000754,0.0000624,0.0000416,0.0000352,0.0000212,0.0000173,0.0000107,0.0000119,0.0000191,0.0000213,0,0.000006,0.0000299,0.0000262,0.0000168,0.0000318,0.000039,0.0000462,0.0000503,0.0000403,0.0000122,0.0000333,0.0000436,0.0000541,0.0000672,0.0000656,0.0000381,0.0000294,0.0000321,0.0000235,0.0000384,0.000049,0.0000429,0.0000627,0.0000786,0.0000772,0.0000741,0.0000686,0.0000449,0.0000251,0.0000353,0.0000289,0.0000163,0.000038,0.0000436,0.0000531,0.0000673,0.0000643,0.0000566,0.000068,0.0000678,0.0000593,0.0000661,0.0000677,0.0000461,0.0000598,0.0000676,0.000067,0.0000647,0.0000595,0.0000346,0.000034,0.0000407,0.0000331,0.000024,0.0000256,0.000016,0.0000096,0.0000414,0.0000517,0.0000582,0.0000595,0.0000498,0.0000252,0.0000219,0.00002,0,0.0000165,0.0000181,0.0000127,0.0000152,0.0000261,0.0000325,0.0000441,0.0000467,0.0000386,0.0000315,0.000024,0,0.0000137,0.0000248,0.00002,0.0000197,0.0000336,0.0000356,0.0000359,0.0000353,0.0000261,0.0000663,0.0001539,0.0002863,0.0005058,0.0008086,0.0011371,0.0014617,0.0017678,0.0018749,0.0018799,0.0018252,0.001647,0.0013535,0.0010161,0.0006912,0.0003549,0.0001635,0.0000578,0.0000216,0.000041,0.0000528,0.0000506,0.0000427,0.0000356,0.0000257,0.000016,0.0000206,0.0000191,0.0000189,0.0000236,0.0000197,0.0000198,0.0000363,0.0000368,0.0000306,0.0000191,0.0000068,0.0000161,0.000024,0.0000257,0.0000297,0.0000516,0.0000631,0.0000624,0.0000527,0.0000413,0.0000656,0.0000898,0.0000996,0.0000961,0.0000877,0.000084,0.0000712,0.000052,0.0000414,0.0000366,0.0000389,0.0000521,0.0000521,0.0000471,0.0000463,0.0000451,0.0000387,0.000037,0.0000366,0.0000206,0.000008,0.0000083,0.0000111,0.0000114,0.0000102,0.0000019,0.0000112,0.000016,0.0000086,0.0000016,0.0000096,0.0000199,0.0000407,0.0000615,0.0000652,0.0000735,0.0000839,0.0000832,0.0000752,0.0000602,0.0000395,0.0000119,0.0000143,0.0000238,0.0000292,0.0000298,0.000028,0.00001,0.0000049,0.0000264,0.0000548,0.0000803,0.0000896,0.0000879],"detections":[{"range_m":3.333622,"snr_db":26.3499,"width_m":0.171607}],"noise_floor":0.000036678,"blast_amplitude":0.2700387,"saturated":false}
{"timestamp":1756162801.7333317,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7071068,-0.7071068,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000137,0.000012,0.0000168,0.0000282,0.0000413,0.0000205,0,0.0000011,0.0000302,0.0000157,0.0000444,0.0000702,0.0000689,0.0000694,0.0000756,0.0000398,0.0000389,0.00004,0,0,0.000034,0.0000294,0.0000148,0.0000136,0.0000243,0.0000266,0.0000248,0.0000064,0.0000365,0.0000531,0.0000358,0.0000138,0.0000392,0.000033,0.0000022,0.0000256,0.0000384,0.0000361,0.0000251,0.0000082,0.0000105,0.0000134,0.0000139,0.0000089,0.0000327,0.0000453,0.0000434,0.0000446,0.0000441,0.0000099,0.0000069,0.0000191,0.0000011,0.0000112,0.0000458,0.000046,0.0000463,0.0000519,0.0000449,0.0000374,0.0000677,0.0000672,0.0000653,0.0000623,0.0000543,0.0000187,0.0000449,0.0000526,0.0000819,0.0001493,0.0002163,0.0002835,0.0003488,0.0003746,0.0003668,0.0003385,0.0002987,0.0002248,0.0001454,0.0000853,0.0000306,5e-7,0.0000299,0.0000353,0.0000362,0.0000348,0.0000174,0,0.000014,0.0000133,0.0000284,0.0000596,0.0000672,0.000073,0.0000774,0.0000779,0.0000488,0.0000523,0.0000564,0.0000491,0.000054,0.0000606,0.0000546,0.000047,0.0000471,0.0000319,0.0000185,0.0000322,0.0000422,0.0000491,0.0000495,0.0000291,0,0.0000144,0.0000151,0.0000304,0.0000583,0.0000607,0.0000572,0.0000487,0.0000336,0.0000013,0.0000108,0.0000142,0.0000085,0.00002,0.0000232,0.0000158,0.0000284,0.0000533,0.0000673,0.0000746,0.0000749,0.0000522,0.0000326,0.000052,0.000062,0.0000683,0.0000683,0.0000493,0.0000675,0.0001936,0.0003584,0.0005937,0.0008879,0.0011807,0.0014459,0.00166,0.0016919,0.0016765,0.0015576,0.0013459,0.0010596,0.0007694,0.0005193,0.0002829,0.000163,0.0001076,0.0000769,0.0000655,0.0000681,0.0000602,0.0000546,0.0000609,0.0000563,0.0000461,0.0000365,0.0000233,0.000007,0.0000026,0.0000049,0.0000082,0.0000189,0.0000214,0.0000284,0.000043,0.0000546,0.0000659,0.0000753,0.0000765,0.0000625,0.0000529,0.0000542,0.000044,0.0000327,0.0000248,0.0000079,0.0000087,0.0000285,0.0000341,0.0000386,0.0000459,0.0000505,0.0000616,0.0000703,0.0000679,0.0000655,0.0000768,0.0000766,0.0000691,0.0000543,0.0000364,0.0000246,0.0000408,0.0000437,0.0000397,0.0000422,0.0000433,0.0000309,0.0000175,0.0000298,0.0000469,0.0000656,0.0000779,0.000081,0.0000888,0.0000936,0.0000878,0.0000734,0.0000582,0.00004,0.000022,0.0000253,0.0000256,0.0000312,0.00004,0.0000394,0.0000332,0.0000256,0.0000074,0.0000297,0.0000488,0.0000515,0.0000443,0.0000323,0.0000266,0.0000329,0.0000435,0.0000465,0.000038],"detections":[{"range_m":1.942919,"snr_db":9.2414,"width_m":0.150156},{"range_m":3.323008,"snr_db":20.8997,"width_m":0.171607}],"noise_floor":0.000040071,"blast_amplitude":0.2700149,"saturated":false}
{"timestamp":1756162801.7999983,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8660254,-0.5,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0001062,0.0001065,0.0001062,0.0001054,0.0001035,0.0000774,0,0.0000038,0.0000446,0.0000358,0.0000228,0.0000188,0.0000324,0.0000519,0.0000599,0.0000109,0.0000363,0.0000586,0.0000449,0.0000293,0.0000307,0.0000318,0.0000525,0.0000678,0.0000445,0.0000548,0.0000929,0.000085,0.0000593,0.0000318,0.0000402,0.0000567,0.0000664,0.0000562,0.0000174,0.0000288,0.0000332,0.0000123,0.0000106,0.0000139,0.0000035,0,0.0000173,0.0000226,0.0000251,0.0000259,0.0000126,0.0000417,0.0000605,0.0000518,0.0000438,0.0000643,0.0000617,0.0000607,0.0000581,0.000036,0.0000151,0.0000263,0.0000216,0.0000122,0.0000449,0.0000498,0.0000545,0.0000555,0.0000508,0.0000114,0.0000396,0.000046,0.0000726,0.0001508,0.0002531,0.0003889,0.0005567,0.000723,0.0008033,0.0008289,0.0008266,0.0007529,0.0006294,0.0004972,0.0003537,0.0001926,0.0001037,0.0000394,0.0000046,0.0000149,0.0000135,0.0000097,0.0000153,0.0000132,0.0000091,0.0000153,0.0000152,0.0000157,0.0000251,0.0000274,0.0000331,0.0000723,0.0000891,0.0000892,0.0000812,0.0000621,0.0000252,0.0000387,0.0000448,0.0000338,0.0000388,0.0000603,0.0000634,0.0000641,0.0000639,0.0000492,0.0000398,0.0000517,0.0000491,0.0000382,0.0000506,0.000052,0.0000525,0.0000575,0.0000566,0.0000609,0.0000729,0.000075,0.0000599,0.0000477,0.0000493,0.0000489,0.0000585,0.000063,0.0000565,0.0000639,0.0000699,0.0001042,0.0002353,0.0004372,0.0006797,0.0009529,0.0012115,0.0014189,0.0014911,0.0014927,0.0014249,0.0012436,0.0010042,0.0007468,0.0004932,0.0002947,0.0001383,0.0000569,0.0000483,0.0000505,0.000041,0.0000453,0.0000498,0.0000391,0.0000273,0.0000221,0.0000211,0.0000362,0.0000481,0.0000466,0.0000408,0.0000331,0.0000181,0.0000288,0.0000647,0.0000819,0.0000887,0.0000886,0.0000719,0.000047,0.0000426,0.0000398,0.0000186,0.0000078,0.0000232,0.0000355,0.0000504,0.0000536,0.0000555,0.0000689,0.0000756,0.0000729,0.0000676,0.0000636,0.0000498,0.0000443,0.0000492,0.0000442,0.0000355,0.0000311,0.0000196,0.0000301,0.0000653,0.0000827,0.0000916,0.0000928,0.0000884,0.0000655,0.0000453,0.0000344,0.0000264,0.000049,0.0000607,0.0000624,0.0000614,0.0000521,0.0000273,0.0000173,0.0000188,0.0000093,0,0.0000153,0.0000302,0.0000515,0.0000691,0.0000772,0.0000878,0.0000941,0.0000891,0.0000676,0.000035,0.0000134,0.0000333,0.0000525,0.0000584,0.0000704,0.0000929,0.0000983,0.0001041,0.0001082,0.0001082,0.0000887,0.0000649,0.0000452,0.0000246,0.0000367,0.0000536,0.0000613],"detections":[{"range_m":1.986331,"snr_db":17.0724,"width_m":0.171607},{"range_m":3.184895,"snr_db":20.1425,"width_m":0.171607}],"noise_floor":0.00004538,"blast_amplitude":0.2699941,"saturated":false}
{"timestamp":1756162801.866665,"source":"simulated","device_id":"batvu-reference-01","beam":[0.9659258,-0.258819,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000103,0.0000375,0.0000249,0,0.000012,0.0000755,0.0000843,0.0000889,0.0000893,0.0000262,0.0000417,0.0000676,0.0000523,0.000036,0.0000222,0,0.0000025,0.0000144,0.0000047,0,0.0000209,0.0000333,0.0000441,0.0000492,0.0000253,0.0000013,0.000041,0.0000347,0.0000228,0.000048,0.0000449,0.0000375,0.0000354,0.0000339,0,0.0000052,0.000013,0.0000102,0.0000274,0.0000459,0.0000601,0.0000711,0.0000726,0.0000363,0.0000179,0.0000302,0.0000207,0.0000182,0.0000364,0.000032,0.0000416,0.0000509,0.000039,0.0000255,0.0000666,0.0000699,0.0000686,0.0000591,0.0000325,0,1e-7,2e-7,0,0.0000236,0.0000384,0.0000929,0.0002118,0.0003516,0.0005071,0.0006679,0.0007945,0.0008294,0.0008301,0.0008018,0.0006985,0.0005622,0.0004353,0.0003131,0.0001889,0.0001283,0.0000804,0.0000445,0.0000419,0.0000383,0.0000532,0.0000996,0.000111,0.0001182,0.0001197,0.000115,0.0000808,0.0000637,0.0000655,0.0000474,0.0000374,0.0000353,0.0000195,0.000026,0.0000305,0.0000196,0.0000226,0.0000292,0.0000219,0.0000103,0.0000076,0.0000066,0.0000116,0.0000225,0.000018,0.0000747,0.0002016,0.0003768,0.0006297,0.0009458,0.0013221,0.0016017,0.0017941,0.0018352,0.0018208,0.0016935,0.0014603,0.0011435,0.0008274,0.0005176,0.0003147,0.000184,0.0001121,0.0000585,0.000026,0.0000343,0.0000368,0.0000392,0.0000416,0.0000336,0.0000423,0.0000669,0.0000732,0.0000739,0.000072,0.0000559,0.0000272,0.0000231,0.0000228,0.0000166,0.000019,0.0000216,0.0000333,0.000049,0.0000525,0.0000569,0.0000739,0.0000806,0.0000703,0.0000511,0.0000363,0.0000369,0.0000415,0.0000417,0.0000272,0.0000113,0.0000198,0.000017,0.0000092,0.0000239,0.0000319,0.0000421,0.0000552,0.0000539,0.0000492,0.0000482,0.0000455,0.000029,0.0000303,0.00004,0.0000445,0.0000475,0.0000483,0.0000443,0.0000579,0.0000644,0.0000626,0.0000725,0.0000777,0.0000748,0.0000687,0.0000591,0.0000366,0.0000248,0.0000377,0.0000363,0.0000322,0.000029,0.0000175,0.0000091,0.0000367,0.000043,0.0000434,0.0000429,0.000041,0.0000384,0.0000503,0.000054,0.0000601,0.0000768,0.0000806,0.0000796,0.0000784,0.0000761,0.0000589,0.0000419,0.0000369,0.0000284,0.0000207,0.0000238,0.0000209,0.0000155,0.0000113,0.0000188,0.0000289,0.0000349,0.0000331,0.0000445,0.0000613,0.0000619,0.0000577,0.000049,0.0000333,0.0000117,0.0000293,0.0000461,0.0000596,0.0000693,0.0000713,0.0000613,0.0000485,0.0000457,0.0000343],"detections":[{"range_m":1.972917,"snr_db":13.4923,"width_m":0.168032},{"range_m":2.809088,"snr_db":23.5471,"width_m":0.171607}],"noise_floor":0.000036602,"blast_amplitude":0.2699966,"saturated":false}
{"timestamp":1756162801.9333315,"source":"simulated","device_id":"batvu-reference-01","beam":[1,0,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000647,0.0000395,0,0,0.0000399,0.0000476,0.0000476,0.0000455,0.0000474,0.0000077,0.0000181,0.0000302,0.0000192,0.0000244,0.0000281,0,0,0.0000116,0,0.0000155,0.000066,0.0000795,0.000084,0.0000838,0.000037,0.0000062,0.0000486,0.0000462,0.0000483,0.0000513,0.0000274,0,0.0000252,0.0000213,0.0000034,0.0000018,0.0000097,0.0000045,0.0000417,0.0000545,0.0000593,0.000061,0.0000607,0.0000148,0.000007,0.0000201,0.0000087,0.0000254,0.000058,0.0000614,0.0000613,0.0000587,0.000026,0.0000192,0.0000459,0.0000442,0.0000393,0.0000324,0.0000195,0.0000257,0.0000352,0.000027,0,0.0000208,0.0000247,0.0000183,0.0000244,0.000063,0.0001256,0.0002194,0.0003196,0.0004518,0.0006201,0.0007829,0.0008471,0.0008542,0.0008346,0.0007291,0.0005878,0.00046,0.0003386,0.0002081,0.0001342,0.0000704,0.0000344,0.000063,0.0000632,0.0000649,0.0000708,0.0000645,0.0000671,0.0001017,0.0001058,0.0001028,0.000088,0.0000625,0.0000043,0.0000351,0.0000424,0.0000488,0.0000777,0.000098,0.0000988,0.0000951,0.0000872,0.0001527,0.0003149,0.0005536,0.0008518,0.0012124,0.0016506,0.0019343,0.0021077,0.0021418,0.0021088,0.0019222,0.0016278,0.0012783,0.0008434,0.0005507,0.0003389,0.0001846,0.0001015,0.0000678,0.0000397,0.0000602,0.0000689,0.0000686,0.0000629,0.0000505,0.0000268,0.0000433,0.0000524,0.0000437,0.000038,0.000043,0.0000355,0.0000206,0.0000109,0.0000154,0.0000203,0.0000239,0.0000185,0.0000078,0.0000137,0.0000181,0.0000322,0.0000563,0.0000577,0.0000633,0.0000737,0.0000757,0.0000632,0.0000494,0.0000381,0.0000355,0.0000603,0.0000702,0.000067,0.0000581,0.000051,0.0000388,0.0000605,0.0000851,0.0000909,0.0000917,0.0000908,0.0000778,0.0000506,0.000033,0.000032,0.0000403,0.0000457,0.0000427,0.000016,0.0000312,0.0000547,0.0000614,0.0000691,0.0000713,0.0000673,0.0000645,0.0000598,0.0000395,0.000022,0.0000179,0.0000219,0.0000442,0.000062,0.0000623,0.000057,0.000042,0.0000088,0.0000235,0.0000355,0.0000343,0.0000381,0.0000614,0.0000744,0.0000862,0.0000884,0.000085,0.0000657,0.0000675,0.0000701,0.0000657,0.0000576,0.0000494,0.0000354,0.0000312,0.0000288,0.0000104,0.0000103,0.000028,0.0000363,0.0000484,0.0000558,0.000053,0.0000467,0.0000435,0.0000356,0.0000154,0.0000222,0.0000345,0.0000417,0.0000442,0.0000419,0.0000287,0.000036,0.0000408,0.0000554,0.0000745,0.0000779,0.0000708,0.0000507,0.0000401,0.0000617,0.0000734,0.000074,0.0000585],"detections":[{"range_m":1.977967,"snr_db":15.2254,"width_m":0.168032},{"range_m":2.678728,"snr_db":20.6919,"width_m":0.175182}],"noise_floor":0.000040832,"blast_amplitude":0.2699939,"saturated":false}
{"timestamp":1756162801.999998,"source":"simulated","device_id":"batvu-reference-01","beam":[0.9659258,0.258819,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00002,0.0000234,0.0000197,0.0000269,0.0000337,0,0.0000229,0.000058,0.0000589,0.0000563,0.000045,0,0.0000206,0.000029,0,0.0000038,0.0000388,0.0000339,0.0000199,0.000009,0.0000245,0.0000339,0.0000352,0.0000102,0.0000303,0.0000681,0.0000568,0.000031,0.0000181,0.0000079,0,0.0000465,0.0000559,0.0000517,0.0000453,0.0000441,0.0000162,0.0000185,0.0000297,0.0000371,0.0000446,0.0000461,0.0000158,0.0000388,0.0000682,0.0000743,0.0000786,0.0000789,0.000045,0.0000171,0.0000339,0.0000283,0.0000282,0.0000443,0.0000401,0.0000256,0.0000431,0.0000399,0.0000256,0.0000146,0.0000094,0.0000062,0.0000376,0.00005,0.0000662,0.0000895,0.000095,0.0000787,0.0000568,0.0000403,0.0000085,0.0000079,0.0000427,0.0000613,0.0000755,0.000081,0.0000673,0.0000526,0.0000642,0.0000588,0.0000466,0.0000392,0.000032,0.0000314,0.0000655,0.0000686,0.0000688,0.000066,0.0000534,0.0000165,0.0000133,0.0000179,0.0000129,0.0000146,0.0000154,0.0000148,0.0000475,0.0000744,0.0000878,0.000095,0.0000962,0.0000753,0.0000505,0.0000353,0.0000142,0.0000117,0.0000645,0.0001429,0.0002986,0.0005424,0.0008519,0.0012387,0.0016612,0.0020918,0.0023366,0.0024222,0.0024139,0.0022551,0.0019503,0.001561,0.0011316,0.0007522,0.0004186,0.0002234,0.0001178,0.0000866,0.0000724,0.0000639,0.0000715,0.0000753,0.0000876,0.0000959,0.0000908,0.0000806,0.0000738,0.0000585,0.000025,0.0000212,0.0000175,0.0000011,0.0000439,0.0000635,0.0000694,0.0000689,0.0000535,0.0000264,0.0000466,0.0000523,0.0000581,0.0000742,0.000082,0.0000763,0.0000638,0.0000472,0.0000172,0.0000277,0.0000388,0.000036,0.0000281,0.0000292,0.0000259,0.0000256,0.0000287,0.0000246,0.0000281,0.0000438,0.0000428,0.0000367,0.0000428,0.0000478,0.0000601,0.0000756,0.0000786,0.0000727,0.0000674,0.0000627,0.000043,0.0000404,0.0000466,0.0000514,0.0000648,0.00007,0.0000665,0.000065,0.0000663,0.0000567,0.0000384,0.0000261,0.0000332,0.0000429,0.0000492,0.0000459,0.0000434,0.0000561,0.0000565,0.0000593,0.0000672,0.0000665,0.0000672,0.0000796,0.0000821,0.0000762,0.0000683,0.0000677,0.0000603,0.0000536,0.0000411,0.0000098,0.000024,0.0000371,0.0000361,0.0000377,0.0000431,0.0000475,0.0000654,0.0000855,0.0000869,0.0000856,0.0000757,0.0000555,0.0000248,0.0000167,0.0000278,0.0000372,0.0000483,0.0000476,0.000045,0.0000552,0.0000578,0.0000559,0.0000575,0.0000596,0.0000539,0.0000549,0.0000587,0.0000573],"detections":[{"range_m":2.794828,"snr_db":22.1958,"width_m":0.171607}],"noise_floor":0.000046455,"blast_amplitude":0.2700394,"saturated":false}
{"timestamp":1756162802.0666647,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8660254,0.5,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000148,0.0000266,0.0000302,0.0000303,0.000031,0,0.0000012,0.0000146,0.0000089,0.0000074,0.0000054,0.0000031,0.000007,0.0000081,0,0.0000017,0.0000062,0,0,0.0000226,0.0000202,0.0000169,0.0000165,0,0,0.0000567,0.000064,0.0000686,0.0000706,0.0000576,0.0000123,0.0000176,0.0000251,0.0000224,0.0000321,0.0000341,0.0000186,0.0000321,0.0000397,0.0000253,0.0000148,0.0000118,0.0000109,0.0000199,0.0000253,0.0000108,0.0000094,0.0000248,0.0000208,0.0000452,0.0000805,0.0000849,0.0000851,0.0000815,0.0000584,0.0000266,0.0000433,0.0000386,0.0000212,0.0000412,0.0000426,0.0000261,0.0000377,0.0000412,0.0000406,0.00004,0.0000368,0,0.0000159,0.0000336,0.0000298,0.0000262,0.00003,0.0000191,0.0000182,0.0000385,0.0000408,0.0000456,0.0000552,0.000052,0.0000514,0.0000506,0.0000348,0.000009,0.0000313,0.0000292,0.0000178,0.0000168,0.0000243,0.0000325,0.0000388,0.00004,0.0000229,0.0000442,0.0000521,0.0000511,0.000049,0.000044,0.0000176,0.0000229,0.0000349,0.0000369,0.0000433,0.0000468,0.0000337,0.000011,0.0000588,0.0000855,0.0001071,0.000116,0.0001081,0.00008,0.0000598,0.0000482,0.0000201,0.0000128,0.0000102,0,0.0000229,0.0000359,0.0000423,0.0000493,0.0000621,0.0001617,0.0003655,0.0006496,0.0009948,0.0013773,0.0017909,0.0020263,0.0021271,0.0021282,0.0020198,0.0017529,0.0013953,0.0010078,0.0005898,0.0003492,0.0001998,0.0001098,0.0000691,0.0000508,0.0000273,0.0000309,0.0000302,0.0000198,0.0000132,0.0000165,0.0000162,0.0000151,0.0000118,0.0000104,0.0000168,0.0000187,0.0000072,0.0000073,0.0000175,0.0000162,0.0000196,0.0000337,0.0000434,0.0000548,0.0000606,0.0000546,0.0000356,0.0000339,0.0000328,0.0000288,0.0000303,0.000029,0.0000225,0.0000323,0.0000348,0.0000241,0.0000114,0.000031,0.0000442,0.0000523,0.0000546,0.0000445,0.0000318,0.000015,0.0000197,0.0000414,0.0000553,0.0000572,0.0000639,0.0000724,0.0000693,0.0000635,0.0000599,0.0000544,0.0000508,0.0000588,0.0000578,0.0000493,0.0000477,0.0000459,0.0000349,0.000029,0.000027,0.0000153,0.0000302,0.000037,0.0000494,0.0000738,0.0000921,0.0000995,0.0001049,0.0001084,0.0001019,0.0000973,0.0000956,0.0000831,0.0000632,0.0000486,0.0000403,0.0000505,0.0000565,0.0000523,0.0000376,0.0000245,0.0000126,0.0000211,0.0000422,0.0000427,0.0000382,0.00003,0.0000198,0.0000065,0.0000254,0.000039,0.00005,0.0000656,0.0000711,0.0000664],"detections":[{"range_m":3.073406,"snr_db":23.4035,"width_m":0.175182}],"noise_floor":0.00003081,"blast_amplitude":0.2699623,"saturated":false}
{"timestamp":1756162802.1333313,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7071068,0.7071068,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000179,0.0000468,0.0000735,0.0000897,0.0000917,0.0000641,0,0.0000099,0.0000424,0.0000334,0.0000369,0.000039,0,0,0.0000125,0.0000095,0.000033,0.0000515,0.000037,0.0000369,0.0000553,0.0000404,0.0000259,0.0000308,0.0000228,0.00003,0.0000328,0.000008,0,0.0000146,0.000009,0.0000037,0.0000224,0.0000188,0.0000229,0.000055,0.0000618,0.0000558,0.0000638,0.0000638,0.0000337,0.0000588,0.0000706,0.0000586,0.0000485,0.0000485,0.0000162,0.0000363,0.0000565,0.0000476,0.0000266,0.0000265,0.0000353,0.0000361,0.0000339,0.0000158,0.0000257,0.0000391,0.0000344,0.0000218,0.0000253,0.0000156,0.0000157,0.0000559,0.0000618,0.0000615,0.0000586,0.0000508,0.0000138,0.0000107,0.0000218,0.000033,0.0000511,0.0000586,0.000043,0.0000501,0.0000694,0.0000744,0.0000775,0.0000775,0.0000567,0.0000286,0.0000413,0.0000361,0.0000224,0.0000205,0.0000193,0.0000184,0.0000177,0.000017,0.0000321,0.0000509,0.0000513,0.0000489,0.0000702,0.0000771,0.0000719,0.0000699,0.0000706,0.0000519,0.0000705,0.0000852,0.0000848,0.0000794,0.0000701,0.0000387,0.0000155,0.0000238,0.0000191,0.0000096,0.0000222,0.00003,0.0000489,0.0000751,0.0000786,0.0000792,0.000078,0.0000686,0.0000418,0.0000576,0.0000573,0.0000447,0.0000441,0.0000463,0.0000328,0.0000154,0.0000086,0.000009,0.0000212,0.0000475,0.0000617,0.0000648,0.0000625,0.0000291,0.0000236,0.0000364,0.00004,0.000088,0.0001989,0.000411,0.0006833,0.0010174,0.0013495,0.001646,0.0018497,0.0018988,0.0018876,0.0017634,0.0014618,0.0011188,0.0007763,0.0004859,0.0002579,0.0001271,0.0000833,0.000076,0.00009,0.0000953,0.0000876,0.0000749,0.0000654,0.0000489,0.0000461,0.000057,0.0000547,0.0000448,0.0000322,0.000018,0.0000221,0.0000321,0.0000285,0.0000185,0.0000208,0.0000189,0.0000043,0.0000108,0.0000156,0.0000122,0.0000084,0.0000105,0.0000188,0.0000407,0.0000587,0.0000671,0.0000757,0.0000781,0.0000684,0.0000582,0.0000581,0.0000542,0.0000654,0.0000827,0.0000852,0.000086,0.0000856,0.000075,0.0000514,0.0000348,0.0000268,0.0000221,0.0000325,0.0000321,0.000025,0.0000222,0.0000233,0.0000152,0.0000261,0.0000334,0.0000341,0.0000337,0.0000341,0.0000258,0.0000178,0.0000172,0.0000313,0.0000424,0.0000447,0.0000346,0.0000138,0.0000167,0.000033,0.0000572,0.0000731,0.0000727,0.0000667,0.0000612,0.0000597,0.0000521,0.0000472,0.0000429,0.0000342,0.0000321,0.0000293,0.0000107,0.0000377,0.0000594,0.0000611,0.0000581,0.0000448,0.000037],"detections":[{"range_m":3.26781,"snr_db":21.9042,"width_m":0.171607}],"noise_floor":0.000039872,"blast_amplitude":0.2699689,"saturated":false}
{"timestamp":1756162802.199998,"source":"simulated","device_id":"batvu-reference-01","beam":[0.5,0.8660254,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000009,0.0000061,4e-7,0,0.0000175,0.0000255,0.0000304,0.0000352,0.0000399,0,0.0000337,0.0000607,0.0000608,0.0000593,0.0000554,0,0.0000124,0.0000517,0.0000651,0.0000774,0.0000828,0.0000455,0.0000376,0.0000733,0.0000706,0.0000686,0.0000671,0.0000362,0,0.0000313,0.000023,0.0000028,0.000028,0.0000315,0.0000318,0.0000306,0.000024,0,0.0000053,0.0000056,0,0.0000334,0.0000516,0.0000478,0.0000367,0.0000306,0,0.0000328,0.0000801,0.0001036,0.0001503,0.0002442,0.0003295,0.0004269,0.0005005,0.0005198,0.0005278,0.0005281,0.0005042,0.0004084,0.0003189,0.0002186,0.000109,0.0000472,0.0000229,0,0.0000109,0.00001,0,0.0000293,0.0000486,0.0000578,0.0000679,0.0000714,0.0000474,0.0000512,0.0000612,0.0000513,0.000032,0.0000233,0.0000193,0.0000094,0.0000283,0.0000446,0.0000543,0.0000566,0.0000465,0.0000268,0.0000613,0.0000665,0.0000674,0.0000649,0.0000487,0.0000029,0.0000298,0.000042,0.0000567,0.0000859,0.0000998,0.0001079,0.0001159,0.0001175,0.0000969,0.0000721,0.0000689,0.0000494,0.0000297,0.0000524,0.0000614,0.0000665,0.0000675,0.0000531,0.000033,0.0000296,0.0000227,0.0000064,0.0000304,0.0000354,0.0000366,0.0000401,0.0000381,0.0000264,0.0000408,0.0000459,0.0000436,0.0000403,0.0000336,0.0000097,0.0000114,0.0000141,0.0000024,0.0000091,0.0000274,0.0000304,0.0000321,0.0000322,0.0000192,0.0000176,0.0000345,0.0000336,0.0000244,0.0000333,0.0000652,0.0001371,0.0002642,0.0004341,0.0006711,0.0010202,0.0012919,0.0015116,0.0016357,0.0016479,0.0015996,0.0014403,0.0012047,0.0008586,0.0005831,0.0003582,0.0001789,0.0000593,0.0000266,0.0000412,0.0000539,0.0000588,0.0000509,0.0000365,0.0000301,0.0000244,0.0000108,0.0000241,0.0000283,0.0000289,0.0000273,0.0000193,0.0000174,0.0000325,0.0000353,0.0000325,0.0000397,0.0000412,0.0000299,0.0000199,0.000018,0.0000131,0.0000411,0.0000654,0.0000796,0.0000894,0.0000932,0.0000862,0.0000772,0.0000779,0.0000685,0.0000491,0.0000284,0.000017,0.000039,0.0000563,0.0000562,0.0000494,0.0000454,0.0000429,0.0000274,0.0000205,0.0000232,0.0000315,0.0000497,0.0000537,0.0000534,0.0000537,0.000053,0.0000345,0.0000098,0.0000313,0.0000407,0.0000444,0.0000446,0.0000346,0.0000215,0.0000238,0.0000215,0.0000156,0.0000138,0.0000106,0.0000197,0.0000442,0.0000605,0.0000775,0.0000924,0.0000913,0.0000794,0.0000673,0.000057,0.0000322,0.0000174,0.0000278,0.0000307,0.000031,0.000031,0.0000204],"detections":[{"range_m":1.640507,"snr_db":13.9003,"width_m":0.171607},{"range_m":3.370651,"snr_db":25.5498,"width_m":0.175182}],"noise_floor":0.000034518,"blast_amplitude":0.2699966,"saturated":false}
{"timestamp":1756162802.2666645,"source":"simulated","device_id":"batvu-reference-01","beam":[0.258819,0.9659258,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000394,0.000043,0.0000309,0.0000135,0.0000092,0.000012,0.0000115,0.0000088,0.0000246,0.0000385,0.0000428,0,0.000001,0.0000068,0,0.000034,0.0000698,0.000061,0.00004,0.0000339,0.0000137,0.0000112,0.0000216,0.0000091,0,0.0000247,0.0000229,0.000021,0.0000173,0,0.0000054,0.0000145,0.0000143,0,0.0000145,0.00002,0.0000066,0.0000071,0.0000389,0.0000598,0.000078,0.0000819,0.0000572,0.0000691,0.0000981,0.0001263,0.0001913,0.0002943,0.0003882,0.0005154,0.0006329,0.000683,0.0006911,0.0006816,0.0006154,0.0004661,0.0003577,0.0002628,0.0001628,0.0000983,0.0000639,0.0000187,0.0000294,0.0000385,0.0000398,0.0000396,0.0000374,0.0000058,0.0000041,0.0000158,0.0000128,0.0000208,0.0000265,0.0000168,0.0000223,0.0000395,0.0000365,0.000026,0.0000187,0.0000176,0.0000242,0.0000272,0.0000176,0,0.0000232,0.0000213,0.0000195,0.0000505,0.0000553,0.0000541,0.0000434,0.0000242,0.0000347,0.0000556,0.0000588,0.0000451,0.0000468,0.0000519,0.0000384,0.0000097,0.0000258,0.0000347,0.000036,0.0000354,0.0000214,0.000036,0.0000682,0.0000775,0.000091,0.0001075,0.0001067,0.0001079,0.0001105,0.0001072,0.000078,0.0000663,0.0000634,0.0000512,0.0000677,0.0000718,0.0000635,0.0000514,0.0000515,0.0000532,0.0000581,0.0000598,0.0000457,0.0000319,0.0000351,0.0000451,0.0000576,0.000063,0.0000534,0.0000371,0.0000598,0.0001108,0.0002009,0.0003442,0.0005346,0.0007944,0.0010935,0.0013541,0.0015428,0.0016226,0.0016151,0.0015021,0.0013026,0.0010569,0.00078,0.0005289,0.0003322,0.0001663,0.0001041,0.0000867,0.0000629,0.000037,0.0000181,0.0000094,0.0000186,0.0000242,0.0000251,0.0000368,0.0000479,0.0000462,0.0000443,0.0000529,0.0000494,0.0000378,0.0000285,0.0000191,0.0000012,0.0000231,0.0000295,0.0000281,0.0000224,0.0000182,0.0000202,0.000027,0.0000288,0.0000177,0.0000124,0.0000157,0.0000091,5e-7,0.0000091,0.0000099,0.0000096,0.0000081,0.0000047,0.0000168,0.00004,0.0000537,0.0000669,0.0000752,0.0000735,0.0000613,0.0000639,0.0000626,0.0000502,0.0000365,0.0000249,0.0000143,0.000026,0.0000279,0.0000253,0.0000384,0.000048,0.0000526,0.0000604,0.0000657,0.0000599,0.0000568,0.0000609,0.0000573,0.0000593,0.0000734,0.0000802,0.00009,0.0000945,0.0000898,0.0000751,0.0000617,0.0000474,0.0000235,0.0000264,0.0000262,0.0000174,0.0000235,0.0000537,0.0000802,0.000102,0.0001094,0.0001075,0.0001057,0.0001056,0.0000928],"detections":[{"range_m":1.629893,"snr_db":16.9165,"width_m":0.171607},{"range_m":3.30911,"snr_db":20.815,"width_m":0.175182}],"noise_floor":0.000040869,"blast_amplitude":0.2699916,"saturated":false}
{"timestamp":1756162802.333331,"source":"simulated","device_id":"batvu-reference-01","beam":[0,1,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000313,0.000023,0.0000081,0,0.0000527,0.0000721,0.0000841,0.0000858,0.0000841,0.00001,0.0000109,0.0000316,0.0000181,0.0000289,0.0000514,0.0000456,0.0000475,0.0000482,0,2e-7,0.0000377,0.0000328,0.0000291,0.0000448,0.0000299,0.0000473,0.0000937,0.0000939,0.0000921,0.000078,0.0000295,0,0.0000317,0.0000277,0.0000331,0.000062,0.0000664,0.0000392,0.000031,0.0000301,0,0.0000194,0.0000379,0.0000339,0.0000168,0.0000206,0.0000348,0.0000379,0.0000354,0.0000265,0.0000977,0.0001994,0.0002905,0.0004165,0.0005346,0.0005874,0.0005984,0.0005926,0.0005343,0.0003968,0.000299,0.0002134,0.0001178,0.0000488,0.0000182,0.0000374,0.0000446,0.0000418,0.0000112,0.0000269,0.0000365,0.0000328,0.0000281,0.0000223,0.0000045,0.0000186,0.0000241,0.0000098,0,0.0000133,0.000011,0.0000138,0.0000309,0.0000346,0.0000437,0.0000569,0.0000547,0.0000578,0.0000663,0.0000582,0.0000332,0.0000301,0.0000286,0.000008,0.000005,0.0000143,0.0000121,0.0000086,0.0000083,0,0.0000104,0.000021,0.0000175,0.0000294,0.0000434,0.0000434,0.0000415,0.0000366,0.0000233,0.0000312,0.0000425,0.0000359,0.0000291,0.0000449,0.0000443,0.0000427,0.0000421,0.0000385,0.0000164,0.0000381,0.000043,0.0000476,0.0000531,0.0000542,0.0000415,0.000066,0.0000733,0.000073,0.0000713,0.0000687,0.000048,0.0000312,0.0000293,0.000023,0.0001326,0.000307,0.0005341,0.0008192,0.0011287,0.0014517,0.0016511,0.0017366,0.0017334,0.0016363,0.0014251,0.0011409,0.0008236,0.0005486,0.0003074,0.0001608,0.0000743,0.0000369,0.000017,0.0000302,0.0000374,0.0000302,0.0000151,0.0000172,0.0000284,0.0000375,0.0000444,0.0000423,0.0000475,0.0000512,0.0000445,0.0000489,0.0000652,0.0000649,0.0000605,0.0000529,0.000036,0.0000137,0.0000193,0.00002,0.0000162,0.0000264,0.0000433,0.0000502,0.0000512,0.0000498,0.0000281,0.0000132,0.0000191,0.0000246,0.000037,0.0000432,0.0000423,0.0000423,0.0000407,0.0000268,0.0000241,0.0000418,0.0000423,0.0000418,0.0000382,0.0000255,0.0000091,0.0000289,0.0000382,0.0000543,0.0000707,0.0000713,0.0000749,0.0000868,0.0000901,0.0000882,0.0000854,0.0000803,0.000061,0.000056,0.00006,0.000057,0.000055,0.0000572,0.0000529,0.0000631,0.00007,0.0000656,0.0000522,0.0000358,0.0000131,0.0000204,0.0000401,0.0000465,0.0000554,0.0000643,0.0000629,0.0000483,0.0000292,0.0000225,0.0000334,0.0000378,0.0000376,0.0000186,0.0000076,0.000031,0.0000466,0.0000637,0.00007,0.0000672],"detections":[{"range_m":1.631952,"snr_db":17.1802,"width_m":0.168032},{"range_m":3.199946,"snr_db":22.4903,"width_m":0.175182}],"noise_floor":0.000040592,"blast_amplitude":0.2699973,"saturated":false}
{"timestamp":1756162802.3999977,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.258819,0.9659258,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000321,0.0000152,0,0,0.0000349,0.0000405,0.0000357,0.0000229,0.0000286,0.0000224,0.0000289,0.0000307,0,0.0000313,0.0000777,0.0000858,0.0000874,0.0000865,0.0000281,0.0000218,0.0000509,0.0000403,0.0000247,0.0000228,0.0000054,0.0000094,0.0000211,0.0000086,1e-7,0.0000447,0.0000513,0.0000558,0.0000559,0.0000396,0.0000135,0.0000487,0.0000538,0.0000268,0.0000112,0.0000038,0,0.0000015,0.000008,0,0.0000327,0.0000612,0.0000743,0.0000929,0.0001121,0.000163,0.0002922,0.0005003,0.0006666,0.0008208,0.0009145,0.0009201,0.0009045,0.0008458,0.000739,0.0005447,0.0003912,0.0002496,0.0001192,0.0000523,0.0000338,0.0000024,0.0000181,0.0000304,0.0000513,0.0000833,0.0000918,0.0000793,0.0000567,0.0000363,0.0000395,0.0000516,0.0000537,0.000029,0.0000052,0.0000206,0.0000169,0.0000153,0.0000352,0.000037,0.0000388,0.0000419,0.0000359,0.0000525,0.0000853,0.0000838,0.0000695,0.0000494,0.0000269,0.0000149,0.000031,0.0000341,0.0000151,0.0000117,0.0000409,0.0000629,0.0000834,0.0000904,0.0000819,0.0000812,0.0000851,0.0000714,0.0000543,0.0000459,0.0000311,0.0000177,0.0000536,0.000068,0.0000762,0.0000768,0.0000641,0.0000324,0.0000227,0.0000216,0.0000223,0.0000482,0.0000506,0.0000495,0.0000449,0.0000383,0.0000111,0.0000169,0.000025,0.0000346,0.0000531,0.0000631,0.0000643,0.0000726,0.0000773,0.0000762,0.0001728,0.0003356,0.0005298,0.000752,0.0009733,0.0011795,0.0012975,0.0013377,0.0013278,0.0012339,0.0010635,0.0008454,0.0006047,0.0004028,0.0002297,0.0001161,0.0000404,0.0000204,0.0000231,0.0000194,0.0000252,0.000053,0.0000767,0.000084,0.0000794,0.0000755,0.0000782,0.0000688,0.0000503,0.0000352,0.0000311,0.0000373,0.0000406,0.0000339,0.0000135,0.0000151,0.000022,0.000025,0.0000251,0.0000192,0.0000045,0.0000291,0.0000371,0.000037,0.0000365,0.0000363,0.0000174,0.0000101,0.0000278,0.0000353,0.0000413,0.000043,0.000033,0.000025,0.0000245,0.0000167,0.0000114,0.0000176,0.0000119,0.0000059,0.0000219,0.0000217,0.0000161,0.0000251,0.0000312,0.0000314,0.0000242,0.0000173,0.0000276,0.0000302,0.0000291,0.0000077,0.0000089,0.0000114,0.000023,0.0000509,0.0000745,0.0000861,0.0000895,0.0000888,0.0000676,0.000054,0.000064,0.0000648,0.0000647,0.0000639,0.0000569,0.0000512,0.0000669,0.0000707,0.0000716,0.0000709,0.000063,0.0000388,0.0000241,0.0000322,0.0000459,0.0000649,0.0000747,0.0000797,0.0000806,0.0000791,0.0000599,0.0000361,0.000027,0.0000122],"detections":[{"range_m":1.609424,"snr_db":17.6228,"width_m":0.171607},{"range_m":3.196794,"snr_db":19.0956,"width_m":0.171607}],"noise_floor":0.000036313,"blast_amplitude":0.2699793,"saturated":false}
{"timestamp":1756162802.4666643,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.5,0.8660254,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000044,0.0000375,0.0000229,0.0000042,0.0000483,0.0000644,0.0000718,0.0000713,0.0000608,0,0.0000347,0.0000452,0.0000166,0.0000607,0.0000884,0.0000763,0.0000607,0.0000441,0,0.0000102,0.0000349,0.0000255,0.0000327,0.0000494,0.0000325,0.0000329,0.0000661,0.0000621,0.0000571,0.0000494,0.0000225,0.0000278,0.0000438,0.0000349,0.0000102,0.000053,0.0000612,0.0000484,0.0000272,0.0000825,0.0001961,0.0003637,0.0005474,0.0008145,0.0010672,0.0012471,0.0013251,0.0013288,0.0012856,0.0011168,0.0008888,0.0006749,0.0004371,0.0002737,0.0001652,0.0000788,0.0000173,0.000029,0.0000253,0.0000227,0.0000499,0.0000479,0.000035,0.0000199,0.0000071,0.0000054,0.0000093,0.0000105,0.0000146,0.0000155,0.0000145,0.0000015,0.0000139,0.0000186,0,0.0000206,0.0000382,0.0000392,0.0000443,0.0000495,0.000039,0.0000515,0.0000747,0.0000736,0.0000657,0.0000514,0.0000238,0.000018,0.0000407,0.0000379,0.0000246,0.0000271,0.0000259,0.0000085,0.0000091,0.0000225,0.0000247,0.0000262,0.0000266,0.0000058,0.0000131,0.0000269,0.0000295,0.0000352,0.0000398,0.0000377,0.0000498,0.0000583,0.000052,0.000051,0.0000609,0.0000515,0.0000291,0.0000425,0.0000482,0.0000495,0.0000551,0.0000542,0.0000458,0.0000419,0.0000319,0.0000058,0.0000124,0.0000158,0.0000152,0.0000245,0.0000265,0.0000229,0.0000497,0.0000737,0.0000847,0.0000916,0.0000932,0.0000763,0.0000634,0.0000699,0.0000656,0.0000717,0.0001141,0.0002093,0.0003579,0.0005584,0.0007687,0.0009797,0.0011544,0.0012367,0.0012455,0.0012217,0.0010832,0.0008764,0.0006454,0.0004299,0.0002392,0.0001164,0.0000667,0.0000473,0.0000415,0.0000421,0.000036,0.0000531,0.0000733,0.000082,0.0000892,0.0000894,0.0000721,0.0000388,0.0000408,0.0000643,0.0000821,0.00009,0.0000834,0.000063,0.0000499,0.0000425,0.0000234,0.0000254,0.0000361,0.0000432,0.0000516,0.0000535,0.0000537,0.000073,0.000084,0.0000834,0.0000749,0.0000532,0.0000215,0.0000136,0.0000249,0.0000423,0.0000683,0.0000884,0.0000881,0.0000848,0.0000826,0.0000725,0.0000462,0.0000207,0.0000129,0.0000206,0.0000256,0.0000244,0.0000186,0.0000184,0.0000194,0.0000185,0.0000254,0.0000267,0.0000215,0.000033,0.0000426,0.0000506,0.0000635,0.0000726,0.0000747,0.0000835,0.00009,0.0000872,0.0000823,0.0000836,0.0000798,0.0000721,0.0000696,0.0000623,0.0000461,0.0000445,0.000044,0.0000412,0.0000424,0.0000402,0.0000284,0.0000375,0.0000515,0.0000712,0.0000926,0.0000993,0.0000929,0.0000789,0.0000637,0.0000384],"detections":[{"range_m":1.460104,"snr_db":22.5978,"width_m":0.171607},{"range_m":3.279398,"snr_db":16.6055,"width_m":0.171607}],"noise_floor":0.000042944,"blast_amplitude":0.270032,"saturated":false}
{"timestamp":1756162802.533331,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7071068,0.7071068,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000313,0.0000315,0.0000294,0.0000261,0.0000226,9e-7,0,0,0.0000275,0.0000221,0.0000153,0.000012,0.000018,0.0000337,0.0000466,0.0000325,0.0000501,0.0000613,0.0000356,0.0000647,0.0000958,0.0000853,0.0000676,0.000058,0.0000189,0.0000099,0.0000214,0.000002,0,0.000048,0.0000476,0.0000424,0.0000339,0.0000217,0.0000208,0.00003,0.0000297,0,0.000024,0.0000601,0.0001198,0.0002267,0.0003594,0.0006087,0.0009033,0.0011824,0.0014051,0.0015468,0.0015759,0.0015369,0.0014007,0.0012082,0.0009033,0.000631,0.0004019,0.0002129,0.000078,0.0000293,0.0000257,0.0000194,0.0000594,0.0000816,0.0001059,0.0001231,0.0001217,0.00009,0.0000871,0.0000874,0.0000688,0.000055,0.0000487,0.000021,0.0000082,0.0000144,0.0000322,0.000058,0.0000712,0.0000699,0.000091,0.0001107,0.0001067,0.0000905,0.0000823,0.0000704,0.0000612,0.0000649,0.0000559,0.0000267,0.000018,0.0000289,0.0000411,0.0000561,0.0000556,0.0000384,0.0000278,0.0000355,0.0000444,0.0000523,0.0000535,0.0000329,0.0000342,0.0000418,0.000035,0.00003,0.0000408,0.0000407,0.0000382,0.0000297,0.0000052,0.0000096,0.0000315,0.0000374,0.000044,0.0000476,0.0000403,0.0000262,0.0000401,0.0000403,0.0000432,0.0000705,0.0000817,0.0000912,0.0000959,0.0000959,0.000069,0.0000453,0.000032,0.000009,0.0000283,0.0000444,0.0000446,0.0000404,0.0000294,0.0000327,0.0000709,0.0001266,0.0002096,0.0003522,0.0005446,0.0007824,0.0009686,0.0011013,0.001138,0.0011359,0.0010807,0.0009559,0.0007644,0.0005603,0.0003393,0.0001842,0.0000923,0.0000585,0.000035,0.0000511,0.0000725,0.0000785,0.0000804,0.0000805,0.0000658,0.0000543,0.0000535,0.000045,0.0000388,0.0000407,0.00003,0.0000119,0.0000121,0.0000098,6e-7,0.0000203,0.0000226,0.0000244,0.0000291,0.0000275,0.0000194,0.0000394,0.0000572,0.000066,0.0000688,0.0000681,0.0000454,0.0000411,0.000058,0.0000698,0.0000839,0.0000878,0.0000808,0.0000725,0.0000675,0.0000504,0.0000217,0.0000373,0.0000647,0.0000878,0.0000998,0.0000967,0.0000816,0.0000678,0.0000599,0.0000533,0.000064,0.0000638,0.0000602,0.0000632,0.0000635,0.0000448,0.000022,0.0000201,0.0000348,0.0000496,0.0000569,0.000063,0.0000776,0.0000869,0.0000823,0.0000665,0.000043,0.0000099,0.0000346,0.0000532,0.0000572,0.0000712,0.0000822,0.0000799,0.0000626,0.0000343,0.00002,0.0000367,0.0000404,0.000037,0.0000344,0.0000542,0.0000604,0.0000604,0.0000593,0.000058,0.0000474,0.0000507,0.0000556,0.0000532],"detections":[{"range_m":1.482792,"snr_db":20.0078,"width_m":0.171607},{"range_m":3.216961,"snr_db":16.8942,"width_m":0.171607}],"noise_floor":0.000047459,"blast_amplitude":0.2699607,"saturated":false}
{"timestamp":1756162802.5999975,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8660254,0.5,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000193,0.0000159,0,0,0.0000648,0.0000622,0.0000294,0,0.0000524,0.0000647,0.0000669,0.0000657,0,0.0000041,0.0000329,0.0000287,0.0000277,0.0000322,0.0000129,0.0000344,0.0000577,0.0000455,0.0000624,0.0000809,0.00006,0.0000431,0.0000707,0.0000645,0.0000576,0.0000551,0.0000285,0,0.0000398,0.0000377,0.0000249,0.000028,0.0000498,0.0000646,0.000073,0.0000708,0.0000151,0.0001279,0.0002777,0.000523,0.0007938,0.0010549,0.001291,0.0014844,0.0015623,0.0015584,0.0014718,0.0012896,0.0009588,0.0006618,0.0004206,0.0002291,0.0000928,0.0000603,0.0000582,0.0000552,0.000064,0.0000576,0.000036,0.0000459,0.0000477,0.0000387,0.0000332,0.00003,0.0000216,0.0000391,0.0000439,0.0000319,0.0000258,0.0000283,0.0000144,0.0000313,0.0000423,0.0000361,0.0000335,0.000038,0.0000253,0.0000058,0.0000426,0.0000595,0.0000795,0.0001001,0.0000985,0.0000993,0.0001113,0.0001058,0.0000845,0.0000677,0.0000544,0.0000265,0.0000283,0.0000312,0.0000327,0.0000598,0.0000691,0.000068,0.0000622,0.0000536,0.0000264,0.0000053,0.0000038,0,0.0000138,0.0000378,0.000044,0.0000449,0.0000424,0.0000381,0.0001105,0.0002237,0.0003659,0.0005728,0.0008284,0.0011058,0.0012841,0.0013755,0.0013778,0.0013191,0.0011794,0.000988,0.0007487,0.0005181,0.0002912,0.0001344,0.0000419,0.0000479,0.0000549,0.0000661,0.0000731,0.0000613,0.000042,0.0000265,0.0000087,0.0000135,0.0000273,0.0000333,0.0000552,0.000081,0.0000818,0.0000794,0.0000708,0.0000559,0.0000262,0.0000404,0.0000448,0.0000469,0.0000519,0.0000536,0.0000523,0.0000673,0.0000745,0.0000687,0.0000583,0.0000465,0.0000255,0.0000377,0.0000459,0.0000389,0.0000335,0.0000648,0.0000758,0.0000761,0.0000679,0.0000396,0.0000245,0.0000544,0.000055,0.000054,0.0000541,0.0000519,0.0000433,0.0000563,0.0000592,0.0000505,0.0000482,0.0000538,0.000058,0.0000598,0.0000599,0.0000456,0.0000286,0.0000208,0.0000355,0.0000472,0.0000516,0.000046,0.0000558,0.0000737,0.0000781,0.0000867,0.0000942,0.0000908,0.0000785,0.0000738,0.0000729,0.0000736,0.0000784,0.0000766,0.0000653,0.0000631,0.0000638,0.0000503,0.0000326,0.0000151,0.0000377,0.0000529,0.000056,0.0000456,0.0000323,0.0000293,0.0000225,0.0000271,0.0000331,0.00003,0.0000241,0.0000229,0.0000188,0.0000104,0.0000102,0.0000071,0.000001,0.0000147,0.0000194,0.0000227,0.0000239,0.0000215,0.0000145,0.0000303,0.0000368,0.0000428,0.0000583,0.0000754,0.0000871,0.0000985,0.0001024,0.0000979],"detections":[{"range_m":1.489718,"snr_db":21.5458,"width_m":0.171607},{"range_m":2.798894,"snr_db":19.9053,"width_m":0.171607}],"noise_floor":0.000042585,"blast_amplitude":0.2699904,"saturated":false}
{"timestamp":1756162802.6666641,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.9659258,0.258819,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000442,0.0000476,0.0000506,0.0000507,0.0000469,0.0000152,0,0.0000046,0.0000102,0.0000034,0.0000133,0.0000201,0.0000161,0.0000542,0.0000792,0.0000718,0.0000748,0.0000758,0.0000213,0.0000192,0.0000541,0.0000465,0.0000284,0.0000244,0.0000203,0.0000275,0.0000315,0.0000085,0,0.0000123,0.0000086,0.000004,0.0000299,0.0000274,0.0000303,0.0000674,0.0001286,0.0002635,0.0004806,0.0006923,0.0009043,0.0010915,0.0011806,0.0011884,0.0011628,0.0010759,0.0008878,0.0006699,0.0004676,0.0002719,0.000128,0.0000673,0.0000497,0.0000396,0.000031,0.0000058,0.0000132,0.0000443,0.0000586,0.00008,0.0000976,0.0000929,0.0000762,0.0000938,0.0000945,0.0000756,0.0000692,0.0000687,0.0000656,0.0000894,0.0000965,0.0000856,0.0000807,0.0000887,0.000081,0.000076,0.0000726,0.0000548,0.0000675,0.0000784,0.0000709,0.0000678,0.000078,0.0000701,0.0000503,0.0000437,0.0000416,0.0000434,0.0000569,0.000055,0.0000542,0.0000569,0.0000538,0.00003,0.0000272,0.0000288,0.0000169,0.0000454,0.0000605,0.0000642,0.0000644,0.0000623,0.0000352,0.0000079,0.0000141,0.0000444,0.0001221,0.0002598,0.0004659,0.000766,0.0011942,0.0015249,0.0017874,0.0019265,0.0019322,0.0018751,0.0016961,0.0014258,0.0010178,0.0006926,0.0004183,0.0001994,0.0000794,0.0000598,0.0000542,0.0000552,0.0000561,0.0000359,0.0000162,0.0000047,0,0.0000116,0.0000383,0.0000467,0.0000517,0.0000539,0.0000443,0.0000372,0.0000426,0.0000373,0.0000228,0.0000382,0.0000378,0.0000323,0.0000203,0.0000078,0.0000166,0.0000176,0.0000128,0.0000197,0.0000325,0.0000344,0.0000212,0.0000174,0.0000212,0.0000148,0.0000305,0.0000441,0.0000497,0.0000564,0.0000607,0.0000541,0.0000535,0.0000621,0.0000608,0.0000646,0.0000714,0.0000686,0.0000734,0.0000943,0.0000944,0.0000925,0.0000861,0.0000723,0.0000427,0.0000272,0.0000287,0.0000361,0.0000558,0.0000609,0.000059,0.0000541,0.0000503,0.0000353,0.0000217,0.0000121,0.0000044,0.000022,0.000035,0.0000345,0.0000293,0.0000215,0.0000096,0.0000197,0.000044,0.0000549,0.0000592,0.0000589,0.0000503,0.0000295,0.0000281,0.0000256,0.0000078,0.0000035,0.0000078,0.0000117,0.0000243,0.0000268,0.0000232,0.0000266,0.0000318,0.0000332,0.000035,0.0000353,0.0000241,0.0000279,0.0000408,0.0000465,0.0000539,0.0000583,0.0000537,0.0000425,0.0000608,0.0000755,0.0000928,0.0001075,0.0001072,0.0000992,0.0000913,0.0000832,0.0000662,0.0000613,0.0000634,0.0000657,0.0000676,0.0000676,0.0000535,0.0000341,0.0000378,0.0000483],"detections":[{"range_m":1.38882,"snr_db":18.2941,"width_m":0.171607},{"range_m":2.690172,"snr_db":23.7513,"width_m":0.171607}],"noise_floor":0.000043777,"blast_amplitude":0.270011,"saturated":false}
{"timestamp":1756162802.7333307,"source":"simulated","device_id":"batvu-reference-01","beam":[-1,0,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000137,0,0,0.0000026,0.000049,0.0000398,0,0,0.0000286,0.0000201,0.0000125,0.0000371,0.0000431,0.0000466,0.0000478,0,0,0.000019,0.0000139,0.0000221,0.0000375,0.0000154,0,0.0000371,0.0000375,0.0000344,0.000026,0,0,0.0000196,0.0000129,0.0000011,0.000029,0.0000411,0.0000508,0.0000586,0.0000584,0.0000265,0.0000468,0.0000492,0.000022,0.0000222,0.0000319,0.0000197,0.0000391,0.0000545,0.0000509,0.0000398,0.0000239,0.0000198,0.0000267,0.0000272,0,0,0.0000225,0.0000218,0.0000251,0.000028,0.0000176,0.0000403,0.0001052,0.0001351,0.0001588,0.0001711,0.0001685,0.0001325,0.0001324,0.0001327,0.0001116,0.0000894,0.0000673,0.0000185,0.0000159,0.0000286,0.0000246,0.0000336,0.0000404,0.0000328,0.0000312,0.0000338,0.0000193,0.0000123,0.0000367,0.0000427,0.0000495,0.0000528,0.000043,0.000017,0.0000371,0.0000389,0.0000571,0.0000853,0.0000868,0.000073,0.0000525,0.0000347,0.0000147,0.0000235,0.0000255,0.0000164,0.0000455,0.0000698,0.0000731,0.0000702,0.000063,0.000182,0.0004017,0.0007093,0.0010877,0.0015303,0.0020434,0.0023468,0.0024921,0.002499,0.0024107,0.0021386,0.0017626,0.0013422,0.0008333,0.0004859,0.0002299,0.0000497,0.0000544,0.0000603,0.0000503,0.0000406,0.0000422,0.0000302,0.0000207,0.0000132,2e-7,0.0000066,0.0000139,0.0000161,0.0000259,0.0000334,0.0000286,0.0000265,0.0000389,0.000038,0.0000339,0.0000317,0.0000247,0.0000118,0.0000207,0.0000239,0.0000373,0.0000654,0.0000693,0.0000696,0.0000684,0.0000612,0.000028,0.0000272,0.0000549,0.0000727,0.0000937,0.0001022,0.0000989,0.0000914,0.0000855,0.0000711,0.0000625,0.0000731,0.0000723,0.0000704,0.0000729,0.0000679,0.0000621,0.0000884,0.0000988,0.0001026,0.0001021,0.0000909,0.0000601,0.000041,0.0000368,0.0000228,0.000026,0.0000279,0.0000223,0.00002,0.0000177,0.0000101,0.0000357,0.0000448,0.0000428,0.0000358,0.0000305,0.0000222,0.0000135,0.0000083,0.0000105,0.0000279,0.0000493,0.0000551,0.0000579,0.000058,0.0000532,0.0000329,0.0000191,0.0000137,0.0000087,0.0000241,0.0000292,0.0000337,0.0000489,0.0000527,0.0000517,0.0000503,0.0000487,0.0000341,0.0000312,0.0000409,0.0000385,0.0000285,0.0000141,0.000011,0.0000189,0.0000263,0.0000263,0.0000352,0.0000428,0.0000399,0.0000262,0.0000173,0.0000368,0.0000508,0.0000598,0.000059,0.0000738,0.0000947,0.0000988,0.0000943,0.000081,0.0000628,0.0000307,0.0000321,0.0000547,0.0000625],"detections":[{"range_m":2.672074,"snr_db":25.7906,"width_m":0.171607}],"noise_floor":0.000034871,"blast_amplitude":0.2699593,"saturated":false}
{"timestamp":1756162802.7999973,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.9659258,-0.258819,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000521,0.0000506,0.0000406,0.0000258,0.0000351,0.0000299,0.0000171,0.0000112,0.0000171,0.0000076,0.000007,0.0000067,0,0,0.000025,0.0000277,0.0000276,0.0000236,0,0.0000105,0.0000206,0.0000059,0.0000283,0.0000497,0.0000325,0.0000204,0.0000546,0.0000519,0.0000498,0.0000652,0.0000631,0.0000836,0.0001015,0.0000922,0.0000498,0.0000645,0.0000722,0.0000678,0.000067,0.0000651,0.0000254,0.000046,0.0000622,0.000065,0.0000659,0.0000649,0.000019,0,0.0000072,0,0.0000023,0.0000187,0.0000092,0,0.0000225,0.000023,0.0000224,0.0000182,0.0000053,0.0000236,0.0000394,0.0000345,0.0000258,0.0000582,0.0000618,0.0000521,0.0000335,0.0000126,0.0000179,0.0000414,0.0000474,0.0000354,0.0000287,0.0000334,0.0000155,0.0000106,0.0000492,0.0000657,0.0000735,0.0000741,0.000055,0.0000322,0.0000453,0.0000407,0.0000281,0.0000397,0.000063,0.0000898,0.0001094,0.0001043,0.000086,0.0000959,0.0000957,0.0000826,0.0000764,0.0000756,0.0000429,0.0000281,0.00003,0.0000168,0.0000165,0.0000356,0.0000463,0.0000518,0.0000525,0.0000312,0.0000152,0.0000289,0.0000298,0.0000464,0.0000936,0.000171,0.0003425,0.000619,0.0009665,0.0013803,0.0018058,0.0022034,0.0023967,0.0024329,0.0023985,0.002178,0.0018246,0.001411,0.0009878,0.0006421,0.0003656,0.0002099,0.0001224,0.0000899,0.0000743,0.000067,0.000066,0.0000506,0.0000351,0.0000271,0.0000173,0.0000212,0.000036,0.000036,0.0000402,0.0000461,0.0000416,0.0000279,0.0000223,0.0000257,0.0000367,0.0000538,0.0000538,0.0000547,0.0000779,0.0000952,0.0001053,0.0001076,0.0001058,0.0000715,0.0000424,0.0000255,0.0000014,0.0000138,0.0000261,0.0000243,0.0000222,0.0000328,0.0000337,0.0000336,0.0000325,0.0000261,0.0000174,0.0000223,0.0000237,0.000038,0.000054,0.0000538,0.0000468,0.0000442,0.0000442,0.0000194,0.0000291,0.0000464,0.0000542,0.0000567,0.0000565,0.0000391,0.0000199,0.0000226,0.0000296,0.0000368,0.0000394,0.0000298,0.0000164,0.000041,0.0000478,0.0000492,0.0000488,0.0000404,0.0000265,0.0000322,0.0000316,0.0000287,0.0000331,0.0000314,0.0000212,0.0000294,0.0000322,0.0000298,0.0000281,0.000028,0.0000133,0.0000042,0.0000052,0.0000185,0.0000431,0.000061,0.0000606,0.000052,0.0000378,0.0000376,0.0000546,0.0000656,0.0000639,0.0000559,0.0000497,0.0000405,0.000021,0.0000061,0.0000014,0.0000014,0.0000374,0.0000605,0.000081,0.0000953,0.000097,0.000087,0.0000759,0.0000682,0.0000471,0.0000339,0.000035,0.0000294],"detections":[{"range_m":2.789088,"snr_db":24.1004,"width_m":0.171607}],"noise_floor":0.000036772,"blast_amplitude":0.2699547,"saturated":false}
{"timestamp":1756162802.866664,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8660254,-0.5,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000269,0.0000276,0.0000106,0.0000101,0.0000381,0.0000332,0.0000387,0.0000411,5e-7,0.0000205,0.0000491,0.00005,0.000052,0.0000533,0.0000035,0.0000151,0.0000511,0.0000456,0.0000325,0.0000319,0.0000203,0.0000305,0.0000423,0.0000251,0.0000065,0.0000345,0.0000277,0.0000172,0.0000106,0,0.0000041,0.0000226,0.0000266,0.0000059,0.0000113,0.0000241,0.0000279,0.00003,0.0000308,0.0000078,0.000028,0.0000364,0.0000217,0.0000106,0.0000196,0.000014,0.0000173,0.000044,0.0000556,0.0000676,0.0000726,0.0000551,0.0000304,0.0000465,0.0000424,0.0000221,0.0000345,0.0000324,0.0000264,0.0000219,0.0000129,0.0000207,0.0000522,0.0000551,0.0000446,0.0000342,0.0000294,0.0000083,0.0000236,0.0000392,0.0000376,0.0000347,0.0000292,0.0000071,0.0000157,0.0000203,0.0000062,0,0.0000064,0.0000026,0.0000028,0.0000212,0.0000194,0.0000097,0.0000326,0.0000407,0.0000455,0.0000461,0.0000415,0.0000126,0.0000365,0.00005,0.0000513,0.0000512,0.000049,0.0000212,0.0000383,0.0000661,0.0000859,0.0000986,0.0001013,0.0000824,0.0000625,0.0000607,0.000048,0.0000232,0.0000191,0.000024,0.0000265,0.0000317,0.0000285,0.0000278,0.0000314,0.0000286,0.0000173,0.0000386,0.0000396,0.000032,0.0000217,0.0000157,0.0000257,0.0000529,0.0000824,0.0001751,0.0003669,0.0006408,0.000978,0.0013535,0.0017582,0.0019858,0.0020814,0.002082,0.0019768,0.0017232,0.0013875,0.0010258,0.000634,0.0004049,0.0002567,0.0001615,0.0001141,0.0000889,0.0000571,0.0000415,0.0000347,0.0000102,0.0000241,0.0000415,0.0000467,0.000047,0.0000452,0.0000231,0.0000348,0.0000474,0.0000481,0.0000472,0.0000411,0.0000194,0.0000171,0.0000249,0.0000198,0.0000133,0.0000211,0.0000188,0.0000168,0.0000319,0.0000314,0.0000325,0.000044,0.0000443,0.0000471,0.0000558,0.0000579,0.0000581,0.0000758,0.000086,0.0000952,0.0001074,0.0001121,0.000106,0.0000979,0.0000952,0.0000858,0.0000877,0.0000919,0.0000847,0.0000697,0.0000584,0.0000411,0.0000224,0.0000248,0.0000255,0.0000255,0.0000237,0.0000189,0.0000061,0.0000204,0.0000223,0.0000231,0.0000233,0.0000234,0.0000095,0.0000091,0.000011,0.0000078,0.0000141,0.000019,0.0000285,0.0000514,0.0000738,0.0000773,0.0000773,0.0000749,0.000062,0.0000494,0.0000548,0.0000527,0.0000475,0.0000574,0.0000616,0.0000684,0.0000736,0.0000715,0.000055,0.0000372,0.0000216,0.0000264,0.0000439,0.0000551,0.0000624,0.0000644,0.0000634,0.0000452,0.0000246,0.0000215,0.0000137],"detections":[{"range_m":3.073217,"snr_db":23.6053,"width_m":0.171607}],"noise_floor":0.000032506,"blast_amplitude":0.2699894,"saturated":false}
{"timestamp":1756162802.9333305,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7071068,-0.7071068,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000567,0.0000616,0.000057,0.0000494,0.0000557,0.0000219,0.0000145,0.0000151,0,0.0000108,0.0000275,0.0000077,0,0.0000185,0.0000193,0.0000244,0.0000383,0.0000292,0.0000551,0.00008,0.0000657,0.0000531,0.0000759,0.000068,0.0000597,0.0000563,0.0000259,0,0.0000123,0.0000108,0.0000034,0.0000178,0.0000246,0.0000188,0.000014,0.0000077,0.0000104,0.0000217,0.0000272,0.0000189,0.0000333,0.0000373,0.0000137,0.0000188,0.0000359,0.0000259,0.0000055,0.0000477,0.0000609,0.0000654,0.0000653,0.0000396,0.0000034,0.0000135,0.0000089,0.0000068,0.000062,0.0000757,0.0000806,0.0000806,0.0000738,0.0000356,0.0000637,0.0000718,0.0000757,0.0000771,0.0000767,0.0000404,0.0000151,0.0000187,0.0000049,0.0000178,0.0000481,0.0000531,0.0000528,0.0000452,0.0000134,0,0.0000042,0,0.0000087,0.0000313,0.0000333,0.0000413,0.000052,0.0000459,0.0000278,0.0000308,0.0000303,0.0000189,0.0000191,0.0000208,0.0000217,0.0000509,0.0000599,0.0000567,0.0000461,0.000033,0.0000059,0.000001,0.0000128,0.0000135,0.0000152,0.0000211,0.0000196,0.0000323,0.0000619,0.0000732,0.0000803,0.0000807,0.0000676,0.0000381,0.0000595,0.000067,0.0000696,0.0000737,0.0000717,0.0000596,0.000064,0.0000651,0.0000483,0.0000532,0.0000569,0.0000517,0.0000453,0.0000369,0.0000112,0.0000152,0.0000235,0.0000225,0.0000434,0.0000564,0.0000506,0.0000421,0.0001785,0.0004188,0.0007006,0.0010328,0.0013598,0.0016563,0.0018673,0.0019242,0.0019163,0.0017967,0.0014947,0.0011528,0.0008165,0.0005336,0.0003035,0.0001506,0.0000631,0.0000099,0.0000253,0.0000294,0.0000199,0.0000203,0.0000292,0.0000261,0.0000147,0.0000258,0.0000418,0.0000557,0.0000648,0.000062,0.0000562,0.0000613,0.0000569,0.0000474,0.0000569,0.0000564,0.0000499,0.0000515,0.0000525,0.0000369,0.000035,0.000042,0.0000497,0.0000593,0.0000631,0.0000554,0.0000439,0.0000305,0.000011,0.0000274,0.0000429,0.000044,0.0000436,0.0000398,0.0000237,0.0000273,0.0000432,0.0000432,0.0000461,0.0000578,0.0000583,0.0000577,0.0000541,0.0000434,0.00002,0.0000217,0.000032,0.0000445,0.0000602,0.0000623,0.0000545,0.0000511,0.0000534,0.0000472,0.0000411,0.0000377,0.0000242,0.0000253,0.0000339,0.0000328,0.0000278,0.0000199,0.000004,0.0000167,0.0000262,0.0000245,0.0000181,0.0000197,0.0000194,0.000021,0.0000224,0.0000194,0.0000022,0.0000187,0.0000299,0.000036,0.0000392,0.0000391,0.0000231,0.0000118,0.0000278,0.0000309],"detections":[{"range_m":3.268919,"snr_db":23.9412,"width_m":0.171607}],"noise_floor":0.000030864,"blast_amplitude":0.2699768,"saturated":false}
{"timestamp":1756162802.9999971,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.5,-0.8660254,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000718,0.0000751,0.0000613,0.00004,0.0000203,0.0000108,0.0000191,0.0000198,0,0.0000085,0.000025,0.0000094,0.0000155,0.0000259,0.0000083,0.0000046,0.0000098,0.000001,0.0000185,0.0000425,0.0000323,0.0000278,0.0000365,0.0000176,0,0.0000622,0.0000792,0.0000878,0.0000884,0.0000708,0.0000161,0.0000282,0.000033,0.0000137,0.0000277,0.0000319,0.0000213,0.000024,0.0000249,0,0.0000032,0.0000111,0,0.0000232,0.0000451,0.0000393,0.0000267,0.000026,0.0000178,0.000011,0.0000328,0.0000397,0.000043,0.0000427,0.0000251,0.0000109,0.0000424,0.0000407,0.0000303,0.0000323,0.0000366,0.0000456,0.0000505,0.000048,0.0000306,0.0000527,0.0000587,0.0000459,0.0000337,0.0000292,0.0000011,0.0000099,0.0000285,0.0000283,0.0000265,0.0000275,0.0000157,0.0000084,0.0000256,0.0000276,0.000029,0.0000291,0.0000197,0.0000096,0.000026,0.0000237,0.0000167,0.00003,0.0000328,0.0000455,0.0000612,0.0000636,0.0000338,0.0000105,0.0000383,0.0000501,0.0000572,0.00006,0.0000468,0.0000394,0.0000409,0.0000249,0.0000178,0.0000253,0.0000183,0.0000012,0.0000418,0.0000619,0.000078,0.0000863,0.0000801,0.0000623,0.0000645,0.0000629,0.0000417,0.000026,0.00001,0.0000071,0.0000224,0.0000268,0.0000239,0.000024,0.0000237,0,0.0000285,0.0000499,0.0000554,0.0000567,0.0000564,0.0000371,0.0000307,0.0000427,0.0000419,0.0000445,0.0000532,0.0000645,0.0001044,0.0001783,0.000289,0.0004815,0.0007574,0.0010664,0.0013849,0.0017021,0.0018287,0.0018421,0.0018043,0.0016414,0.0013547,0.0010162,0.0006855,0.0003444,0.0001603,0.0000833,0.0000612,0.0000512,0.0000541,0.0000505,0.0000643,0.000074,0.0000716,0.0000649,0.0000602,0.000051,0.0000345,0.0000382,0.0000363,0.0000399,0.000059,0.0000626,0.000064,0.0000646,0.0000645,0.0000439,0.0000471,0.0000526,0.0000536,0.0000562,0.0000589,0.0000542,0.0000533,0.0000519,0.000033,0.0000244,0.0000431,0.0000497,0.0000506,0.0000482,0.0000241,0.0000127,0.0000301,0.0000301,0.000033,0.000043,0.0000428,0.0000435,0.0000506,0.0000491,0.0000359,0.0000246,0.000023,0.0000159,0.0000118,0.0000102,0.000015,0.0000361,0.0000527,0.0000595,0.0000633,0.0000647,0.0000554,0.0000609,0.0000693,0.0000674,0.0000576,0.0000408,0.0000164,0.0000301,0.0000405,0.0000392,0.0000404,0.0000461,0.000044,0.0000249,0.0000297,0.0000625,0.0000951,0.0001236,0.0001313,0.0001312,0.0001273,0.0001201,0.0000982,0.0000715,0.0000561,0.000033],"detections":[{"range_m":3.336489,"snr_db":21.5684,"width_m":0.171607}],"noise_floor":0.000037665,"blast_amplitude":0.2699642,"saturated":false}
{"timestamp":1756162803.0666637,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.258819,-0.9659258,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000311,0.0000106,0,0,0.0000399,0.0000367,0.0000152,0.0000278,0.0000582,0.0000519,0.0000496,0.00005,0.0000047,0.0000368,0.000055,0.000022,0.0000124,0.00005,0.0000561,0.0000577,0.0000576,0.0000129,0.0000191,0.0000633,0.0000627,0.000055,0.0000425,0.0000177,0.0000185,0.0000266,0.0000177,0.0000406,0.0000713,0.0000657,0.0000416,0.0000458,0.0000495,0.0000292,0.0000222,0.0000194,0,0.0000397,0.0000731,0.0000827,0.0000827,0.0000753,0.0000176,6e-7,0.000017,0.0000063,0,0.0000108,0.0000069,3e-7,0.000006,0.0000038,0.000008,0.0000484,0.0000609,0.0000681,0.0000704,0.0000587,0.0000262,0.0000426,0.0000449,0.000034,0.0000255,0.0000213,5e-7,0.0000358,0.0000542,0.0000557,0.0000551,0.0000502,0.0000139,0.0000065,0.0000196,0.0000204,0.0000228,0.0000246,0.0000118,0.0000165,0.00003,0.0000258,0.0000188,0.0000256,0.0000241,0.0000332,0.0000469,0.0000428,0.0000306,0.0000403,0.0000393,0.0000208,0.000007,0.0000074,0.0000043,0.0000287,0.0000452,0.0000481,0.0000475,0.0000401,0.0000083,0.0000045,0.00001,0.0000089,0.0000177,0.000026,0.0000227,0.0000281,0.0000347,0.0000245,0.000013,0.0000242,0.0000211,0.0000055,0.0000282,0.0000441,0.0000482,0.0000482,0.0000427,0.0000283,0.0000433,0.0000465,0.0000399,0.0000518,0.0000557,0.0000646,0.0000868,0.0000964,0.0000913,0.0000786,0.000069,0.0000524,0.0000591,0.0000736,0.0000719,0.0000601,0.0001255,0.0003104,0.0005503,0.0008524,0.0011736,0.0014945,0.001754,0.0018676,0.0018718,0.0017998,0.0015337,0.0012066,0.0008771,0.0005946,0.0003574,0.0001899,0.0000875,0.0000205,0.0000117,0.0000189,0.000041,0.000063,0.0000737,0.0000711,0.0000776,0.0000883,0.0000869,0.0000819,0.0000739,0.0000558,0.0000305,0.0000334,0.0000312,0.0000223,0.0000223,0.0000278,0.0000383,0.000049,0.0000508,0.000041,0.0000478,0.0000501,0.0000555,0.0000808,0.0000991,0.0001007,0.0000981,0.0000815,0.0000496,0.0000278,0.0000269,0.0000186,0.0000059,0.0000055,0.0000099,0.0000246,0.000041,0.000041,0.000044,0.0000618,0.0000733,0.0000893,0.0000997,0.0000984,0.0000853,0.0000725,0.0000627,0.0000404,0.0000258,0.000021,0.0000097,0.0000058,0.0000227,0.0000353,0.0000455,0.0000491,0.0000385,0.0000253,0.0000186,0.000017,0.0000318,0.0000487,0.0000504,0.000057,0.0000726,0.0000828,0.0000928,0.0000959,0.0000928,0.000073,0.0000588,0.0000522,0.0000408,0.000036,0.0000354,0.0000216,0.0000216,0.0000267,0.0000243,0.0000228,0.000025,0.0000211],"detections":[{"range_m":3.27542,"snr_db":20.1394,"width_m":0.171607}],"noise_floor":0.000036342,"blast_amplitude":0.2700173,"saturated":false}
{"timestamp":1756162803.1333303,"source":"simulated","device_id":"batvu-reference-01","beam":[0,-1,0],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000059,9e-7,0,0.0000136,0.0000502,0.0000422,0.0000333,0.0000572,0.0000686,0.0000242,0.0000415,0.000068,0.00007,0.0000729,0.0000745,0.0000113,0.0000088,0.0000229,0,0.0000043,0.0000549,0.0000608,0.0000678,0.0000778,0.0000543,0.0000534,0.0000776,0.0000666,0.0000493,0.0000498,0.0000331,0.0000236,0.0000424,0.0000355,0.0000217,0.0000672,0.0000764,0.0000732,0.0000727,0.0000723,0.000042,0.0000553,0.0000645,0.0000503,0.0000381,0.0000336,0,0,0.000028,0.0000298,0.0000346,0.0000433,0.000031,0.0000232,0.0000277,0.0000155,0,0.0000293,0.0000331,0.0000337,0.0000356,0.0000273,0.0000126,0.0000266,0.0000277,0.0000175,0.0000438,0.0000505,0.0000516,0.0000506,0.0000444,0.0000102,0.0000183,0.0000273,0.0000192,0.0000187,0.0000201,0,0.0000076,0.0000413,0.0000519,0.000056,0.0000568,0.0000417,0.0000417,0.0000631,0.0000616,0.0000549,0.0000513,0.0000371,0.0000066,0.0000097,0.00001,0.0000056,0.0000406,0.0000609,0.000063,0.0000624,0.0000581,0.00003,0.0000398,0.0000562,0.0000601,0.0000605,0.0000587,0.0000355,0.0000346,0.0000443,0.0000374,0.0000204,0.0000239,0.0000387,0.0000576,0.0000732,0.0000713,0.0000693,0.0000824,0.0000814,0.0000568,0.0000333,0.0000486,0.0000687,0.0000822,0.0000841,0.0000711,0.0000823,0.0000852,0.0000771,0.0000871,0.0000955,0.0000908,0.0000723,0.0000692,0.0002192,0.0004484,0.0007454,0.0010862,0.0014539,0.0017828,0.0020088,0.0020403,0.0020124,0.0018334,0.0015236,0.0011676,0.0008224,0.0005128,0.000285,0.0001198,0.0000481,0.0000488,0.0000505,0.0000382,0.0000488,0.0000621,0.0000633,0.0000628,0.000058,0.0000336,0.0000127,0.0000108,0.0000042,0,0.0000112,0.0000117,0.0000138,0.000019,0.0000166,0.0000146,0.0000153,0.000009,0.0000209,0.0000455,0.0000479,0.0000467,0.0000395,0.0000278,0.0000167,0.0000316,0.0000344,0.0000298,0.0000287,0.0000305,0.0000241,0.0000314,0.0000349,0.0000296,0.0000383,0.0000502,0.0000549,0.0000618,0.0000651,0.0000552,0.0000372,0.0000269,0.0000255,0.0000427,0.0000659,0.000068,0.0000671,0.0000674,0.0000661,0.0000577,0.0000491,0.0000345,0.000009,0.0000385,0.0000432,0.0000405,0.0000353,0.0000349,0.0000269,0.0000257,0.0000307,0.0000278,0.0000286,0.0000289,0.0000184,0.0000053,0.0000315,0.0000453,0.0000629,0.0000743,0.0000736,0.0000703,0.0000745,0.0000729,0.0000615,0.0000636,0.0000687,0.0000727,0.0000727,0.000068,0.000044,0.0000256,0.0000181,0.0000213,0.0000367,0.0000425,0.0000403],"detections":[{"range_m":3.175081,"snr_db":21.31,"width_m":0.175182}],"noise_floor":0.00003978,"blast_amplitude":0.2699786,"saturated":false}
{"timestamp":1756162803.199997,"source":"simulated","device_id":"batvu-reference-01","beam":[0,-0.9063078,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000729,0.0000701,0.0000532,0.0000334,0.000054,0.0000494,0.000031,0.0000151,0.000051,0.0000761,0.0000974,0.0001005,0.0000468,0.0000663,0.0000916,0.0000744,0.0000597,0.0000547,0.0000124,0.0000406,0.0000815,0.000081,0.0000796,0.0000751,0.0000282,0,0.0000122,0.0000071,0.0000021,0.0000055,0,0,0.0000071,0,0,0.0000079,0.0000162,0.0000095,0.0000428,0.0000507,0.0000522,0.0000569,0.0000588,0.0000323,0.0000308,0.0000378,0.0000278,0.0000405,0.0000502,0.0000356,0.0000182,0.0000081,0.0000013,0.0000136,0.0000328,0.0000281,0.0000172,0.0000055,0.0000139,0.0000162,0.000016,0.000006,0.0000105,0.0000153,0.000012,0.0000099,0.0000449,0.0000508,0.0000554,0.0000607,0.0000613,0.0000298,0.0000079,0.0000143,0.0000045,8e-7,0.0000123,0.0000094,0.0000108,0.0000234,0.0000204,0.000021,0.0000314,0.0000275,0.0000224,0.0000212,0.000014,0.0000066,0.0000124,0.0000049,0,0.0000286,0.0000316,0.0000289,0.0000199,0.0000132,0.0000333,0.0000513,0.0000542,0.000039,0.0000357,0.0000395,0.0000237,0.0000263,0.0000515,0.0000536,0.0000523,0.0000544,0.0000896,0.0001913,0.0004234,0.0007117,0.0011041,0.00156,0.0019938,0.0023589,0.0025824,0.0026108,0.0025335,0.0022765,0.0018869,0.0014166,0.0009683,0.0005962,0.0002977,0.0001022,0.0000431,0.0000476,0.0000445,0.0000318,0.0000079,0.0000217,0.0000338,0.0000344,0.0000418,0.0000479,0.0000416,0.0000307,0.0000255,0.0000252,0.0000442,0.0000642,0.0000637,0.000056,0.0000417,0.000021,0.000017,0.0000394,0.0000396,0.0000333,0.0000328,0.000035,0.0000414,0.0000544,0.0000596,0.0000513,0.0000441,0.0000397,0.0000198,0.0000017,0.0000122,0.0000157,0.0000417,0.0000651,0.0000683,0.0000676,0.0000601,0.00004,0.0000121,0.0000196,0.0000279,0.0000531,0.0000919,0.0001097,0.0001146,0.0001133,0.0000982,0.0000442,0.0000244,0.000042,0.0000558,0.0000736,0.000082,0.0000813,0.0000797,0.0000798,0.0000691,0.0000746,0.0000846,0.0000832,0.0000771,0.0000692,0.0000516,0.0000353,0.0000265,0.0000116,0.0000179,0.0000462,0.0000542,0.0000581,0.0000618,0.0000603,0.0000548,0.0000638,0.0000656,0.0000562,0.0000429,0.0000301,0.0000182,0.0000358,0.0000587,0.0000785,0.0000953,0.000102,0.0000952,0.000088,0.000089,0.0000804,0.0000612,0.0000377,0.0000091,0.0000347,0.0000455,0.0000434,0.0000358,0.0000432,0.0000428,0.0000373,0.0000316,0.0000229,0.0000081,0.0000061,0.0000063,0.0000014,0.0000146,0.0000271,0.0000425,0.0000668,0.0000811,0.000082],"detections":[{"range_m":2.747782,"snr_db":26.9263,"width_m":0.171607}],"noise_floor":0.000035007,"blast_amplitude":0.2700119,"saturated":false}
{"timestamp":1756162803.2666636,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.2345697,-0.8754261,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000636,0.0000623,0.0000491,0.0000614,0.0000684,0.0000168,0.0000251,0.0000502,0.0000446,0.0000354,0.0000271,0.0000015,0.0000256,0.0000426,0.0000229,0.0000022,0.0000354,0.0000527,0.0000671,0.0000811,0.0000615,0.0000537,0.0000556,0.0000292,0,0.0000455,0.0000472,0.0000539,0.0000644,0.0000555,0.0000278,0.0000545,0.0000594,0.0000363,0.0000487,0.0000575,0.0000702,0.0000849,0.0000876,0.0000579,0.0000675,0.0000769,0.0000585,0.0000339,0.0000178,0.0000216,0.0000256,0.0000279,0.0000076,0.0000056,0.0000214,0.0000209,0.0000315,0.0000469,0.0000427,0.0000326,0.0000484,0.0000447,0.0000275,0.0000118,0.0000212,0.0000438,0.0000639,0.0000641,0.0000462,0.0000758,0.000095,0.0001004,0.0001007,0.0000975,0.0000578,0.0000521,0.0000595,0.0000473,0.0000275,0.0000296,0.0000469,0.0000705,0.0000875,0.0000829,0.0000704,0.0000588,0.000037,0,0.0000524,0.0000685,0.0000781,0.0000789,0.0000708,0.000029,0.0000382,0.0000488,0.0000484,0.0000553,0.0000583,0.000058,0.0000705,0.0000764,0.0000683,0.000071,0.0000742,0.0000581,0.0000371,0.0000249,0.0000077,0.0000147,0.0000285,0.0000424,0.0001715,0.0004108,0.000734,0.0011494,0.0016125,0.002105,0.0024068,0.0025434,0.0025433,0.00241,0.0021005,0.0016802,0.0012073,0.0007874,0.0004201,0.0002052,0.0000764,0.0000128,0.0000188,0.0000267,0.0000364,0.0000357,0.000041,0.0000462,0.0000396,0.0000292,0.0000301,0.0000386,0.0000539,0.000065,0.0000618,0.0000527,0.0000633,0.0000629,0.0000552,0.0000602,0.000059,0.0000494,0.0000462,0.0000465,0.0000293,0.0000278,0.0000329,0.0000288,0.0000468,0.000063,0.0000701,0.0000812,0.000092,0.0000914,0.0000914,0.0000899,0.0000741,0.0000549,0.0000572,0.0000557,0.0000609,0.0000684,0.0000623,0.0000393,0.000029,0.0000365,0.0000384,0.0000382,0.0000375,0.0000235,0.0000175,0.0000125,0.0000214,0.0000354,0.0000404,0.0000356,0.0000418,0.0000464,0.0000417,0.0000365,0.0000386,0.0000313,0.0000195,0.0000225,0.0000262,0.0000336,0.0000421,0.0000403,0.000034,0.0000291,0.0000238,0.0000137,0.000027,0.0000274,0.0000264,0.0000358,0.0000421,0.000052,0.000069,0.0000714,0.0000624,0.0000527,0.0000599,0.0000606,0.0000583,0.0000475,0.0000255,0.0000349,0.0000391,0.0000325,0.0000219,0.0000202,0.0000159,0.0000336,0.0000625,0.0000735,0.0000755,0.000074,0.0000632,0.0000398,0.0000282,0.000026,0.0000312,0.0000535,0.0000659,0.0000726,0.00008,0.0000836,0.0000805,0.0000797,0.0000773,0.0000585],"detections":[{"range_m":2.797511,"snr_db":25.2471,"width_m":0.171607}],"noise_floor":0.000042446,"blast_amplitude":0.2700145,"saturated":false}
{"timestamp":1756162803.3333302,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.4531539,-0.7848856,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000076,0.0000011,0,0,0.0000305,0.0000308,0.0000254,0.0000237,0.0000216,0,0.0000127,0.0000293,0.0000269,0.0000351,0.000041,0.0000033,0.0000134,0.0000185,0,0,0.0000167,0.0000086,0,0.0000307,0.0000337,0.0000392,0.0000508,0.0000349,0.0000151,0.0000162,0,0.0000043,0.00006,0.0000606,0.0000592,0.0000532,0.0000423,0.0000031,0.0000272,0.0000304,0.0000216,0.0000642,0.0000822,0.0000767,0.000058,0.000038,0.0000032,0.0000233,0.0000338,0.0000213,0.00004,0.0000683,0.0000624,0.0000483,0.0000338,0.0000122,0.0000128,0.0000257,0.0000218,0.0000066,0.0000096,0.0000183,0.0000275,0.0000378,0.0000364,0.0000139,0.0000658,0.000083,0.0000904,0.0000931,0.0000933,0.0000631,0.0000694,0.0000845,0.0000783,0.0000654,0.0000503,0.0000245,0.0000311,0.0000372,0.0000258,0.0000121,0.0000224,0.0000184,0.0000136,0.0000289,0.0000278,0.0000228,0.0000132,0.0000206,0.0000359,0.0000474,0.000046,0.0000342,0.0000501,0.0000538,0.0000409,0.0000571,0.0000727,0.0000791,0.0000797,0.000077,0.0000519,0.0000558,0.0000623,0.0000521,0.0000381,0.0000394,0.0000325,0.0000221,0.0000394,0.0000517,0.0000665,0.0000982,0.0001754,0.0003502,0.000625,0.0010354,0.0014368,0.0018381,0.0021464,0.0023293,0.002363,0.002333,0.002122,0.0017783,0.0012874,0.0008679,0.0005213,0.0002743,0.000102,0.0000859,0.0001372,0.0001452,0.0001447,0.0001335,0.0000985,0.0000566,0.0000342,0.0000212,0.0000099,0.0000318,0.0000328,0.0000318,0.0000269,0.0000262,0.0000371,0.0000471,0.0000454,0.0000457,0.000063,0.0000661,0.0000576,0.0000485,0.0000472,0.0000311,0.0000224,0.000027,0.0000271,0.0000346,0.0000417,0.0000388,0.0000372,0.0000391,0.0000297,0.0000147,0.0000087,0.0000173,0.0000322,0.0000508,0.0000508,0.0000599,0.0000758,0.000076,0.0000691,0.0000669,0.0000687,0.0000662,0.0000733,0.0000752,0.0000679,0.0000612,0.0000545,0.0000343,0.0000245,0.0000341,0.0000415,0.0000509,0.0000559,0.0000498,0.0000386,0.0000303,0.0000096,0.0000252,0.0000563,0.0000683,0.0000751,0.0000771,0.0000744,0.0000596,0.0000759,0.0000787,0.0000789,0.0000783,0.0000752,0.0000528,0.0000315,0.0000291,0.0000557,0.0000925,0.0001209,0.0001341,0.0001365,0.0001338,0.0000999,0.0000603,0.0000374,0.0000468,0.0000531,0.0000533,0.0000429,0.000016,0.0000263,0.0000392,0.0000507,0.0000631,0.0000631,0.0000594,0.0000564,0.0000504,0.0000318,0.0000174,0.0000066,0.0000253,0.0000573,0.0000812,0.0000905,0.0000906,0.0000858,0.0000656],"detections":[{"range_m":2.842646,"snr_db":21.2006,"width_m":0.171607}],"noise_floor":0.000039849,"blast_amplitude":0.2699783,"saturated":false}
{"timestamp":1756162803.3999968,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.6408564,-0.6408564,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000574,0.0000522,0.0000356,0.0000197,0.0000074,0.0000052,0.0000096,0.0000269,0.0000456,0.0000289,0.0000396,0.0000523,0.0000352,0.0000234,0.0000173,0.0000287,0.0000473,0.0000577,0.0000309,0.0000574,0.0000874,0.0000764,0.0000573,0.0000446,0.0000056,0.0000112,0.0000271,0.0000131,0,0.0000406,0.0000506,0.0000596,0.0000636,0.0000505,0.0000052,0.0000416,0.0000496,0.0000413,0.0000346,0.0000266,0,0,0.0000073,4e-7,0.0000026,0.0000131,0.0000156,0.0000258,0.0000333,0.0000186,0.000026,0.0000701,0.0000854,0.0000988,0.0001047,0.0000886,0.0000803,0.0001127,0.0001114,0.0001,0.0000882,0.000066,0.0000316,0.0000672,0.0000778,0.0000817,0.0000815,0.0000715,0.000025,0.0000107,0.0000145,0.0000019,0.0000142,0.0000342,0.0000388,0.0000468,0.0000509,0.0000375,0.0000537,0.0000771,0.0000762,0.0000695,0.0000612,0.0000373,0.0000132,0.0000162,0.0000128,0.0000062,0.0000176,0.0000194,0.0000304,0.0000453,0.0000449,0.0000385,0.0000603,0.0000671,0.0000587,0.0000469,0.0000342,0,0.0000136,0.0000316,0.0000374,0.0000393,0.0000391,0.0000158,0.0000135,0.0000291,0.0000337,0.0000547,0.0000774,0.000073,0.0000876,0.0002546,0.0005144,0.0008796,0.0013194,0.0018325,0.0021931,0.0024181,0.0024504,0.0024101,0.0022015,0.0018613,0.0014359,0.001026,0.0006275,0.0003652,0.0001861,0.0000823,0.0000294,0.000031,0.0000436,0.0000556,0.0000669,0.0000698,0.000057,0.0000355,0.0000297,0.0000246,0.0000107,0.0000095,0.000006,0.0000155,0.0000348,0.0000356,0.0000302,0.0000245,0.0000227,0.0000121,0.000005,0.0000112,0.0000208,0.0000316,0.0000364,0.0000337,0.0000497,0.0000615,0.0000628,0.0000627,0.0000601,0.0000432,0.0000232,0.0000195,0.0000122,0.0000018,0.0000075,0.0000107,0.0000179,0.0000373,0.0000441,0.0000536,0.0000605,0.0000583,0.0000393,0.0000299,0.0000438,0.0000584,0.000072,0.000074,0.0000611,0.0000439,0.0000302,0.0000117,0.000014,0.0000247,0.0000262,0.0000261,0.0000238,0.0000139,0.0000166,0.0000243,0.0000211,0.0000331,0.0000569,0.0000683,0.0000775,0.0000838,0.0000822,0.0000783,0.0000923,0.0000925,0.0000866,0.0000752,0.0000584,0.0000261,0.0000334,0.0000409,0.0000463,0.0000559,0.0000599,0.000054,0.000044,0.0000353,0.000028,0.0000375,0.0000428,0.0000381,0.0000319,0.0000383,0.0000367,0.0000306,0.0000203,0.0000083,0.0000295,0.0000497,0.0000505,0.000047,0.0000412,0.0000355,0.0000217,0.0000113,0.0000156,0.0000246,0.0000327,0.0000356,0.0000299,0.0000262,0.0000265,0.0000149],"detections":[{"range_m":2.805707,"snr_db":26.0194,"width_m":0.171607}],"noise_floor":0.000035575,"blast_amplitude":0.2700244,"saturated":false}
{"timestamp":1756162803.4666634,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7848856,-0.4531539,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000115,0.0000065,6e-7,0.0000051,0.0000476,0.0000416,0.0000142,0.0000138,0.0000362,0.0000276,0.0000231,0.0000229,0,0.0000125,0.0000507,0.0000552,0.0000587,0.0000601,0.0000083,0.0000192,0.0000585,0.0000548,0.0000412,0.0000313,0.0000057,0.000001,0.0000326,0.0000405,0.0000493,0.0000539,0.0000297,0,0.0000493,0.0000521,0.0000532,0.0000532,0.0000495,0,0.0000264,0.0000334,0.0000246,0.0000147,0.0000051,0.0000049,0.0000055,0.0000105,0.0000192,0.0000347,0.0000475,0.0000431,0.0000614,0.0000837,0.0000814,0.0000921,0.000099,0.0000829,0.0000558,0.0000666,0.0000616,0.0000304,0.0000114,0.0000281,0.0000456,0.000066,0.0000665,0.0000465,0.0000442,0.0000443,0.0000287,0.0000291,0.0000395,0.0000423,0.0000422,0.0000403,0.0000445,0.0000682,0.0000755,0.0000591,0.0000383,0.0000544,0.0000523,0.0000441,0.0000343,0.0000103,0.0000081,0.000019,0.000015,0.0000198,0.0000578,0.0000585,0.0000561,0.0000464,0.0000295,0,0.0000097,0.0000123,7e-7,0.0000204,0.0000376,0.0000537,0.0000792,0.0000935,0.0000923,0.0000818,0.0000536,0.000115,0.0003241,0.0006256,0.0010044,0.0014564,0.0020008,0.0023515,0.0025571,0.0025903,0.0025409,0.0022969,0.0019187,0.0014759,0.0009395,0.0005839,0.0003321,0.0001572,0.0000709,0.0000536,0.0000434,0.00006,0.0000658,0.0000644,0.0000711,0.0000771,0.0000746,0.0000735,0.0000713,0.0000483,0.0000346,0.0000425,0.0000391,0.0000314,0.0000248,0.0000148,0.0000182,0.0000321,0.0000327,0.0000411,0.0000544,0.000054,0.0000448,0.0000383,0.0000312,0.0000099,0.0000063,0.0000119,0.0000172,0.0000328,0.0000454,0.0000501,0.0000563,0.0000588,0.0000491,0.0000493,0.0000545,0.0000457,0.0000232,0.0000591,0.0000782,0.0000818,0.0000789,0.0000542,0.0000143,0.000034,0.0000426,0.0000577,0.0000757,0.0000757,0.000066,0.0000529,0.000046,0.0000311,0.0000225,0.0000114,0.0000261,0.0000416,0.0000469,0.0000462,0.0000652,0.000075,0.000075,0.0000734,0.0000699,0.0000549,0.0000368,0.0000376,0.0000358,0.0000344,0.000034,0.0000276,0.0000185,0.000034,0.0000381,0.0000445,0.0000518,0.0000509,0.0000518,0.0000668,0.0000699,0.0000634,0.0000468,0.0000434,0.0000643,0.0000753,0.0000757,0.000058,0.0000381,0.0000391,0.0000424,0.0000517,0.0000576,0.0000538,0.000049,0.0000544,0.0000522,0.0000469,0.0000445,0.0000369,0.0000189,0.0000173,0.0000214,0.0000262,0.0000342,0.0000331,0.0000248,0.0000178,0.0000169,0.0000236,0.0000334,0.0000375,0.0000357,0.00004,0.000041,0.0000282],"detections":[{"range_m":2.67729,"snr_db":23.9001,"width_m":0.171607}],"noise_floor":0.0000412,"blast_amplitude":0.2700642,"saturated":false}
{"timestamp":1756162803.53333,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8754261,-0.2345697,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000475,0.0000525,0.0000496,0.0000445,0.0000386,0,0,0.0000014,0,0.0000025,0.0000334,0.0000313,0.0000465,0.0000658,0.0000606,0.000064,0.0000671,0.000032,0.0000035,0.0000142,0.0000022,0,0.0000312,0.0000479,0.0000615,0.0000627,0.0000327,0,0.0000039,0,0,0.0000122,0.0000171,0,0.0000117,0.0000216,0.0000241,0.0000345,0.0000392,0.0000188,0.0000204,0.0000292,0.0000192,0.000027,0.000042,0.0000349,0.0000253,0.0000145,0.0000198,0.00004,0.0000555,0.0000475,0.0000437,0.0000648,0.0000618,0.0000539,0.0000736,0.0000716,0.0000696,0.0000784,0.0000771,0.0000508,0.0000305,0.0000182,0.0000055,0.0000306,0.0000416,0.000041,0.000037,0.0000264,0.0000131,0.0000292,0.000034,0.0000168,0.0000011,0.0000068,0.0000016,0,0.0000208,0.0000209,0.0000182,0.0000144,0.0000298,0.0000473,0.0000578,0.0000494,0.0000254,0.0000317,0.0000325,0.0000408,0.000056,0.000058,0.00003,0.0001783,0.0004186,0.0007797,0.0012623,0.0017955,0.0023901,0.0027588,0.0029129,0.0029133,0.0027817,0.0024581,0.0019905,0.0014667,0.0009863,0.0005239,0.0002558,0.0001076,0.0000481,0.0000331,0.0000349,0.0000323,0.0000241,0.0000381,0.0000371,0.000019,0.0000079,0.000018,0.0000184,0.000018,0.0000184,9e-7,0.0000017,0.0000129,0.0000124,0.0000104,0.0000096,0,0.0000232,0.00005,0.0000598,0.000067,0.0000713,0.0000653,0.0000473,0.0000412,0.0000335,0.0000362,0.000064,0.0000682,0.0000679,0.0000635,0.0000567,0.000045,0.0000465,0.0000463,0.0000224,0.0000022,0.000016,0.0000221,0.0000282,0.0000301,0.0000187,0.0000181,0.0000252,0.0000208,0.0000259,0.000041,0.000041,0.0000365,0.0000256,0.0000266,0.000044,0.0000574,0.0000541,0.0000432,0.0000375,0.0000332,0.000017,0.0000205,0.000023,0.0000241,0.000032,0.0000338,0.0000252,0.0000261,0.0000305,0.000028,0.0000298,0.0000304,0.0000176,0.0000058,0.0000132,0.000017,0.0000296,0.0000462,0.0000484,0.0000524,0.0000557,0.0000507,0.0000373,0.0000333,0.0000322,0.0000428,0.0000648,0.0000671,0.0000659,0.0000583,0.0000483,0.0000424,0.0000626,0.0000654,0.0000579,0.0000445,0.0000302,0.0000168,0.0000381,0.0000537,0.0000539,0.0000534,0.0000524,0.0000411,0.0000252,0.0000257,0.0000277,0.0000342,0.0000385,0.0000346,0.000024,0.0000189,0.0000172,0.000022,0.000047,0.0000554,0.0000642,0.0000741,0.000076,0.0000717,0.0000809,0.0000862,0.0000838,0.0000805,0.0000798,0.0000724],"detections":[{"range_m":2.522419,"snr_db":29.933,"width_m":0.175182}],"noise_floor":0.00003173,"blast_amplitude":0.2700129,"saturated":false}
{"timestamp":1756162803.5999966,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.9063078,0,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000093,0.0000193,0.0000275,0.0000503,0.0000396,0.0000226,0.0000313,0.0000351,0,0.0000018,0.0000141,0.0000059,0.0000316,0.0000491,0.0000186,0.0000276,0.0000651,0.0000706,0.0000713,0.00007,0.0000242,0.0000217,0.0000602,0.0000587,0.0000606,0.0000661,0.0000449,0.0000254,0.0000649,0.0000599,0.0000575,0.0000736,0.0000661,0.0000344,0.0000399,0.0000474,0.0000468,0.000046,0.0000414,0,0.0000292,0.0000451,0.0000426,0.0000516,0.0000555,0.0000341,0.0000173,0.0000079,0.000025,0.0000482,0.0000664,0.0000533,0.0000332,0.0000198,0.0000185,0.0000246,0.0000265,0.0000148,0.0000124,0.0000395,0.0000373,0.0000278,0.0000362,0.0000361,0.0000162,0.0000014,0.0000026,0,0.0000162,0.0000433,0.0000563,0.000068,0.0000731,0.0000603,0.0000883,0.0001098,0.00011,0.0001058,0.0000917,0.0000518,6e-7,0,0,0,0.0000273,0.0000291,0.000032,0.000038,0.0000321,0.0000278,0.000037,0.000033,0.0000864,0.0002958,0.0006725,0.0011035,0.0016185,0.0021337,0.0025895,0.0029129,0.0030132,0.0029981,0.0027304,0.0023054,0.0017667,0.0012316,0.0007879,0.000448,0.0002122,0.000085,0.0000556,0.0000634,0.0000779,0.0000769,0.0000728,0.0000648,0.0000477,0.0000071,0.0000044,0.000009,0.0000172,0.0000264,0.0000281,0.0000155,0.000033,0.0000415,0.0000458,0.0000509,0.0000528,0.0000397,0.0000411,0.0000509,0.0000453,0.0000331,0.0000198,0.0000027,0.0000067,0.0000168,0.0000229,0.0000304,0.0000364,0.0000326,0.0000466,0.0000816,0.0001001,0.0001139,0.0001187,0.0001137,0.0000806,0.0000489,0.0000241,0.000013,0.0000344,0.0000425,0.0000367,0.0000271,0.0000196,0.000003,0.0000094,0.0000372,0.0000521,0.0000619,0.0000622,0.0000481,0.0000278,0.0000276,0.0000239,0.000017,0.000035,0.0000372,0.0000385,0.0000385,0.0000345,0.0000159,0.0000174,0.0000199,0.0000151,0.0000121,0.0000136,0.0000159,0.0000182,0.0000184,0.0000065,0.000011,0.0000132,0.000003,0.0000185,0.000035,0.0000406,0.0000531,0.0000696,0.0000697,0.0000661,0.0000543,0.0000286,0.000019,0.0000411,0.000042,0.0000435,0.0000509,0.0000497,0.0000378,0.0000248,0.0000121,0.0000104,0.0000226,0.0000244,0.0000173,0.0000135,0.0000132,3e-7,0.0000097,0.0000233,0.000032,0.0000515,0.0000684,0.0000697,0.000069,0.0000665,0.0000599,0.000045,0.0000287,0.0000395,0.0000572,0.0000676,0.0000661,0.0000538,0.0000448,0.0000341,0.0000179,0.0000438,0.0000599,0.0000695,0.0000793,0.0000837,0.0000813,0.0000783,0.0000708,0.0000469],"detections":[{"range_m":2.46053,"snr_db":26.8058,"width_m":0.175182}],"noise_floor":0.000037435,"blast_amplitude":0.2699634,"saturated":false}
{"timestamp":1756162803.6666632,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.8754261,0.2345697,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000262,0.0000363,0.0000413,0.0000414,0.0000711,0.0000657,0.0000896,0.0001134,0.0001206,0.000066,0.0000922,0.000115,0.000103,0.0000881,0.0000757,0,0.0000168,0.0000428,0.0000319,0.0000102,0.0000409,0.0000654,0.0000754,0.0000764,0.0000344,0.0000174,0.0000593,0.0000554,0.0000454,0.0000388,0.0000234,0.0000209,0.0000257,0.0000139,0,0.0000212,0.0000296,0.000026,0.0000468,0.0000522,0.0000511,0.0000621,0.0000677,0.0000576,0.0000741,0.000079,0.0000573,0.0000508,0.0000547,0.0000313,0.0000051,0.0000182,0.0000131,0.000004,0.0000182,0.0000255,0.000035,0.0000477,0.0000432,0.0000274,0.000031,0.0000253,0.0000207,0.0000399,0.0000417,0.0000562,0.0000969,0.0001021,0.0000987,0.0000842,0.0000594,0.000015,0.0000586,0.0000842,0.0000895,0.0001005,0.000106,0.0000921,0.0000762,0.0000738,0.0000626,0.0000478,0.0000436,0.0000245,0,0.0000496,0.0001218,0.0002656,0.0005635,0.0009023,0.0013502,0.0018668,0.0023454,0.0027314,0.0029509,0.0029749,0.0028535,0.0025349,0.0020828,0.001549,0.0010479,0.0006448,0.0003392,0.0001192,0.000047,0.0000358,0.0000408,0.0000442,0.0000339,0.0000357,0.0000566,0.000055,0.0000475,0.0000367,0.0000237,0.0000342,0.0000474,0.0000461,0.0000335,0.0000464,0.0000458,0.0000328,0.000022,0.0000174,0.0000011,0.0000156,0.0000219,0.0000215,0.0000211,0.0000224,0.0000122,0.0000118,0.0000189,0.0000197,0.0000236,0.0000246,0.0000115,0.0000032,0.0000212,0.0000205,0.0000145,0.0000096,0.0000127,0.0000339,0.0000632,0.0000709,0.0000764,0.0000817,0.000079,0.0000577,0.0000412,0.0000338,0.0000138,0.0000079,0.0000356,0.0000493,0.000058,0.0000595,0.0000459,0.0000524,0.0000698,0.0000703,0.0000687,0.0000609,0.0000427,0.000034,0.0000526,0.000061,0.0000732,0.0000835,0.0000788,0.0000632,0.0000555,0.0000531,0.000035,0.0000167,0.0000104,0.0000184,0.0000272,0.0000291,0.0000208,0.0000115,0.0000043,0.0000091,0.0000137,0.0000175,0.0000226,0.0000304,0.000035,0.0000304,0.0000367,0.0000469,0.0000436,0.0000357,0.0000344,0.0000304,0.00002,0.0000132,0.0000127,0.0000128,0.0000123,0.0000085,0.0000089,0.0000289,0.0000471,0.0000655,0.0000841,0.0000861,0.0000758,0.0000654,0.0000631,0.0000547,0.000053,0.0000558,0.0000451,0.0000285,0.0000229,0.0000284,0.0000321,0.000036,0.000035,0.000043,0.0000462,0.0000409,0.0000263,0.0000243,0.0000233,0.000018,0.0000289,0.000029,0.0000332,0.0000401,0.0000408,0.0000239,0.0000173,0.0000415,0.0000491,0.0000487,0.0000413,0.0000188],"detections":[{"range_m":2.341614,"snr_db":24.7451,"width_m":0.175182}],"noise_floor":0.000034277,"blast_amplitude":0.2700113,"saturated":false}
{"timestamp":1756162803.7333298,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.7848856,0.4531539,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000309,0.0000344,0.0000356,0.0000369,0.000042,0.0000223,0,0,0.0000176,0.0000138,0.0000057,0.0000188,0.0000362,0.0000558,0.0000645,0.000018,0.0000594,0.0000943,0.0000998,0.0001034,0.0001036,0.0000594,0.0000299,0.000056,0.0000438,0.000034,0.0000503,0.0000372,0.0000185,0.0000405,0.0000344,0.0000314,0.000048,0.0000426,0.0000407,0.0000707,0.0000765,0.0000596,0.000053,0.0000536,0.0000523,0.0000744,0.0000799,0.0000538,0.0000451,0.0000503,0.0000284,0.0000178,0.0000412,0.0000434,0.0000435,0.0000426,0.0000109,0,0.0000293,0.0000303,0.0000317,0.0000357,0.0000278,0.0000121,0.000038,0.0000435,0.0000555,0.0000691,0.0000681,0.0000462,0.0000753,0.000079,0.0000754,0.000072,0.0000723,0.0000539,0.0000735,0.0000825,0.0000648,0.0000551,0.0000772,0.0000808,0.0000784,0.0000506,0.0001688,0.0004056,0.0007399,0.0011665,0.0016958,0.0022548,0.0027115,0.003003,0.0030724,0.0030096,0.0027119,0.0022615,0.0017412,0.0012057,0.0007544,0.0004233,0.0001532,0.0000512,0.0000326,0.0000236,0.0000444,0.000057,0.0000534,0.0000415,0.0000306,0.000004,0.0000017,0.0000212,0.0000232,0.000024,0.0000239,0.0000092,0.0000192,0.0000509,0.0000617,0.0000732,0.0000864,0.000086,0.0000817,0.0000885,0.0000861,0.0000638,0.0000473,0.0000383,0.0000098,0.0000247,0.0000319,0.0000294,0.0000216,0.0000187,0.0000314,0.0000491,0.0000598,0.0000548,0.0000491,0.0000514,0.000044,0.0000511,0.0000632,0.0000599,0.0000404,0.0000273,0.0000208,0.0000141,0.0000236,0.0000236,0.0000193,0.0000207,0.0000226,0.0000301,0.0000365,0.0000375,0.0000246,0.0000397,0.0000465,0.0000371,0.0000189,0.0000169,0.0000283,0.0000328,0.0000329,0.0000214,0.0000131,0.0000225,0.0000243,0.0000315,0.0000414,0.0000411,0.0000486,0.0000569,0.0000513,0.0000289,0.0000147,0.0000335,0.0000435,0.000049,0.0000502,0.0000507,0.0000569,0.0000572,0.0000368,0.0000204,0.0000336,0.0000499,0.0000762,0.0000837,0.0000786,0.0000635,0.0000521,0.0000522,0.0000582,0.0000596,0.0000478,0.000028,0.0000172,0.0000114,0.0000122,0.0000313,0.0000338,0.0000345,0.0000411,0.0000408,0.0000407,0.0000472,0.0000489,0.0000436,0.0000401,0.0000394,0.0000358,0.0000453,0.0000492,0.0000446,0.0000461,0.0000507,0.0000443,0.0000348,0.000027,0.0000183,0.000021,0.0000257,0.0000231,0.0000264,0.000032,0.0000288,0.0000206,0.0000242,0.0000234,0.0000187,0.0000269,0.0000266,0.0000283,0.0000388,0.0000417,0.0000451,0.0000551,0.0000597,0.0000559,0.000056,0.0000584,0.0000528],"detections":[{"range_m":2.219249,"snr_db":25.9613,"width_m":0.171607}],"noise_floor":0.000038964,"blast_amplitude":0.270044,"saturated":false}
{"timestamp":1756162803.7999964,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.6408564,0.6408564,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000682,0.0000653,0.0000411,0.0000602,0.0000809,0.000058,0.0000388,0.0000322,0.0000029,0.000004,0.0000065,0,0.0000314,0.0000618,0.0000634,0.0000633,0.0000592,0.0000125,0.0000018,0.0000184,0.0000046,7e-7,0.0000258,0.0000217,0.0000207,0.0000214,0,0,7e-7,0,0,0.0000122,0.0000204,0.0000141,0.0000228,0.0000264,0.000016,0.0000149,0.0000159,0,0.0000069,0.0000217,0.0000204,0.0000211,0.0000221,0,0.0000017,0.0000357,0.0000357,0.0000355,0.0000366,0.0000182,0.0000118,0.000047,0.0000461,0.0000354,0.0000343,0.0000371,0.0000455,0.0000539,0.0000524,0.0000272,0.0000164,0.0000177,0.0000196,0.0000198,0.0000187,0,0.0000111,0.0000477,0.0000739,0.0000982,0.0001055,0.000091,0.0000864,0.0001038,0.0001034,0.0001122,0.0001198,0.0001112,0.0001084,0.0001182,0.00011,0.0001347,0.0004118,0.0007585,0.001218,0.0017485,0.0022495,0.0026703,0.0029304,0.0029688,0.0028701,0.0025488,0.0020734,0.0015119,0.0009941,0.000589,0.0002873,0.0000636,0.000069,0.0000772,0.0000757,0.0000648,0.0000448,0.0000369,0.0000374,0.0000208,0.0000066,0.0000269,0.0000266,0.0000252,0.0000244,0.0000196,0,0.0000032,0.0000031,0.0000074,0.0000357,0.0000493,0.0000521,0.0000523,0.0000523,0.0000328,0.0000253,0.0000272,0.0000173,0.0000359,0.0000528,0.0000505,0.0000389,0.0000208,0.0000251,0.0000419,0.0000516,0.0000477,0.0000472,0.0000681,0.0000712,0.0000716,0.0000703,0.0000629,0.0000423,0.0000655,0.0000789,0.0000957,0.0001086,0.0001099,0.0000891,0.0000635,0.0000407,0.0000041,0.0000284,0.0000372,0.0000325,0.0000193,0.0000077,0.000017,0.000024,0.0000263,0.0000178,0.0000183,0.000033,0.0000325,0.0000276,0.0000198,0.0000112,0.0000111,0.0000095,0.0000151,0.0000359,0.0000542,0.000057,0.0000478,0.0000467,0.0000479,0.000038,0.0000352,0.0000381,0.0000387,0.0000637,0.0000782,0.0000792,0.0000782,0.0000733,0.0000571,0.0000407,0.0000439,0.0000393,0.0000295,0.0000186,0.0000028,0.000013,0.0000194,0.0000176,0.0000053,0.0000126,0.0000133,0.0000201,0.0000343,0.0000389,0.0000414,0.0000461,0.0000466,0.0000318,0.0000205,0.0000239,0.0000204,0.000015,0.0000139,0.0000163,0.0000189,0.0000198,0.0000119,0.00001,0.0000272,0.000035,0.0000455,0.0000521,0.0000495,0.0000485,0.0000597,0.0000595,0.0000523,0.00004,0.000021,0.0000257,0.0000376,0.0000392,0.0000297,0.0000237,0.0000266,0.0000314,0.0000441,0.0000493,0.0000467],"detections":[{"range_m":2.343495,"snr_db":22.8944,"width_m":0.171607}],"noise_floor":0.000033884,"blast_amplitude":0.2699887,"saturated":false}
{"timestamp":1756162803.866663,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.4531539,0.7848856,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000112,0.0000041,0,0,0.0000404,0.0000373,0.0000086,0,0.000035,0.0000393,0.0000455,0.0000481,0.000012,0.0000337,0.0000634,0.0000761,0.0000908,0.0000968,0.0000546,0.0000716,0.000105,0.0000962,0.0000813,0.0000832,0.000058,0.0000626,0.0000824,0.0000682,0.0000479,0.0000536,0.0000333,0.000001,0.0000067,0.0000014,0,0.0000287,0.0000441,0.0000552,0.0000698,0.0000703,0.0000361,0.0000388,0.0000454,0.0000248,0.0000071,0.0000063,0,0.000015,0.00005,0.000055,0.0000555,0.0000541,0.0000176,0,0.0000092,0.0000027,8e-7,0.0000153,0.0000113,0.0000135,0.0000443,0.0000425,0.0000288,0.0000102,0.0000246,0.0000387,0.0000496,0.0000486,0.0000299,0.0000501,0.0000592,0.0000587,0.0000641,0.0000671,0.0000469,0.0000542,0.0000638,0.0000566,0.0000525,0.0000572,0.0000461,0.0000264,0.0000178,0.0000028,0.0000204,0.000036,0.0000329,0.0000231,0.0000356,0.0000297,0.0000024,0.0000341,0.0000373,0.0000288,0.0001921,0.0005164,0.0009044,0.0013815,0.0018694,0.0023129,0.0026415,0.0027615,0.0027554,0.0025351,0.0021553,0.001658,0.0011537,0.0007268,0.0003912,0.0001506,0.0000559,0.0000696,0.0000683,0.0000521,0.0000218,0.0000019,0.0000096,0.0000151,0.0000365,0.000064,0.0000657,0.0000619,0.0000576,0.0000577,0.0000384,0.0000353,0.0000487,0.000057,0.0000606,0.0000612,0.0000468,0.0000492,0.000055,0.0000415,0.0000305,0.0000532,0.0000619,0.0000645,0.0000643,0.0000531,0.0000293,0.0000402,0.0000393,0.0000351,0.0000308,0.0000235,0.0000174,0.0000559,0.0000724,0.0000847,0.000091,0.0000913,0.0000714,0.00006,0.0000625,0.0000502,0.0000385,0.0000305,0.0000157,0.0000249,0.0000341,0.0000317,0.0000266,0.0000258,0.000016,0.0000161,0.0000426,0.000051,0.0000537,0.0000535,0.0000426,0.0000218,0.0000169,0.0000168,0.0000217,0.0000297,0.0000315,0.0000277,0.0000462,0.0000534,0.0000532,0.0000478,0.000035,0.0000093,0.000029,0.0000357,0.0000354,0.0000419,0.0000459,0.0000381,0.0000219,0.0000272,0.0000373,0.0000449,0.0000478,0.0000419,0.0000275,0.0000383,0.0000393,0.0000386,0.0000321,0.0000185,0.0000038,0.0000118,0.0000124,7e-7,0.0000235,0.0000321,0.0000389,0.0000497,0.0000543,0.0000502,0.0000443,0.0000395,0.0000238,0.0000297,0.0000392,0.0000372,0.0000272,0.0000137,0.0000093,0.000018,0.0000293,0.0000389,0.0000565,0.0000754,0.0000764,0.000075,0.0000728,0.0000697,0.0000563,0.0000477,0.0000405,0.0000145,0.0000281,0.0000555,0.000064,0.0000675,0.0000683,0.0000592],"detections":[{"range_m":2.462697,"snr_db":27.6475,"width_m":0.175182}],"noise_floor":0.000039104,"blast_amplitude":0.2698932,"saturated":false}
{"timestamp":1756162803.9333296,"source":"simulated","device_id":"batvu-reference-01","beam":[-0.2345697,0.8754261,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000818,0.0000688,0.0000454,0.0000194,0.0000311,0.0000311,0.0000221,0.0000071,0.0000294,0.0000437,0.0000639,0.0000706,0.0000381,0.0000354,0.0000522,0.00004,0.000044,0.0000457,0,0.000031,0.0000724,0.0000691,0.0000551,0.0000425,0,0,0.0000422,0.0000545,0.0000654,0.0000688,0.0000455,0.0000144,0.0000608,0.000062,0.0000628,0.0000626,0.0000609,0.0000369,0.0000623,0.0000653,0.0000409,0.000059,0.000072,0.0000656,0.0000753,0.0000787,0.0000551,0.000039,0.0000399,0.0000255,0.0000258,0.0000353,0.0000234,0.0000316,0.0000475,0.0000402,0.0000258,0.0000185,0.0000097,0,0.0000291,0.0000349,0.0000374,0.0000426,0.0000418,0.00003,0.0000321,0.0000287,4e-7,0.0000107,0.0000137,0.0000088,0.0000292,0.0000433,0.0000391,0.0000427,0.0000452,0.0000271,0.0000292,0.0000451,0.0000404,0.0000247,0.0000193,0.0000132,0.0000146,0.0000213,0.0000153,0.0000092,0.0000562,0.0000662,0.0000683,0.0000676,0.0000602,0.0000348,0.0000411,0.0000433,0.0000331,0.0000561,0.0000626,0.0000513,0.000041,0.0001884,0.0004723,0.0008233,0.0012484,0.0017136,0.0021705,0.0025173,0.0026628,0.0026664,0.0025565,0.0021691,0.0017199,0.0012678,0.0008631,0.0005262,0.00029,0.0001516,0.0000871,0.0000848,0.0000767,0.0000446,0.0000264,0.0000192,0.0000104,0.0000415,0.0000517,0.0000554,0.00006,0.000062,0.0000506,0.0000576,0.0000671,0.0000623,0.0000683,0.0000785,0.0000762,0.000071,0.0000682,0.0000597,0.0000405,0.000044,0.0000403,0.000034,0.000041,0.0000392,0.0000217,0.0000055,0.0000104,0.0000106,0.0000106,0.0000111,0,0.0000192,0.0000459,0.0000559,0.0000585,0.0000579,0.0000394,0.0000496,0.0000686,0.0000714,0.0000761,0.0000797,0.0000721,0.0000574,0.0000431,0.000022,0.0000025,0.0000167,0.0000153,0.0000147,0.0000255,0.000025,0.0000166,0.0000099,0.0000128,0.0000191,0.0000298,0.000032,0.0000226,0.000008,0.0000249,0.0000379,0.0000444,0.0000446,0.0000299,0.0000193,0.0000248,0.0000245,0.0000306,0.0000371,0.0000327,0.0000392,0.0000534,0.0000532,0.0000505,0.0000464,0.0000406,0.0000266,0.0000332,0.0000328,0.0000359,0.0000533,0.0000601,0.0000602,0.0000578,0.0000504,0.0000323,0.0000257,0.0000241,0.0000109,0.0000258,0.0000419,0.0000471,0.0000542,0.0000586,0.0000535,0.0000462,0.0000438,0.000035,0.0000104,0.0000445,0.0000659,0.0000796,0.0000839,0.0000812,0.0000625,0.0000478,0.0000377,0.0000237,0.0000309,0.0000373,0.000043,0.0000484,0.0000492,0.000032,0.0000134,0.0000269,0.0000338],"detections":[{"range_m":2.595257,"snr_db":24.5685,"width_m":0.175182}],"noise_floor":0.000035931,"blast_amplitude":0.27005,"saturated":false}
{"timestamp":1756162803.9999962,"source":"simulated","device_id":"batvu-reference-01","beam":[0,0.9063078,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000431,0.0000512,0.0000582,0.000076,0.0000902,0.0000624,0.0000886,0.0001007,0.0000741,0.0000569,0.0000544,0,0.0000184,0.0000599,0.0000623,0.0000619,0.0000577,0.000017,0.0000091,0.000018,0,0.0000168,0.0000383,0.0000238,0.000013,0.0000745,0.0000771,0.0000767,0.0000714,0.0000479,0,0.0000101,0.0000168,0.0000022,0.0000456,0.0000709,0.0000877,0.0000977,0.0000984,0.000055,0.0000531,0.0000671,0.0000601,0.0000502,0.0000432,0.0000269,0.0000482,0.0000675,0.0000568,0.0000488,0.0000557,0.000044,0.0000527,0.0001056,0.0001229,0.0001277,0.0001275,0.0001115,0.0000792,0.0001004,0.0001016,0.0000831,0.0000704,0.000068,0.0000417,0.0000455,0.0000524,0.0000458,0.000039,0.0000378,0.0000407,0.0000521,0.0000549,0.0000325,0.0000094,0.0000094,0,0,0.0000106,0.0000035,0.0000274,0.0000798,0.0000993,0.0001096,0.0001114,0.0000998,0.0000703,0.0000768,0.0000774,0.0000685,0.0000616,0.000055,0.0000146,0.0000112,0.0000263,0.0000288,0.0000447,0.0001202,0.0003343,0.0006511,0.0010659,0.0015391,0.0020205,0.0024136,0.0026314,0.0026696,0.0026341,0.0023397,0.001923,0.0014545,0.001002,0.0006147,0.0003456,0.0001888,0.0000884,0.0000533,0.0000275,0.0000369,0.000047,0.0000471,0.0000186,0.0000147,0.0000189,0.0000157,0.0000372,0.0000526,0.0000529,0.0000512,0.0000467,0.0000317,0.0000473,0.0000585,0.0000555,0.0000497,0.0000543,0.0000493,0.0000386,0.0000562,0.0000602,0.0000629,0.0000632,0.0000587,0.000037,0.0000496,0.0000507,0.0000494,0.0000485,0.0000486,0.0000306,0.0000337,0.000052,0.0000605,0.0000649,0.0000651,0.0000478,0.0000338,0.00004,0.0000359,0.000027,0.0000199,0.0000156,0.0000264,0.0000441,0.0000525,0.0000686,0.0000892,0.0000889,0.0000854,0.0000814,0.0000746,0.0000535,0.0000409,0.0000357,0.0000164,0.0000314,0.0000366,0.0000365,0.0000354,0.000033,0.0000156,0.0000026,0.0000104,0.00002,0.000042,0.000063,0.0000704,0.0000767,0.0000804,0.0000715,0.000054,0.0000411,0.0000324,0.0000229,0.0000164,0.0000068,0.0000181,0.0000372,0.0000429,0.0000477,0.000049,0.0000484,0.0000299,0.0000287,0.0000311,0.0000282,0.0000332,0.0000374,0.0000432,0.000061,0.0000772,0.0000782,0.0000779,0.000076,0.0000697,0.0000888,0.0001087,0.0001086,0.0000986,0.0000701,0.0000409,0.000046,0.0000589,0.0000577,0.0000434,0.0000282,0.0000147,0.000015,0.0000316,0.0000375,0.0000418,0.0000529,0.0000602,0.0000604,0.0000587,0.0000519,0.00003],"detections":[{"range_m":2.60293,"snr_db":23.7083,"width_m":0.175182}],"noise_floor":0.000045183,"blast_amplitude":0.2700521,"saturated":false}
{"timestamp":1756162804.0666628,"source":"simulated","device_id":"batvu-reference-01","beam":[0.2345697,0.8754261,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000425,0.0000391,0.0000281,0.0000212,0.0000198,0.0000024,0.0000102,0.0000355,0.0000501,0.0000172,0.0000158,0.0000286,0.0000107,0.0000116,0.0000356,0.0000309,0.0000237,0.0000138,0.0000094,0.0000188,0.0000339,0.0000278,0.0000389,0.0000447,0.0000089,0,0.000042,0.0000393,0.000026,0.0000259,0.0000474,0.0000644,0.0000726,0.0000621,0.0000271,0.0000482,0.0000526,0.0000468,0.0000676,0.0000702,0.0000557,0.000094,0.0001105,0.0001035,0.0000869,0.0000756,0.0000564,0.0000793,0.0000888,0.0000709,0.0000696,0.0000931,0.0000854,0.0000723,0.000062,0.0000378,0.0000326,0.0000658,0.0000651,0.0000628,0.0000627,0.0000504,0.000016,0.000007,0.0000059,0.0000059,0.0000347,0.0000378,0.0000308,0.0000253,0.000025,0.0000022,0.0000021,0.0000161,0.0000125,0.0000146,0.0000268,0.0000283,0.0000294,0.0000297,0.000015,0.0000081,0.0000118,0,0,0.0000078,0.0000072,0.0000088,0.0000229,0.0000213,0.0000257,0.0000369,0.0000356,0.000019,0.0000394,0.0000461,0.0000368,0.0000476,0.0000675,0.0000778,0.000079,0.0000751,0.0000385,0.0000326,0.0001259,0.0002957,0.0005846,0.0009738,0.0014133,0.0018656,0.0023098,0.0025071,0.0025432,0.0025141,0.0023154,0.0019567,0.0015265,0.0010938,0.000632,0.0003651,0.0002006,0.000092,0.0000395,0.0000269,0.0000174,0.0000262,0.0000305,0.0000348,0.0000472,0.0000544,0.0000549,0.0000661,0.0000732,0.0000601,0.0000352,0.0000159,0.0000347,0.0000506,0.0000638,0.0000628,0.0000689,0.0000772,0.0000741,0.0000691,0.0000773,0.0000762,0.0000697,0.0000859,0.0000858,0.0000766,0.0000659,0.0000561,0.000031,0.0000286,0.0000362,0.0000417,0.0000569,0.0000672,0.0000736,0.0000873,0.0000962,0.0000918,0.0000794,0.0000855,0.0000941,0.0000989,0.0000987,0.0000837,0.0000528,0.0000338,0.0000216,0.0000088,0.0000252,0.0000268,0.0000286,0.0000377,0.0000486,0.0000696,0.0000989,0.0001113,0.0001138,0.0001141,0.000114,0.0000987,0.0000805,0.0000621,0.0000362,0.0000164,0.0000151,0.0000199,0.0000265,0.0000299,0.0000211,0.0000111,0.0000245,0.0000327,0.0000519,0.0000768,0.0000796,0.0000779,0.0000651,0.0000464,0.0000211,0.0000286,0.0000306,0.0000234,0.0000254,0.0000281,0.0000298,0.0000339,0.0000357,0.0000278,0.00003,0.0000364,0.0000317,0.0000242,0.0000367,0.0000504,0.000064,0.000071,0.000067,0.0000546,0.0000508,0.0000475,0.0000413,0.000049,0.0000489,0.0000516,0.0000552,0.0000522,0.0000289,0.0000273,0.0000551,0.0000696,0.000074,0.0000746,0.0000773,0.0000955,0.0001015,0.0000971],"detections":[{"range_m":2.660501,"snr_db":25.2765,"width_m":0.175182}],"noise_floor":0.000038032,"blast_amplitude":0.2700114,"saturated":false}
{"timestamp":1756162804.1333294,"source":"simulated","device_id":"batvu-reference-01","beam":[0.4531539,0.7848856,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000041,0.0000043,0.000005,0.0000171,0.0000339,0.0000482,0.0000269,0.0000404,0.0000446,0.0000048,0.0000155,0.0000441,0.0000397,0.0000333,0.000028,0,0,0.0000197,0.0000275,0.0000553,0.0000804,0.000066,0.0000601,0.0000875,0.0000792,0.0000629,0.0000464,0,0,0.0000123,0.0000097,0.0000097,0.000022,0.0000266,0.0000308,0.0000397,0.0000389,0,0.0000073,0.0000224,0.0000164,0.0000064,0.0000116,0.0000206,0.000033,0.0000411,0.0000283,0.0000418,0.000063,0.0000526,0.0000341,0.0000264,0.0000312,0.000041,0.0000557,0.0000527,0.0000679,0.0000872,0.0000834,0.0000687,0.0000742,0.0000733,0.0000492,0.0000356,0.0000332,0.000006,0.0000272,0.0000611,0.0000826,0.0000999,0.0001055,0.0000864,0.0000789,0.0000804,0.0000565,0.0000376,0.0000671,0.000077,0.0000796,0.0000794,0.0000602,0.000038,0.000052,0.0000494,0.0000381,0.0000374,0.0000313,0.0000144,0.0000413,0.0000611,0.0000779,0.0000893,0.0000907,0.0000626,0.0000586,0.0000637,0.0000665,0.000076,0.0000804,0.0000696,0.0000821,0.0000909,0.0000834,0.0000654,0.0000437,0.0000113,0.0000054,0.0000108,0.0000649,0.0001826,0.0003804,0.0006521,0.0010278,0.0014748,0.0019735,0.0022894,0.0024422,0.0024458,0.0023353,0.0020564,0.0016674,0.0012124,0.0007875,0.000392,0.0001574,0.0000316,0.0000155,0.0000087,0.0000234,0.0000568,0.0000759,0.0000943,0.0001016,0.0000916,0.0000661,0.0000405,0.0000131,0.0000028,0.0000044,0,0.0000082,0.0000231,0.0000234,0.0000185,0.0000327,0.0000403,0.0000504,0.0000634,0.0000666,0.0000677,0.0000738,0.0000756,0.0000577,0.0000408,0.0000282,0.0000037,0.0000153,0.0000298,0.0000297,0.0000274,0.0000199,7e-7,0.0000115,0.0000182,0.0000139,0.0000032,0.000021,0.0000272,0.0000333,0.0000357,0.0000328,0.0000154,0.0000278,0.000038,0.0000517,0.0000724,0.000078,0.0000773,0.0000744,0.0000701,0.000052,0.0000416,0.000045,0.000039,0.0000307,0.0000227,0.0000055,0.0000036,0.0000095,0.0000036,0.0000098,0.0000286,0.0000339,0.0000385,0.0000401,0.0000372,0.0000186,0.0000118,0.000014,0.0000249,0.000041,0.0000441,0.0000389,0.0000294,0.0000229,0.0000181,0.0000288,0.0000353,0.0000345,0.0000305,0.0000209,0.0000173,0.0000371,0.000048,0.0000473,0.0000509,0.0000572,0.0000543,0.0000427,0.0000241,0.0000119,0.0000292,0.00004,0.0000388,0.0000293,0.0000444,0.0000464,0.0000519,0.000064,0.0000671,0.0000655,0.0000617,0.0000566,0.0000416,0.0000307,0.0000318,0.0000238],"detections":[{"range_m":2.798828,"snr_db":23.4996,"width_m":0.175182}],"noise_floor":0.000036393,"blast_amplitude":0.27,"saturated":false}
{"timestamp":1756162804.199996,"source":"simulated","device_id":"batvu-reference-01","beam":[0.6408564,0.6408564,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000042,0.0000463,0.0000526,0.0000576,0.0000601,0.0000088,0.00003,0.0000426,0.000017,0,0.0000227,0.0000315,0.0000484,0.0000597,0.0000335,0.0000373,0.0000528,0.0000287,0.0000091,0.0000442,0.0000436,0.0000403,0.0000337,0.0000126,0.0000234,0.0000321,0.0000112,0,0.0000448,0.000044,0.0000388,0.0000494,0.000052,0.0000276,0.0000222,0.0000215,0,0.000012,0.0000283,0.0000276,0.000029,0.0000304,0.0000102,0.0000175,0.0000271,0.0000163,0.0000211,0.0000487,0.0000543,0.0000624,0.0000677,0.000052,0.0000266,0.0000166,5e-7,0.0000318,0.0000754,0.0000786,0.0000799,0.0000827,0.0000799,0.000049,0.0000395,0.0000385,0.0000197,0.0000104,0.0000051,0.0000196,0.0000431,0.0000576,0.0000577,0.0000697,0.0000759,0.0000636,0.0000537,0.0000598,0.0000501,0.0000522,0.000079,0.0000805,0.0000788,0.0000682,0.0000428,0.0000402,0.000072,0.0000711,0.0000826,0.0001083,0.0001099,0.000099,0.0000819,0.0000615,0.0000152,0.0000445,0.0000604,0.0000728,0.0000893,0.0000957,0.0000858,0.0000775,0.0000809,0.0000689,0.0000633,0.0000725,0.0000691,0.0000716,0.0000944,0.0001245,0.0002153,0.0003913,0.0006396,0.0009835,0.001398,0.0018853,0.0022342,0.0024565,0.0024892,0.0024486,0.0022334,0.0018752,0.0014222,0.0009835,0.0005633,0.0003003,0.0001334,0.0000459,0.0000039,0.0000059,0.0000102,0.0000036,0.0000088,0.0000394,0.0000523,0.0000588,0.0000607,0.0000538,0.0000435,0.000053,0.0000509,0.0000439,0.0000391,0.0000307,0.000011,0.0000412,0.0000469,0.0000524,0.0000638,0.0000666,0.0000616,0.0000578,0.000058,0.0000446,0.0000503,0.0000549,0.0000472,0.0000388,0.000052,0.0000537,0.0000525,0.0000379,0.0000074,0.0000137,0.0000149,0.0000043,0.00002,0.0000414,0.0000438,0.000053,0.0000634,0.0000621,0.0000493,0.0000512,0.0000537,0.0000474,0.0000414,0.0000366,0.0000188,0.0000239,0.0000304,0.0000275,0.0000183,0.0000138,0.0000253,0.0000315,0.0000326,0.0000238,0.0000316,0.0000638,0.0000818,0.0000947,0.0000971,0.0000885,0.0000631,0.0000457,0.0000374,0.0000205,0.0000061,0.0000093,0.0000189,0.0000314,0.0000349,0.0000409,0.0000528,0.0000545,0.0000455,0.0000387,0.000041,0.0000408,0.0000514,0.0000579,0.0000513,0.00004,0.0000309,0.0000162,0.0000144,0.0000261,0.0000249,0.0000149,0.0000197,0.0000277,0.0000302,0.0000315,0.0000303,0.0000415,0.0000568,0.000056,0.0000455,0.0000354,0.0000329,0.0000332,0.0000465,0.0000563,0.0000642,0.0000755,0.000079,0.0000704],"detections":[{"range_m":2.805746,"snr_db":22.5491,"width_m":0.171607}],"noise_floor":0.00004025,"blast_amplitude":0.2700157,"saturated":false}
{"timestamp":1756162804.2666626,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7848856,0.4531539,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000042,0.0000021,0,0,0.0000034,0,0,0.0000311,0.0000769,0.0000752,0.0000929,0.0001051,0.0000942,0.000106,0.00011,0.0000436,0.0000491,0.0000731,0.0000629,0.0000505,0.0000439,0.0000045,0.0000186,0.0000592,0.0000576,0.0000486,0.0000348,0.0000043,0.0000047,0.0000242,0.0000194,0.0000203,0.0000202,0.0000025,0.0000034,0.0000216,0.0000245,0.0000015,0.0000182,0.000024,0.0000181,0.0000151,0.0000166,0.0000255,0.0000459,0.0000519,0.0000311,0.0000303,0.0000455,0.000038,0.0000291,0.0000341,0.0000343,0.0000492,0.000061,0.0000507,0.0000308,0.0000204,0.0000108,0.0000198,0.0000384,0.0000355,0.0000384,0.0000574,0.0000576,0.0000324,0.0000256,0.0000361,0.000043,0.000052,0.0000542,0.0000337,0.0000257,0.000042,0.0000462,0.0000496,0.0000515,0.0000346,0.0000262,0.0000295,0.0000172,0.0000132,0.000033,0.0000337,0.0000349,0.000036,0.0000269,0.000008,0.0000119,0.0000052,0.000004,0.0000359,0.0000423,0.0000441,0.0000445,0.000044,0.0000088,0.000026,0.0000438,0.0000461,0.0000451,0.0000375,0.000009,0.0000323,0.0000868,0.0001951,0.0003941,0.0006831,0.0010463,0.0014809,0.0020055,0.0023443,0.0025447,0.0025784,0.0025318,0.0022959,0.0019269,0.0014908,0.0009558,0.0005947,0.0003327,0.000145,0.000046,0.0000361,0.0000357,0.0000328,0.0000355,0.0000442,0.0000579,0.0000637,0.0000567,0.0000466,0.0000385,0.0000158,0.0000165,0.000039,0.000045,0.0000467,0.000047,0.0000406,0.0000293,0.000027,0.0000134,0,0.0000062,0.0000035,0.000008,0.0000264,0.0000263,0.0000225,0.0000327,0.0000352,0.0000262,0.0000201,0.0000257,0.0000237,0.0000184,0.0000185,0.0000396,0.0000617,0.0000744,0.0000747,0.000084,0.0000888,0.0000806,0.0000644,0.0000538,0.0000426,0.0000264,0.0000285,0.0000255,0.0000202,0.0000311,0.0000312,0.0000279,0.0000289,0.0000305,0.0000432,0.0000602,0.0000634,0.0000595,0.0000667,0.0000719,0.0000695,0.0000725,0.000075,0.0000669,0.000059,0.000056,0.0000454,0.0000316,0.0000362,0.0000363,0.0000397,0.0000442,0.0000411,0.0000427,0.0000561,0.0000561,0.0000498,0.0000405,0.000035,0.0000258,0.0000269,0.0000281,0.0000342,0.000051,0.0000535,0.0000487,0.0000502,0.0000539,0.0000514,0.0000537,0.0000548,0.0000429,0.0000307,0.0000263,0.0000173,0.0000049,0.0000012,0.0000051,0.0000321,0.0000647,0.0000831,0.0000964,0.0001021,0.0000998,0.0000825,0.0000672,0.0000509,0.000026,0.000008,0.0000072,0.0000105,0.0000177,0.0000226,0.0000288,0.0000392,0.0000432,0.000038],"detections":[{"range_m":2.677521,"snr_db":26.6231,"width_m":0.171607}],"noise_floor":0.000034531,"blast_amplitude":0.2700238,"saturated":false}
{"timestamp":1756162804.3333292,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8754261,0.2345697,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000153,0.0000089,0,0.0000011,0.0000486,0.0000431,0.0000107,0,0.0000459,0.0000517,0.000054,0.0000556,0.000023,0.0000494,0.0000655,0.0000384,0.0000488,0.0000608,0.0000305,0.0000068,0.000047,0.0000569,0.0000616,0.0000642,0.0000305,0.0000322,0.0000702,0.0000652,0.0000544,0.0000446,0.0000158,0.0000136,0.0000249,0.0000158,0,0.0000232,0.0000321,0.0000302,0.0000296,0.0000293,0.0000195,0.0000317,0.000034,0.0000028,0.0000159,0.0000278,0.0000155,0,0.0000302,0.0000414,0.0000495,0.0000544,0.0000356,0.0000453,0.0000654,0.0000598,0.0000501,0.0000461,0.0000309,0.000006,0.0000392,0.000038,0.0000341,0.0000498,0.0000508,0.0000361,0.0000344,0.0000346,0.000027,0.0000345,0.0000365,0.0000151,3e-7,0.0000045,0.000003,0.0000323,0.00006,0.0000644,0.0000643,0.0000594,0.0000329,0.000009,0.0000241,0.0000215,0.0000168,0.000013,0.0000013,0.0000183,0.0000462,0.0000455,0.0000519,0.0000668,0.0000665,0.0000556,0.0001144,0.000262,0.0004823,0.0008169,0.0012403,0.0017389,0.0022532,0.0026604,0.0028811,0.0028855,0.0027666,0.0024215,0.0019476,0.0014489,0.0009772,0.0005767,0.0002837,0.000056,0.0000434,0.0000465,0.0000311,0.0000041,0.0000241,0.000024,0.0000206,0.0000449,0.0000508,0.0000555,0.0000594,0.00006,0.0000423,0.0000563,0.0000619,0.0000591,0.0000535,0.0000446,0.0000167,0.0000072,0.0000151,0.0000087,0.0000097,0.0000151,0.0000075,0.000001,0.0000278,0.0000337,0.0000391,0.000048,0.0000462,0.0000398,0.0000323,0.000029,0.0000529,0.0000824,0.0000832,0.0000773,0.000078,0.0000794,0.0000676,0.0000585,0.0000542,0.0000369,0.0000359,0.0000416,0.00004,0.0000398,0.0000397,0.0000311,0.0000415,0.00005,0.0000463,0.0000387,0.0000379,0.0000334,0.000029,0.000037,0.0000338,0.0000262,0.0000336,0.0000327,0.0000271,0.0000382,0.0000428,0.0000551,0.0000782,0.0000855,0.0000851,0.0000805,0.0000768,0.000066,0.0000585,0.0000554,0.0000432,0.000033,0.0000277,0.0000188,0.0000153,0.0000179,0.0000252,0.0000461,0.0000669,0.0000705,0.0000734,0.0000747,0.000072,0.0000554,0.000054,0.0000534,0.0000569,0.0000689,0.0000712,0.0000617,0.0000443,0.0000176,0.0000199,0.0000325,0.0000355,0.0000281,0.0000329,0.0000394,0.0000343,0.0000271,0.0000275,0.0000318,0.000049,0.0000657,0.0000656,0.0000597,0.0000433,0.0000199,0.0000121,0.0000278,0.0000279,0.0000279,0.0000399,0.0000399,0.0000374,0.0000405,0.0000412,0.0000284,0.0000203,0.0000379,0.0000553,0.0000658,0.0000685,0.0000602],"detections":[{"range_m":2.488204,"snr_db":27.0248,"width_m":0.175182}],"noise_floor":0.000034473,"blast_amplitude":0.2700443,"saturated":false}
{"timestamp":1756162804.3999958,"source":"simulated","device_id":"batvu-reference-01","beam":[0.9063078,0,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000094,0.0000182,0.0000281,0.0000366,0.0000448,0.000025,0,0.0000249,0.0000515,0.00004,0.0000462,0.0000508,0.0000202,0.0000445,0.0000671,0.0000534,0.0000456,0.0000463,0.0000188,0.0000341,0.0000453,0.0000167,0.0000324,0.0000653,0.0000561,0.0000392,0.0000245,0.0000042,0.0000114,0.0000201,0.000007,0.0000028,0.0000133,0.0000053,0,0.000022,0.0000312,0.0000232,0.0000106,0.0000131,0.00002,0.0000241,0.000025,0,0.0000346,0.0000526,0.0000526,0.0000508,0.0000458,0.0000166,0.0000185,0.0000251,0.0000028,0.0000021,0.0000284,0.000026,0.0000202,0.0000151,0.0000015,0.0000217,0.0000489,0.0000473,0.0000629,0.0000986,0.0001026,0.0000946,0.0000785,0.0000633,0.0000287,0.0000265,0.0000279,0.0000025,0.0000099,0.0000313,0.0000324,0.0000341,0.0000348,0.0000116,0,0.0000221,0.0000201,0.0000095,0.0000113,0.0000087,0.0000023,0.0000354,0.0000419,0.0000415,0.0000332,0.0001457,0.0003449,0.0006521,0.0010483,0.0015535,0.0021156,0.0026915,0.0029911,0.0030703,0.0030514,0.0028172,0.0024108,0.0019194,0.0013963,0.0008384,0.0004897,0.0002358,0.0000858,0.0000312,0.0000373,0.0000551,0.0000761,0.0000747,0.0000713,0.0000707,0.0000624,0.0000399,0.0000237,0.0000129,0.000023,0.000032,0.0000301,0.0000142,0.0000244,0.0000286,0.0000237,0.0000242,0.0000264,0.0000207,0.0000217,0.0000225,0.0000066,0.0000088,0.0000289,0.000032,0.0000372,0.0000415,0.0000331,0.0000182,0.0000144,0.0000139,0.000013,0.0000173,0.000016,0.0000141,0.000017,0.0000184,0.0000226,0.0000251,0.0000226,0.0000107,0.0000239,0.0000346,0.0000448,0.000053,0.0000546,0.000037,0.0000361,0.000042,0.0000399,0.0000519,0.0000675,0.0000718,0.0000767,0.0000792,0.0000721,0.0000783,0.000096,0.0000993,0.0001077,0.000121,0.0001192,0.0001094,0.0000952,0.0000738,0.0000393,0.0000337,0.0000414,0.0000552,0.000076,0.0000814,0.0000804,0.0000774,0.0000758,0.0000647,0.000066,0.0000702,0.0000697,0.0000841,0.0000977,0.0000977,0.0000952,0.0000885,0.0000671,0.0000468,0.0000481,0.0000463,0.0000424,0.0000438,0.0000417,0.0000286,0.000017,0.0000121,0.0000303,0.000052,0.0000589,0.0000614,0.0000662,0.0000668,0.0000524,0.0000393,0.0000323,0.0000204,0.0000265,0.0000408,0.0000476,0.0000577,0.000064,0.0000604,0.0000534,0.0000507,0.0000456,0.0000332,0.0000304,0.0000286,0.00003,0.0000391,0.0000386,0.0000307,0.000025,0.0000386,0.0000562,0.0000775,0.0000923,0.0001053,0.0001125,0.0001126,0.0000901,0.0000677,0.0000544,0.0000391],"detections":[{"range_m":2.388322,"snr_db":28.2226,"width_m":0.171607}],"noise_floor":0.000038313,"blast_amplitude":0.2700501,"saturated":false}
{"timestamp":1756162804.4666624,"source":"simulated","device_id":"batvu-reference-01","beam":[0.8754261,-0.2345697,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000054,0,0,0,0.0000706,0.0000748,0.0000646,0.0000454,0.0000296,0,0.0000192,0.0000339,0.0000247,0.0000427,0.0000575,0.0000299,0.0000157,0.0000175,0.0000095,0.0000078,0.0000167,0.000039,0.000059,0.0000694,0.0000386,0.0000386,0.0000835,0.0000808,0.0000713,0.0000594,0.0000206,0,0.0000206,0.0000253,0.0000357,0.0000454,0.0000446,0,0.0000162,0.000021,0.0000013,0.0000079,0.0000284,0.0000289,0.000033,0.0000347,0.0000079,0.0000061,0.0000323,0.0000346,0.0000351,0.0000348,0.0000016,0,0.0000215,0.0000176,0.0000284,0.0000604,0.0000591,0.0000456,0.0000273,0.0000235,0.0000533,0.0000864,0.0000894,0.0000899,0.0001066,0.0001065,0.0000827,0.0000632,0.0000534,0.0000255,0.0000214,0.0000267,0.0000165,0.0000347,0.0000498,0.0000483,0.0000487,0.0000509,0.000037,0.0000221,0.0000315,0.0000261,0.0000175,0.0000212,0.000014,0.0000016,0.0000477,0.0000481,0.000032,0.0001372,0.0003508,0.0006721,0.0011041,0.0017026,0.0022279,0.0026961,0.0029819,0.0030407,0.0030117,0.0027789,0.0023442,0.0017141,0.0012176,0.0007816,0.0004434,0.0002139,0.0000648,0.0000297,0.0000335,0.0000158,0,0.0000035,0.0000066,0.000018,0.0000371,0.0000439,0.0000654,0.0000965,0.0001004,0.0001001,0.0000966,0.0000905,0.0000626,0.0000549,0.0000582,0.0000568,0.0000592,0.0000592,0.0000384,0.0000209,0.0000336,0.000032,0.0000276,0.0000225,0.0000063,0,0.0000195,0.0000259,0.0000329,0.0000394,0.0000354,0.0000324,0.0000459,0.000046,0.0000523,0.0000826,0.0000893,0.0000907,0.0000905,0.0000888,0.0000695,0.000061,0.0000609,0.0000386,0.0000165,0.0000139,0.0000234,0.0000372,0.0000488,0.000048,0.0000453,0.0000399,0.0000237,0.0000154,0.0000362,0.0000454,0.000055,0.0000616,0.0000564,0.0000468,0.0000619,0.0000627,0.0000613,0.0000579,0.0000503,0.0000179,0.0000175,0.0000203,0.0000164,0.0000195,0.0000226,0.0000182,0.0000371,0.0000461,0.0000451,0.0000434,0.0000511,0.0000551,0.0000606,0.000064,0.0000566,0.0000544,0.0000665,0.0000662,0.0000643,0.0000667,0.0000655,0.0000662,0.000073,0.0000715,0.0000609,0.0000595,0.0000599,0.0000419,0.0000192,0.0000225,0.0000362,0.0000435,0.0000445,0.0000317,0.0000168,0.0000077,0.0000169,0.0000414,0.0000601,0.0000613,0.0000597,0.0000529,0.0000387,0.0000206,0.0000309,0.0000385,0.000048,0.000055,0.0000533,0.0000402,0.0000294,0.0000174,0.0000091,0.0000293,0.0000332,0.0000281,0.0000144,0.0000212,0.0000293,0.0000295,0.0000268,0.0000107],"detections":[{"range_m":2.422224,"snr_db":26.5946,"width_m":0.171607}],"noise_floor":0.000035016,"blast_amplitude":0.2699404,"saturated":false}
{"timestamp":1756162804.533329,"source":"simulated","device_id":"batvu-reference-01","beam":[0.7848856,-0.4531539,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000537,0.0000461,0.0000269,0.0000053,0.0000255,0.0000393,0.0000395,0.0000317,0.0000194,0.0000162,0.0000284,0.0000344,0.0000243,0.0000459,0.0000587,0.0000233,0.0000094,0.0000198,0.0000097,0.000007,0.0000176,0.0000201,0.0000373,0.000054,0.0000344,0.0000269,0.0000583,0.0000541,0.0000511,0.0000538,0.0000346,0.0000421,0.0000916,0.0000903,0.0000801,0.0000653,0.0000496,0.0000094,0.0000224,0.0000263,0.0000284,0.0000311,0.0000302,0.0000014,0.0000244,0.0000296,0.0000067,0.0000347,0.0000606,0.0000591,0.0000538,0.0000469,0.0000085,0,0.0000284,0.0000282,0.0000298,0.0000319,0.0000215,0,0.0000048,0.0000056,0.0000195,0.0000512,0.0000554,0.0000588,0.0000661,0.0000643,0.000043,0.0000645,0.0000705,0.0000543,0.0000291,0.0000381,0.000053,0.00006,0.0000605,0.0000349,0.0000211,0.0000379,0.0000358,0.0000381,0.0000438,0.0000347,0.000032,0.000048,0.0000459,0.0000385,0.0000393,0.0000318,0.0000286,0.0000617,0.0000687,0.0000705,0.0000719,0.0000723,0.0000466,0.0000532,0.0000548,0.0000427,0.0001954,0.0004381,0.000846,0.0012847,0.0017556,0.0022024,0.0025672,0.0027581,0.0027669,0.0026761,0.0023823,0.0018377,0.0013333,0.0008945,0.0005539,0.000305,0.0001537,0.0000753,0.0000389,0.0000435,0.0000414,0.0000322,0.0000457,0.0000489,0.0000478,0.0000756,0.0000875,0.000092,0.0000952,0.0000956,0.0000776,0.0000608,0.0000667,0.0000616,0.0000545,0.0000461,0.0000256,0.0000132,0.000019,0.0000137,0.0000062,0.0000277,0.0000337,0.0000423,0.0000518,0.0000503,0.0000352,0.0000334,0.000042,0.0000552,0.0000663,0.0000679,0.000054,0.0000467,0.0000485,0.000033,0.0000194,0.0000137,0.0000081,0.0000292,0.0000556,0.0000669,0.0000723,0.0000721,0.0000557,0.0000303,0.0000135,0.000017,0.000025,0.0000291,0.0000227,0.0000083,0.0000212,0.0000278,0.0000506,0.0000855,0.0001057,0.0001093,0.0001091,0.0001034,0.0000759,0.0000555,0.0000475,0.0000315,0.0000269,0.0000394,0.0000427,0.0000429,0.000041,0.0000253,0.0000097,0.0000205,0.0000194,0.0000225,0.0000279,0.0000238,0.000011,0.0000251,0.0000283,0.0000279,0.0000206,0.0000121,0.0000157,0.0000179,0.0000179,0.0000064,0.0000144,0.0000154,0.0000043,0.0000212,0.0000317,0.0000318,0.0000299,0.0000335,0.0000415,0.0000543,0.0000659,0.000075,0.0000901,0.0001006,0.0000983,0.0000867,0.0000745,0.0000654,0.0000542,0.0000502,0.0000458,0.0000295,0.0000213,0.0000179,0.0000121,0.0000378,0.0000497,0.0000505,0.0000479,0.0000391,0.0000139,0.000009,0.0000153,0.0000152],"detections":[{"range_m":2.579358,"snr_db":23.8892,"width_m":0.171607}],"noise_floor":0.000034386,"blast_amplitude":0.26999,"saturated":false}
{"timestamp":1756162804.5999956,"source":"simulated","device_id":"batvu-reference-01","beam":[0.6408564,-0.6408564,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000347,0.0000438,0.0000453,0.0000442,0.0000441,0.00003,0.0000177,0.0000221,0.0000232,0,0.0000248,0.0000353,0.0000097,0.0000091,0.0000341,0.0000321,0.0000312,0.0000334,0.0000068,0.0000185,0.0000285,0.0000053,0.0000305,0.0000568,0.0000442,0.0000546,0.0000889,0.0000811,0.0000601,0.0000383,0,0.0000048,0.0000125,0.0000071,0.0000091,0.000026,0.0000297,0.0000204,0.0000523,0.0000591,0.0000568,0.0000651,0.0000686,0.0000462,0.0000375,0.0000389,0.0000108,0.0000106,0.000029,0.0000299,0.0000435,0.0000596,0.0000481,0.0000333,0.0000225,0,0.000014,0.0000402,0.0000382,0.000033,0.0000441,0.0000397,0.0000203,0.0000076,0.0000299,0.0000489,0.0000628,0.0000618,0.0000389,0.0000497,0.0000575,0.0000518,0.0000458,0.0000394,0.0000056,0.0000212,0.00004,0.0000449,0.0000522,0.000057,0.0000445,0.0000333,0.0000529,0.0000564,0.0000631,0.0000721,0.0000681,0.0000668,0.0000824,0.0000782,0.0000573,0.0000352,0.0000284,0.0000512,0.0000696,0.0000721,0.0000502,0.0000571,0.0000627,0.0000571,0.0000489,0.0000388,0.0000102,0.0000081,0.0000137,0.0000103,0.000013,0.0000139,0.0000299,0.000098,0.0002549,0.0004681,0.000799,0.0012238,0.0016632,0.0020685,0.0023614,0.0024576,0.0024431,0.0022855,0.0019796,0.001561,0.0011277,0.0007442,0.0004287,0.0002296,0.0001334,0.0000922,0.0000703,0.0000628,0.0000489,0.0000596,0.0000719,0.0000661,0.0000504,0.0000324,0.000026,0.0000464,0.0000658,0.000071,0.0000893,0.0001124,0.000115,0.0001178,0.0001209,0.0001181,0.0000977,0.0000837,0.0000721,0.000044,0.0000191,0.0000116,0.0000218,0.0000289,0.0000309,0.0000185,0.000036,0.0000482,0.0000518,0.0000611,0.0000691,0.0000655,0.0000556,0.0000436,0.0000317,0.0000431,0.0000586,0.0000583,0.0000576,0.0000615,0.0000565,0.0000424,0.0000329,0.0000312,0.00004,0.0000512,0.0000527,0.0000356,0.0000216,0.0000136,0.0000019,0.0000202,0.0000288,0.0000266,0.0000176,0.0000107,0.00002,0.0000264,0.0000292,0.0000225,0.000022,0.0000353,0.0000424,0.0000555,0.0000642,0.0000597,0.0000385,0.000032,0.0000547,0.0000743,0.0000815,0.0000796,0.0000664,0.0000654,0.000066,0.0000497,0.0000278,0.0000226,0.0000347,0.0000396,0.0000404,0.0000415,0.000065,0.0000817,0.0000815,0.0000783,0.0000772,0.0000684,0.00005,0.0000268,0.0000213,0.0000482,0.0000628,0.0000625,0.0000598,0.000057,0.0000501,0.0000298,0.0000197,0.0000188,0.000028,0.0000503,0.0000596,0.0000599,0.000056,0.0000451,0.00002,0.0000102,0.0000181,0.0000263],"detections":[{"range_m":2.756516,"snr_db":23.0926,"width_m":0.171607}],"noise_floor":0.000039018,"blast_amplitude":0.2699787,"saturated":false}
{"timestamp":1756162804.6666622,"source":"simulated","device_id":"batvu-reference-01","beam":[0.4531539,-0.7848856,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000111,0.0000167,0.0000198,0.0000249,0.0000511,0.0000403,0.0000061,0.0000073,0.0000337,0.0000354,0.0000512,0.0000572,0.0000275,0.0000704,0.0000979,0.0000888,0.0000797,0.0000747,0.0000254,0.000021,0.0000561,0.0000551,0.0000545,0.0000521,0.0000105,0.0000058,0.00005,0.0000498,0.0000526,0.0000573,0.0000396,0.0000427,0.0000759,0.0000713,0.0000562,0.0000895,0.000097,0.0000896,0.0000844,0.0000775,0.0000321,0.0000435,0.0000544,0.0000415,0.0000236,0.0000147,0.0000354,0.000054,0.0000596,0.0000361,0.0000219,0.0000469,0.0000431,0.0000442,0.0000571,0.0000512,0.0000445,0.0000416,0.0000253,0,0.0000075,0.0000026,0,0.0000067,0.0000085,0,0.0000194,0.0000279,0.0000282,0.0000264,0.0000196,0.0000128,0.0000314,0.0000384,0.0000232,0.0000355,0.0000481,0.0000424,0.0000318,0.0000219,0.0000162,0.0000302,0.0000384,0.000029,0.0000228,0.0000364,0.0000331,0.0000155,0.0000129,0.0000232,0.0000357,0.0000526,0.0000525,0.000038,0.0000258,0.0000173,0.0000306,0.0000606,0.000069,0.0000663,0.0000623,0.0000626,0.0000462,0.0000401,0.0000446,0.0000337,0.0000212,0.0000318,0.0000323,0.000033,0.0000329,0.000015,0.000004,0.0000518,0.0001265,0.0002861,0.0005458,0.0009447,0.0013461,0.0017613,0.0020998,0.0023256,0.0023928,0.0023821,0.0022009,0.001866,0.0013617,0.0009236,0.0005626,0.0003096,0.0001341,0.0000294,0.0000541,0.0000539,0.0000408,0.0000143,0.0000372,0.0000561,0.0000663,0.0000635,0.0000808,0.0001047,0.000106,0.0001059,0.0001037,0.0000945,0.0000628,0.0000385,0.0000327,0.0000291,0.0000272,0.0000223,0.000006,0.0000262,0.0000392,0.0000407,0.0000423,0.0000432,0.0000304,0.0000285,0.0000425,0.0000434,0.0000428,0.0000383,0.0000288,0.000032,0.0000374,0.0000334,0.0000328,0.0000465,0.0000453,0.0000399,0.000043,0.0000415,0.000029,0.0000155,0.0000175,0.0000322,0.0000454,0.0000478,0.0000416,0.0000365,0.0000341,0.0000236,0.0000224,0.0000233,0.0000139,0.0000234,0.0000319,0.0000303,0.0000311,0.0000359,0.0000303,0.0000266,0.0000369,0.0000399,0.0000493,0.0000625,0.0000625,0.000063,0.0000685,0.0000664,0.0000485,0.0000292,0.0000181,0.0000111,0.0000102,0.0000072,0,0.0000082,0.0000134,0.0000108,0.0000064,0.0000203,0.0000234,0.0000236,0.000022,0.0000101,0.0000029,0.0000181,0.0000189,0.000018,0.0000101,0.0000125,0.0000225,0.0000292,0.0000279,0.0000239,0.0000368,0.0000368,0.000034,0.0000321,0.0000319,0.000021,0.0000341,0.0000458,0.0000464,0.0000446,0.0000366,0.0000191],"detections":[{"range_m":2.846889,"snr_db":22.8317,"width_m":0.171607}],"noise_floor":0.000035156,"blast_amplitude":0.2700525,"saturated":false}
{"timestamp":1756162804.7333288,"source":"simulated","device_id":"batvu-reference-01","beam":[0.2345697,-0.8754261,0.4226183],"start_range_m":0.3,"range_step_m":0.018359375,"profile":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0000149,0.0000193,0.0000283,0.0000325,0.0000343,0.0000092,0.0000347,0.0000403,9e-7,0.0000555,0.0000936,0.0000941,0.0000929,0.0000868,0.0000184,0.0000071,0.0000419,0.0000348,0.0000592,0.0000892,0.0000811,0.0000824,0.0000964,0.0000786,0.000045,0.0000709,0.0000682,0.0000653,0.0000577,0.000028,0.0000097,0.0000385,0.0000416,0.0000163,0.0000457,0.0000496,0.0000203,0.000019,0.0000549,0.0000628,0.0000629,0.0000594,0.0000136,0,0.000016,0.0000085,0,0.0000088,0.000008,0.0000087,0.0000311,0.0000357,0.0000414,0.000045,0.0000343,0.000007,0.0000307,0.0000284,0.0000173,0.000019,0.0000201,0.0000167,0.0000446,0.0000521,0.0000586,0.0000658,0.0000673,0.000044,0.0000587,0.0000745,0.0000688,0.0000582,0.0000458,0.0000106,0.0000086,0.00003,0.0000282,0.0000202,0.0000157,0.0000237,0.0000411,0.0000584,0.0000564,0.0000733,0.000115,0.000116,0.000113,0.0001009,0.0000793,0.0000368,0.0000332,0.0000359,0.0000261,0.0000527,0.0000621,0.0000608,0.0000565,0.0000572,0.0000428,0.0000258,0.0000136,0.0000049,0.0000129,0.0000187,0.0000273,0.000107,0.0003059,0.0005509,0.0008874,0.0012892,0.0016919,0.0020647,0.0023346,0.0024101,0.002384,0.0021933,0.0018542,0.0014213,0.0010049,0.0006625,0.0003875,0.0002018,0.0000786,0.0000178,0.000016,0.0000179,0.0000042,0,0.0000041,0.0000101,0.0000394,0.0000671,0.0000693,0.0000666,0.0000527,0.0000275,0.000026,0.0000404,0.0000398,0.0000385,0.0000366,0.000024,0.0000137,0.0000462,0.0000507,0.0000574,0.0000675,0.0000693,0.000058,0.000061,0.0000672,0.0000638,0.0000716,0.0000777,0.0000755,0.0000734,0.0000712,0.0000555,0.0000327,0.0000157,0,0,0.0000053,0.0000024,0.0000136,0.0000527,0.0000711,0.0000846,0.0000894,0.0000864,0.0000653,0.0000589,0.0000607,0.0000513,0.0000478,0.0000496,0.0000587,0.0000742,0.0000795,0.0000721,0.0000577,0.0000462,0.0000355,0.0000304,0.000028,0.000015,0,0.00001,0.0000111,0.0000133,0.0000146,0.0000088,0.00001,0.0000308,0.0000373,0.0000531,0.0000761,0.0000833,0.000087,0.0000889,0.0000892,0.0000764,0.0000757,0.0000769,0.0000708,0.0000848,0.0000925,0.0000903,0.0000796,0.0000658,0.0000613,0.0000771,0.0000873,0.000089,0.0000979,0.0001064,0.0001034,0.0000872,0.0000578,0.0000244,0.0000167,0.0000392,0.0000437,0.0000471,0.0000536,0.0000528,0.0000537,0.0000633,0.0000654,0.0000612,0.0000597,0.0000604,0.0000472,0.0000351,0.0000333,0.0000406],"detections":[{"range_m":2.754237,"snr_db":26.402,"width_m":0.171607}],"noise_floor":0.000041085,"blast_amplitude":0.2699899,"saturated":false}
@@ -0,0 +1,260 @@
//! ADR-262 P4 gates for the second modality.
//!
//! Same shape as `p1_gates.rs`: round-trip, fusability, privacy-safety,
//! determinism. Not accuracy — nothing here claims an ultrasonic scan is
//! *right*, only that it is well-formed, signed, correctly classified, and that
//! the things it must refuse to do, it refuses.
//!
//! The fixture is not hand-written. `batvu_living_room.ultrasonic.jsonl` is
//! produced by BatVu's own `npm run artifacts` — a 72-ping simulated sweep,
//! written by its TypeScript emitter — and copied here verbatim. The same file
//! is a test fixture in `ruvnet/rufield`, so a schema drift between BatVu's
//! emitter and RuField's parser fails a build in one of three repositories
//! rather than an ingest in a deployment.
use rufield_core::{FieldEvent, FusionEngine, InferenceQuery, Modality, PrivacyClass};
use rufield_fusion::RuFieldFusion;
use rufield_provenance::{is_fusable, verify_event};
use wifi_densepose_rufield::{
network_egress_allowed, ScanSource, UltrasonicScan, ULTRASONIC_EGRESS_CLASS,
};
const SCAN: &str = include_str!("fixtures/batvu_living_room.ultrasonic.jsonl");
fn scan() -> UltrasonicScan {
UltrasonicScan::load(SCAN, "living_room", ScanSource::Simulated).expect("fixture loads")
}
// ── round-trip ───────────────────────────────────────────────────────────────
#[test]
fn gate_round_trip_every_event_is_well_formed_and_serializes() {
let mut s = scan();
assert_eq!(s.ping_count(), 72);
assert_eq!(s.device_id(), "batvu-reference-01");
assert!(!s.calibration_id().is_empty());
let events = s.events().expect("events");
assert_eq!(events.len(), 72);
let mut previous = 0u64;
for event in &events {
event
.validate_evidence_at(event.timestamp_ns)
.expect("structural evidence invariants hold");
assert_eq!(event.tensor.modality, Modality::Ultrasonic);
assert_eq!(event.sensor.vendor, "batvu");
assert_eq!(event.observation.zone_id.as_deref(), Some("living_room"));
// Every profile value finite and non-negative. `FieldTensor::validate`
// checks only shape and axis rank, so a NaN would serialize to JSON
// `null` and then fail to deserialize as an f32 on the far side of the
// wire — the worst place to find it. The adapter rejects it at parse.
assert!(
event
.tensor
.values
.iter()
.all(|v| v.is_finite() && *v >= 0.0),
"profile values are finite and non-negative"
);
// Strictly increasing, which RuField's replay watermark requires in
// every trust mode and silently drops what does not satisfy.
assert!(event.timestamp_ns > previous);
previous = event.timestamp_ns;
// serde round-trip, byte-stable.
let json = serde_json::to_string(event).expect("serializes");
let back: FieldEvent = serde_json::from_str(&json).expect("deserializes");
assert_eq!(*event, back);
}
let mut ids: Vec<&str> = events.iter().map(|e| e.event_id.as_str()).collect();
ids.sort_unstable();
ids.dedup();
assert_eq!(ids.len(), events.len(), "event ids are unique");
}
// ── fusability ───────────────────────────────────────────────────────────────
#[test]
fn gate_every_event_carries_a_signature_that_verifies() {
let mut s = scan();
let events = s.events().expect("events");
for event in &events {
verify_event(event).expect("ed25519 signature verifies");
assert!(is_fusable(event));
}
// And tampering breaks it, so the signature is load-bearing rather than
// decorative.
let mut tampered = events[0].clone();
tampered.tensor.values[0] = 999.0;
assert!(verify_event(&tampered).is_err());
}
#[test]
fn gate_fusion_ingests_every_event() {
let mut s = scan();
let mut engine = RuFieldFusion::new();
for event in s.events().expect("events") {
engine.ingest(event).expect("fusion accepts the event");
}
}
// ── privacy safety — the correctness item ────────────────────────────────────
#[test]
fn gate_coarse_scan_passes_the_egress_gate_intact() {
// The claim the module makes: configuring the adapter for the coarse output
// means the egress gate has nothing left to catch. If a submodule bump ever
// changes the adapter's default class, this is where it surfaces.
let mut s = scan();
let all = s.events().expect("events").len();
let mut s = scan();
let egress = s.egress_events().expect("egress events").len();
assert_eq!(all, 72);
assert_eq!(
egress, all,
"no event is dropped at the gate in coarse mode"
);
}
#[test]
fn gate_every_event_is_p1_on_both_tensor_and_observation() {
let mut s = scan();
for event in s.events().expect("events") {
assert_eq!(event.tensor.privacy_class, ULTRASONIC_EGRESS_CLASS);
assert_eq!(event.observation.privacy_class, ULTRASONIC_EGRESS_CLASS);
// Both, because the guard is conjunctive over the pair — a P0 tensor
// under a P1 observation is exactly the composite leak the default
// guard exists to close.
assert!(network_egress_allowed(event.tensor.privacy_class, false));
assert!(network_egress_allowed(
event.observation.privacy_class,
false
));
}
assert_eq!(ULTRASONIC_EGRESS_CLASS, PrivacyClass::P1);
}
#[test]
fn gate_ultrasonic_can_never_reach_the_identity_tiers() {
// P5 is only reachable through `identity_evidence`, which
// `validate_evidence_at` restricts to BLE advertisement RSSI — so an
// ultrasonic event carrying it is a hard validation failure rather than a
// policy question. The ceiling is structural.
let mut s = scan();
for event in s.events().expect("events") {
assert!(event.tensor.privacy_class < PrivacyClass::P4);
assert!(event.observation.privacy_class < PrivacyClass::P4);
assert!(event.observation.identity_evidence.is_none());
assert!(event.observation.channel_sounding_provenance.is_none());
}
}
#[test]
fn gate_no_event_claims_a_person() {
// The tempting mistake, refused deliberately. `presence` is one of exactly
// six feature keys the fusion window reads, and populating it would light
// up the shipped `person_present` rule. One transducer pair cannot
// distinguish a person from a coat over the back of a chair.
let mut s = scan();
for event in s.events().expect("events") {
for forbidden in ["presence", "breathing_band", "posture_height", "transient"] {
assert!(
!event.observation.features.contains_key(forbidden),
"an ultrasonic event must not claim `{forbidden}`"
);
}
for label in &event.observation.labels {
assert!(
!label.contains("person") && !label.contains("presence"),
"unexpected personhood label: {label}"
);
}
}
}
/// The honest negative result, asserted rather than avoided.
///
/// Because nothing claims presence, a BatVu scan produces no fused inferences
/// under the shipped rules. Two independent reasons, and pinning both matters
/// because fixing only the first would look like progress and change nothing:
/// no rule lists `"ultrasonic"` among its inputs, and the engine's feature
/// vocabulary is entirely statements about a body, so `range_m` has nothing to
/// drive. RuField v0.1 has no predicate for static geometry.
#[test]
fn gate_no_inferences_and_that_is_the_correct_outcome() {
let mut s = scan();
let mut engine = RuFieldFusion::new();
for event in s.events().expect("events") {
engine.ingest(event).expect("ingest");
}
let inferences = engine
.infer(&InferenceQuery {
zone_id: Some("living_room".into()),
labels: vec![],
track_id: None,
as_of_ns: None,
})
.expect("infer");
assert!(
inferences.is_empty(),
"no shipped rule can fire on a range-only sensor: {inferences:?}"
);
}
// ── trust tier ───────────────────────────────────────────────────────────────
#[test]
fn gate_a_recording_cannot_relabel_itself_into_a_higher_trust_tier() {
// The fixture declares `simulated`. An operator pointing a capture-trusting
// deployment at it gets a hard refusal rather than a silently upgraded
// tier — and the reverse is refused too, so neither direction is a quiet
// reinterpretation.
let err = UltrasonicScan::load(SCAN, "living_room", ScanSource::DeviceCapture)
.expect_err("must refuse");
assert!(
err.to_string().contains("device_capture"),
"the refusal names the mismatch: {err}"
);
}
#[test]
fn gate_simulated_recordings_are_marked_synthetic() {
// Not cosmetic: `synthetic: true` is what keeps simulator output out of
// captured-replay and production trust, which reject it before any key
// lookup. Marking it otherwise to get it accepted is the §11 invariant
// violation ADR-262 forbids.
let mut s = scan();
for event in s.events().expect("events") {
assert!(event.provenance.synthetic);
}
}
// ── determinism ──────────────────────────────────────────────────────────────
#[test]
fn gate_same_recording_yields_a_byte_identical_event_stream() {
let mut a = scan();
let mut b = scan();
let left = serde_json::to_string(&a.events().expect("events")).expect("serializes");
let right = serde_json::to_string(&b.events().expect("events")).expect("serializes");
assert_eq!(left, right);
}
#[test]
fn gate_a_malformed_recording_is_refused_whole() {
// No partial ingest. A stream that half-replays and then dies is the worst
// outcome for a consumer, because it has already acted on the good prefix.
let mut bad = SCAN.lines().take(4).collect::<Vec<_>>().join("\n");
bad.push_str("\n{\"timestamp\":1756162800,\"source\":\"simulated\",\"device_id\":\"x\"}\n");
let err =
UltrasonicScan::load(&bad, "living_room", ScanSource::Simulated).expect_err("must refuse");
assert!(err.to_string().contains("rejected"));
}
@@ -26,6 +26,7 @@ tower-http = { version = "0.6", features = ["fs", "cors", "set-header"] }
tokio = { workspace = true, features = ["full", "process"] }
futures-util = "0.3"
ruvector-mincut = { workspace = true }
mdns-sd = "0.11"
# Serialization
serde = { workspace = true }
@@ -0,0 +1,125 @@
//! Local DNS-SD advertisement for RuView installation discovery.
//!
//! The TXT record deliberately contains no SSID, node identifiers, room data,
//! sensor values, credentials, or personal data. Mobile clients treat the
//! installation id as a routing hint only and still health-check the service.
use std::collections::HashMap;
use mdns_sd::{ServiceDaemon, ServiceInfo};
pub const SERVICE_TYPE: &str = "_ruview._tcp.local.";
pub const SCHEMA: &str = "ruview.installation.v1";
pub struct DiscoveryAdvertiser {
daemon: ServiceDaemon,
fullname: String,
}
impl Drop for DiscoveryAdvertiser {
fn drop(&mut self) {
let _ = self.daemon.unregister(&self.fullname);
let _ = self.daemon.shutdown();
}
}
/// Reduce an operator/host label to a deterministic RFC 6762-safe hostname.
pub fn discovery_hostname(raw: &str) -> String {
let mut label = String::with_capacity(48);
for character in raw.chars().flat_map(char::to_lowercase) {
if character.is_ascii_alphanumeric() {
label.push(character);
} else if (character == '-' || character == '_' || character == ' ')
&& !label.ends_with('-')
{
label.push('-');
}
if label.len() >= 40 {
break;
}
}
let label = label.trim_matches('-');
let safe = if label.is_empty() {
"installation"
} else {
label
};
format!("ruview-{safe}.local.")
}
pub fn build_service(
instance_name: &str,
installation_id: &str,
hostname: &str,
http_port: u16,
tls: bool,
) -> Result<ServiceInfo, mdns_sd::Error> {
let mut properties = HashMap::with_capacity(3);
properties.insert("schema".to_string(), SCHEMA.to_string());
properties.insert("tls".to_string(), if tls { "1" } else { "0" }.to_string());
properties.insert(
"installation".to_string(),
installation_id.chars().take(128).collect(),
);
ServiceInfo::new(
SERVICE_TYPE,
&instance_name.chars().take(96).collect::<String>(),
hostname,
(),
http_port,
Some(properties),
)
.map(ServiceInfo::enable_addr_auto)
}
/// Register a live local advertisement. Failure is recoverable: the sensing
/// server remains available through its explicitly configured origin.
pub fn start_advertiser(
instance_name: &str,
installation_id: &str,
hostname: &str,
http_port: u16,
) -> Result<DiscoveryAdvertiser, mdns_sd::Error> {
let daemon = ServiceDaemon::new()?;
let service = build_service(instance_name, installation_id, hostname, http_port, false)?;
let fullname = service.get_fullname().to_owned();
daemon.register(service)?;
Ok(DiscoveryAdvertiser { daemon, fullname })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn advertisement_matches_mobile_contract_without_sensor_metadata() {
let service = build_service(
"RuView Living Room",
"home-a",
"ruview-home-a.local.",
3000,
false,
)
.unwrap();
assert_eq!(service.get_type(), SERVICE_TYPE);
assert_eq!(service.get_port(), 3000);
assert!(service.is_addr_auto());
assert_eq!(service.get_property_val_str("schema"), Some(SCHEMA));
assert_eq!(service.get_property_val_str("tls"), Some("0"));
assert_eq!(service.get_property_val_str("installation"), Some("home-a"));
for forbidden in ["ssid", "node", "room", "csi", "pose", "token"] {
assert!(service.get_property(forbidden).is_none());
}
}
#[test]
fn hostname_is_bounded_and_safe() {
assert_eq!(
discovery_hostname("Cohen's Mac Mini"),
"ruview-cohens-mac-mini.local."
);
let value = discovery_hostname("🚫 ///");
assert_eq!(value, "ruview-installation.local.");
assert!(discovery_hostname(&"A".repeat(200)).len() <= 54);
}
}
@@ -41,7 +41,7 @@ use wifi_densepose_signal::ruvsense::fusion_quality::CalibrationId;
use wifi_densepose_signal::ruvsense::multistatic::MultistaticConfig;
use wifi_densepose_worldgraph::WorldId;
use super::multistatic_bridge::node_frames_from_states;
use super::multistatic_bridge::node_frames_from_states_with_guard;
use super::NodeState;
/// Minimum spacing between engine-error warn logs (errors are still counted
@@ -53,6 +53,8 @@ const ENGINE_ERROR_WARN_INTERVAL: Duration = Duration::from_secs(10);
/// live sensing loop publishes beliefs into.
pub struct EngineBridge {
engine: StreamingEngine,
/// Hard timestamp guard shared by cohort selection and engine validation.
guard_interval_us: u64,
room: WorldId,
/// Nodes already wired into the WorldGraph as sensors (by `node_id`).
registered_nodes: HashMap<u8, WorldId>,
@@ -94,6 +96,11 @@ impl EngineBridge {
room_name: &str,
multistatic_cfg: Option<MultistaticConfig>,
) -> Self {
let guard_interval_us = multistatic_cfg
.as_ref()
.map_or_else(|| MultistaticConfig::default().guard_interval_us, |cfg| {
cfg.guard_interval_us
});
let mut engine = StreamingEngine::new(mode, model_version, GeoRegistration::default());
if let Some(cfg) = multistatic_cfg {
engine.set_multistatic_config(cfg);
@@ -101,6 +108,7 @@ impl EngineBridge {
let room = engine.add_room(room_area_id, room_name);
Self {
engine,
guard_interval_us,
room,
registered_nodes: HashMap::new(),
calibration: CalibrationId(0x5256_0001), // "RV\0\x01" — placeholder epoch
@@ -165,7 +173,8 @@ impl EngineBridge {
node_states: &HashMap<u8, NodeState>,
now_ms: i64,
) -> Option<Result<TrustedOutput, EngineError>> {
let frames = node_frames_from_states(node_states);
let frames =
node_frames_from_states_with_guard(node_states, self.guard_interval_us);
if frames.is_empty() {
return None;
}
@@ -195,7 +204,15 @@ impl EngineBridge {
node_states: &HashMap<u8, NodeState>,
now_ms: i64,
) -> Option<TrustedOutput> {
match self.process_cycle_from_states(node_states, now_ms)? {
let result = self.process_cycle_from_states(node_states, now_ms)?;
self.record_cycle_result(result)
}
fn record_cycle_result(
&mut self,
result: Result<TrustedOutput, EngineError>,
) -> Option<TrustedOutput> {
match result {
Ok(trust) => {
self.last_witness = Some(trust.witness);
self.recalibration_recommended = trust.recalibration_recommended;
@@ -419,45 +436,29 @@ mod tests {
assert!(!bridge.suppress_raw_outputs());
}
/// Error wiring (review finding 1a): a live cycle that fails fusion yields
/// an `EngineError` — previously dropped by `if let Some(Ok(..))` at the
/// call sites. The counter must increment and the last good trust state
/// must survive a later failure.
///
/// Originally this forced the failure with a 56-vs-30 subcarrier mismatch
/// (`DimensionMismatch`). Since #1170 the live bridge canonicalizes every
/// node onto the 56-tone grid, so heterogeneous counts now fuse cleanly —
/// a frame-timestamp spread wider than the fuser's 60 ms guard interval is
/// the remaining deterministic way to provoke a fusion error here.
/// Error-result accounting is independent from live cohort selection, so
/// a future engine error remains auditable without deliberately forwarding
/// temporally incoherent frames through the production bridge.
#[test]
fn observe_cycle_counts_engine_errors() {
// Both nodes are 56-subcarrier (canonicalization-clean), but their
// frame timestamps are 500 ms apart — far beyond the 60 ms guard —
// so the fuser rejects the cycle with TimestampMismatch. Future
// offsets keep both instants safely after the bridge's lazy EPOCH.
fn mismatched_states() -> HashMap<u8, NodeState> {
let now = Instant::now();
let mut a = node_state_with_history(1.0, 56);
a.last_frame_time = Some(now + std::time::Duration::from_millis(600));
let mut b = node_state_with_history(1.05, 56);
b.last_frame_time = Some(now + std::time::Duration::from_millis(100));
let mut m = HashMap::new();
m.insert(0u8, a);
m.insert(1u8, b);
m
}
let mut bridge = EngineBridge::new(PrivacyMode::PrivateHome, 1, "r", "R", None);
let mismatched = mismatched_states();
let error = || {
EngineError::Fusion(
wifi_densepose_signal::ruvsense::multistatic::MultistaticError::TimestampMismatch {
spread_us: 500_000,
guard_us: 60_000,
},
)
};
assert!(bridge.observe_cycle(&mismatched, 1_000).is_none());
assert!(bridge.record_cycle_result(Err(error())).is_none());
assert_eq!(bridge.engine_error_count(), 1);
assert!(
bridge.last_trust_witness().is_none(),
"no witness from a failed cycle"
);
assert!(bridge.observe_cycle(&mismatched, 2_000).is_none());
assert!(bridge.record_cycle_result(Err(error())).is_none());
assert_eq!(bridge.engine_error_count(), 2);
// A later good cycle records trust state; the audit count is kept.
@@ -467,11 +468,39 @@ mod tests {
assert_eq!(bridge.engine_error_count(), 2);
// And a subsequent failure keeps the last good witness readable.
assert!(bridge.observe_cycle(&mismatched, 4_000).is_none());
assert!(bridge.record_cycle_result(Err(error())).is_none());
assert_eq!(bridge.engine_error_count(), 3);
assert!(bridge.last_trust_witness().is_some());
}
#[test]
fn governed_cycles_prune_slow_mixed_width_nodes_without_errors() {
let mut bridge = EngineBridge::new(PrivacyMode::PrivateHome, 1, "r", "R", None);
for tick in 0..50_i64 {
let now = Instant::now();
let mut states = HashMap::new();
for (node_id, age_ms, n_sub) in [
(1, 0, 64),
(3, 10, 256),
(4, 50, 64),
(7, 1_000, 256),
] {
let mut node = node_state_with_history(1.0 + node_id as f64 * 0.01, n_sub);
node.last_frame_time = Some(now - Duration::from_millis(age_ms));
states.insert(node_id, node);
}
assert!(
bridge.observe_cycle(&states, 1_000 + tick * 50).is_some(),
"governed cycle {tick}"
);
}
assert_eq!(bridge.engine_error_count(), 0);
assert!(bridge.last_trust_witness().is_some());
}
/// ADR-141 mapping (review finding 1c): a cycle emitted at class
/// Restricted flips `suppress_raw_outputs`, which `main.rs` uses to strip
/// per-node raw amplitude vectors from the live publish — the same field
@@ -13,6 +13,7 @@ pub mod browser_session;
pub mod ws_ticket;
pub mod cli;
pub mod dataset;
pub mod discovery;
pub mod edge_registry;
pub mod error_response;
pub mod host_validation;
@@ -133,6 +133,23 @@ struct Args {
#[arg(long, default_value = "127.0.0.1", env = "SENSING_BIND_ADDR")]
bind_addr: String,
/// Disable local `_ruview._tcp` discovery. Discovery is automatically
/// skipped for loopback-only binds and never carries sensor data.
#[arg(long, env = "RUVIEW_NO_MDNS")]
no_mdns: bool,
/// Stable, non-secret installation routing hint published over mDNS.
#[arg(long, env = "RUVIEW_INSTALLATION_ID")]
installation_id: Option<String>,
/// Human-readable local service name shown by commissioning clients.
#[arg(
long,
default_value = "RuView Installation",
env = "RUVIEW_INSTALLATION_NAME"
)]
installation_name: String,
/// Additional hostname (with or without `:PORT`) to permit in the `Host`
/// header — defends loopback-bound deployments against DNS rebinding.
/// Loopback names (`localhost`, `127.0.0.1`, `[::1]`) are always permitted
@@ -8762,9 +8779,15 @@ async fn main() {
);
wifi_densepose_sensing_server::host_validation::HostAllowlist::disabled()
} else {
let discovery_label = args.installation_id.as_deref().unwrap_or("installation");
let discovery_host =
wifi_densepose_sensing_server::discovery::discovery_hostname(discovery_label);
let allowlist =
wifi_densepose_sensing_server::host_validation::HostAllowlist::from_cli_and_env(
args.allowed_hosts.iter().cloned(),
args.allowed_hosts
.iter()
.cloned()
.chain(std::iter::once(discovery_host)),
);
info!(
"Host-header validation ON ({} entries; loopback names always included)",
@@ -8978,6 +9001,32 @@ async fn main() {
args.http_port
);
let discovery_label = args.installation_id.as_deref().unwrap_or("installation");
let discovery_hostname =
wifi_densepose_sensing_server::discovery::discovery_hostname(discovery_label);
let _discovery_advertiser = if args.no_mdns || bind_ip.is_loopback() {
if bind_ip.is_loopback() && !args.no_mdns {
info!("RuView discovery skipped for loopback-only HTTP bind");
}
None
} else {
match wifi_densepose_sensing_server::discovery::start_advertiser(
&args.installation_name,
discovery_label,
&discovery_hostname,
args.http_port,
) {
Ok(advertiser) => {
info!(hostname = %discovery_hostname, port = args.http_port, "RuView local discovery advertised");
Some(advertiser)
}
Err(error) => {
warn!(%error, "RuView local discovery unavailable; manual origin remains usable");
None
}
}
};
// Run the HTTP server with graceful shutdown support
let shutdown_state = state.clone();
let server = axum::serve(http_listener, http_app).with_graceful_shutdown(async {
@@ -12,7 +12,9 @@ use std::time::{Duration, Instant};
use wifi_densepose_signal::hardware_norm::{CanonicalCsiFrame, HardwareNormalizer, HardwareType};
use wifi_densepose_signal::ruvsense::multiband::MultiBandCsiFrame;
use wifi_densepose_signal::ruvsense::multistatic::{FusedSensingFrame, MultistaticFuser};
use wifi_densepose_signal::ruvsense::multistatic::{
FusedSensingFrame, MultistaticConfig, MultistaticFuser,
};
use super::NodeState;
@@ -44,6 +46,24 @@ static NORMALIZER: LazyLock<HardwareNormalizer> = LazyLock::new(HardwareNormaliz
/// `last_frame_time`.
pub fn node_frame_from_state(node_id: u8, ns: &NodeState) -> Option<MultiBandCsiFrame> {
let last_time = ns.last_frame_time.as_ref()?;
let timestamp_us = ns
.mesh_aligned_us_for_latest_csi_frame()
.unwrap_or_else(|| host_arrival_timestamp_us(last_time));
node_frame_from_state_at(node_id, ns, timestamp_us)
}
fn host_arrival_timestamp_us(last_time: &Instant) -> u64 {
last_time
.checked_duration_since(*EPOCH)
.unwrap_or_default()
.as_micros() as u64
}
fn node_frame_from_state_at(
node_id: u8,
ns: &NodeState,
timestamp_us: u64,
) -> Option<MultiBandCsiFrame> {
let latest = ns.frame_history.back()?;
if latest.is_empty() {
return None;
@@ -60,19 +80,6 @@ pub fn node_frame_from_state(node_id: u8, ns: &NodeState) -> Option<MultiBandCsi
let n_sub = amplitude.len();
let phase = vec![0.0_f32; n_sub];
// Prefer the capture timestamp recovered from the node's mesh sync. This
// keeps UDP scheduling jitter out of the fuser's cross-node guard. Older
// firmware, stale sync state, and frames without the sync-valid bit retain
// the process-local host-arrival fallback.
let timestamp_us = ns
.mesh_aligned_us_for_latest_csi_frame()
.unwrap_or_else(|| {
last_time
.checked_duration_since(*EPOCH)
.unwrap_or_default()
.as_micros() as u64
});
let canonical = CanonicalCsiFrame {
amplitude,
phase,
@@ -88,25 +95,91 @@ pub fn node_frame_from_state(node_id: u8, ns: &NodeState) -> Option<MultiBandCsi
})
}
/// Collect `MultiBandCsiFrame`s from all active nodes.
/// Collect the default-guard coherent `MultiBandCsiFrame` cohort.
///
/// A node is considered active if its `last_frame_time` is within
/// [`STALE_THRESHOLD`] of `now`.
pub fn node_frames_from_states(node_states: &HashMap<u8, NodeState>) -> Vec<MultiBandCsiFrame> {
let now = Instant::now();
let mut frames = Vec::with_capacity(node_states.len());
node_frames_from_states_with_guard(
node_states,
MultistaticConfig::default().guard_interval_us,
)
}
for (&node_id, ns) in node_states {
// Skip stale nodes
if let Some(ref t) = ns.last_frame_time {
if now.duration_since(*t) > STALE_THRESHOLD {
continue;
}
} else {
/// Collect the freshest temporally coherent cohort of active node frames.
///
/// Nodes can publish at very different rates (for example, a mixed S3/C6
/// fleet). `STALE_THRESHOLD` determines whether a node is alive; it does not
/// mean its latest frame belongs to the current sensing cycle. After choosing
/// one timestamp domain for the whole cycle, retain only frames within the
/// fuser's hard guard of the freshest frame. This prevents a slow-but-live node
/// from turning every governed cycle into `TimestampMismatch`, while always
/// preserving at least the freshest node for the supported single-node path.
pub fn node_frames_from_states_with_guard(
node_states: &HashMap<u8, NodeState>,
guard_interval_us: u64,
) -> Vec<MultiBandCsiFrame> {
let now = Instant::now();
let mut active: Vec<(u8, &NodeState)> = node_states
.iter()
.filter_map(|(&node_id, ns)| {
let last_time = ns.last_frame_time.as_ref()?;
(now.duration_since(*last_time) <= STALE_THRESHOLD).then_some((node_id, ns))
})
.collect();
active.sort_unstable_by_key(|(node_id, _)| *node_id);
if active.is_empty() {
return Vec::new();
}
let guard_interval_us = guard_interval_us.max(1);
// Timestamp domains must be selected for the cycle as a whole. A CSI
// frame can legitimately arrive between periodic sync-marked frames. If
// that one node fell back to process-local host time while a peer retained
// mesh epoch time, the resulting hundreds-of-seconds spread made every
// governed fusion cycle fail. Use mesh time only when every active node
// can provide it; otherwise use host-arrival time consistently for all.
let mesh_times: Option<Vec<u64>> = active
.iter()
.map(|(_, ns)| ns.mesh_aligned_us_for_latest_csi_frame())
.collect::<Option<Vec<_>>>()
.filter(|times| {
let Some(min) = times.iter().min() else {
return false;
};
let Some(max) = times.iter().max() else {
return false;
};
max.saturating_sub(*min) <= guard_interval_us
});
let mut timed = Vec::with_capacity(active.len());
for (index, (node_id, ns)) in active.into_iter().enumerate() {
let timestamp_us = mesh_times.as_ref().map_or_else(
|| {
host_arrival_timestamp_us(
ns.last_frame_time.as_ref().expect("active node has time"),
)
},
|times| times[index],
);
timed.push((node_id, ns, timestamp_us));
}
let freshest_timestamp_us = timed
.iter()
.map(|(_, _, timestamp_us)| *timestamp_us)
.max()
.expect("non-empty active cohort");
let mut frames = Vec::with_capacity(timed.len());
for (node_id, ns, timestamp_us) in timed {
if freshest_timestamp_us.saturating_sub(timestamp_us) > guard_interval_us {
continue;
}
if let Some(frame) = node_frame_from_state(node_id, ns) {
if let Some(frame) = node_frame_from_state_at(node_id, ns, timestamp_us) {
frames.push(frame);
}
}
@@ -125,7 +198,8 @@ pub fn fuse_or_fallback(
node_states: &HashMap<u8, NodeState>,
dedup_factor: f64,
) -> (Option<FusedSensingFrame>, Option<usize>) {
let frames = node_frames_from_states(node_states);
let frames =
node_frames_from_states_with_guard(node_states, fuser.guard_interval_us());
if frames.is_empty() {
return (None, Some(0));
}
@@ -313,26 +387,127 @@ mod tests {
}
#[test]
fn unsynchronized_frames_keep_host_arrival_guard() {
fn partial_sync_uses_one_host_timestamp_domain_for_the_cycle() {
let base = Instant::now() - Duration::from_millis(500);
let mut states = HashMap::new();
for (node_id, arrival) in [
(1, base),
(2, base + Duration::from_millis(200)),
let mut synced_history = VecDeque::new();
synced_history.push_back(vec![1.0; 64]);
let mut synced = make_node_state(synced_history, None, 0);
mark_mesh_timed_frame(&mut synced, 1, 100, 101, 500_000_000, base);
states.insert(1, synced);
let mut unsynced_history = VecDeque::new();
unsynced_history.push_back(vec![1.1; 64]);
states.insert(
2,
make_node_state(unsynced_history, Some(base + Duration::from_millis(5)), 0),
);
let frames = node_frames_from_states(&states);
let spread = frames.iter().map(|f| f.timestamp_us).max().unwrap()
- frames.iter().map(|f| f.timestamp_us).min().unwrap();
assert_eq!(spread, 5_000, "partial sync must fall back as one cycle");
assert!(
MultistaticFuser::new().fuse(&frames).is_ok(),
"mixed sync validity must not mix mesh and host timestamp domains"
);
}
#[test]
fn incoherent_mesh_timestamps_fall_back_to_host_arrival_for_the_cycle() {
let base = Instant::now() - Duration::from_millis(500);
let mut states = HashMap::new();
for (node_id, mesh_epoch_us, arrival) in [
(1, 1_000_000, base),
(2, 500_000_000, base + Duration::from_millis(5)),
] {
let mut history = VecDeque::new();
history.push_back(vec![1.0; 64]);
let mut state = make_node_state(history, None, 0);
mark_mesh_timed_frame(&mut state, node_id, 100, 101, mesh_epoch_us, arrival);
states.insert(node_id, state);
}
let frames = node_frames_from_states(&states);
let spread = frames.iter().map(|f| f.timestamp_us).max().unwrap()
- frames.iter().map(|f| f.timestamp_us).min().unwrap();
assert_eq!(spread, 5_000, "incoherent mesh time must not reach fusion");
assert!(MultistaticFuser::new().fuse(&frames).is_ok());
}
#[test]
fn unsynchronized_frames_prune_to_freshest_host_cohort() {
let base = Instant::now() - Duration::from_millis(500);
let mut states = HashMap::new();
for (node_id, arrival) in [(1, base), (2, base + Duration::from_millis(200))] {
let mut history = VecDeque::new();
history.push_back(vec![1.0; 64]);
states.insert(node_id, make_node_state(history, Some(arrival), 0));
}
let frames = node_frames_from_states(&states);
assert_eq!(frames.len(), 1, "only the freshest host frame is coherent");
assert_eq!(frames[0].node_id, 2);
assert!(
MultistaticFuser::new().fuse(&frames).is_err(),
"without valid mesh time, 200 ms arrival skew must still trip the 60 ms guard"
MultistaticFuser::new().fuse(&frames).is_ok(),
"an asynchronous slow node must not fail the live cycle"
);
}
#[test]
fn slow_live_node_is_excluded_from_fresh_cohort() {
let now = Instant::now();
let mut states = HashMap::new();
for (node_id, age_ms, n_sub) in [
(1, 0, 64),
(3, 10, 256),
(4, 50, 64),
(7, 1_000, 256),
] {
let mut history = VecDeque::new();
history.push_back(vec![1.0 + node_id as f64 * 0.01; n_sub]);
states.insert(
node_id,
make_node_state(
history,
Some(now - Duration::from_millis(age_ms)),
1,
),
);
}
let frames = node_frames_from_states_with_guard(&states, 60_000);
let ids: Vec<u8> = frames.iter().map(|frame| frame.node_id).collect();
assert_eq!(ids, vec![1, 3, 4]);
assert!(MultistaticFuser::new().fuse(&frames).is_ok());
}
#[test]
fn configured_guard_is_shared_with_cohort_selection() {
let base = Instant::now() - Duration::from_millis(500);
let mut states = HashMap::new();
for (node_id, arrival) in [
(1, base),
(2, base + Duration::from_millis(150)),
] {
let mut history = VecDeque::new();
history.push_back(vec![1.0; 64]);
states.insert(node_id, make_node_state(history, Some(arrival), 0));
}
let cfg = MultistaticConfig {
guard_interval_us: 200_000,
..MultistaticConfig::default()
};
let fuser = MultistaticFuser::with_config(cfg);
let (fused, fallback) = fuse_or_fallback(&fuser, &states, 3.0);
assert_eq!(fused.as_ref().map(|frame| frame.active_nodes), Some(2));
assert!(fallback.is_none());
}
#[test]
fn heterogeneous_node_counts_canonicalize_and_fuse() {
// Issue #1170 regression: a mixed mesh with HT20 (64-bin) and HT40
@@ -272,6 +272,17 @@ impl MultistaticFuser {
self.node_positions = positions;
}
/// Return the configured hard timestamp guard in microseconds.
///
/// Callers that assemble frames before invoking [`Self::fuse`] use this
/// to select one temporally coherent sensing cohort. Keeping selection and
/// validation on the same guard prevents stale low-rate nodes from making
/// every otherwise-live fusion cycle fail.
#[must_use]
pub fn guard_interval_us(&self) -> u64 {
self.config.guard_interval_us
}
/// Return the current node positions.
pub fn node_positions(&self) -> &[[f32; 3]] {
&self.node_positions
+1 -1