mirror of
https://github.com/ruvnet/RuView
synced 2026-08-11 20:41:44 +00:00
f49c722764
The Rust port lived two directories deep (rust-port/wifi-densepose-rs/) without any sibling under rust-port/ that warranted the extra level. Move the whole workspace up to v2/ to match v1/ (Python) at the same depth and shorten every cd / build command across the repo. git mv preserves history for all tracked files. 60 files updated for path references (CI workflows, ADRs, docs, scripts, READMEs, internal .claude-flow state). Two manual fixes for relative-cd paths in CLAUDE.md and ADR-043 that became wrong after the depth change (cd ../.. → cd ..). Validated: - cargo check --workspace --no-default-features → clean (after target/ nuke; the gitignored target/ was carried by the OS rename and had hard-coded old paths in build scripts) - cargo test --workspace --no-default-features → 1,539 passed, 0 failed, 8 ignored (same totals as pre-rename) - ESP32-S3 on COM7 → still streaming live CSI (cb #40300, RSSI -64 dBm) After-merge follow-up: contributors should `rm -rf v2/target` once and let cargo regenerate from the new path.
61 lines
1.8 KiB
Rust
61 lines
1.8 KiB
Rust
//! Sensor calibration utilities for gain/offset correction and cross-calibration.
|
|
|
|
/// Calibration data for a sensor array.
|
|
pub struct CalibrationData {
|
|
/// Per-channel gain factors.
|
|
pub gains: Vec<f64>,
|
|
/// Per-channel DC offsets to subtract.
|
|
pub offsets: Vec<f64>,
|
|
/// Per-channel noise floor estimates (fT RMS).
|
|
pub noise_floors: Vec<f64>,
|
|
}
|
|
|
|
/// Apply gain and offset correction to a single sample on a given channel.
|
|
///
|
|
/// `corrected = (raw - offset) * gain`
|
|
pub fn calibrate_channel(raw: f64, channel: usize, cal: &CalibrationData) -> f64 {
|
|
let offset = cal.offsets.get(channel).copied().unwrap_or(0.0);
|
|
let gain = cal.gains.get(channel).copied().unwrap_or(1.0);
|
|
(raw - offset) * gain
|
|
}
|
|
|
|
/// Estimate the noise floor (RMS) of a quiet signal segment.
|
|
pub fn estimate_noise_floor(signal: &[f64]) -> f64 {
|
|
if signal.is_empty() {
|
|
return 0.0;
|
|
}
|
|
let mean_sq = signal.iter().map(|x| x * x).sum::<f64>() / signal.len() as f64;
|
|
mean_sq.sqrt()
|
|
}
|
|
|
|
/// Cross-calibrate a target channel against a reference channel.
|
|
///
|
|
/// Returns `(gain, offset)` such that `target * gain + offset ~ reference`.
|
|
/// Uses simple linear regression.
|
|
pub fn cross_calibrate(reference: &[f64], target: &[f64]) -> (f64, f64) {
|
|
let n = reference.len().min(target.len());
|
|
if n == 0 {
|
|
return (1.0, 0.0);
|
|
}
|
|
|
|
let mean_r = reference[..n].iter().sum::<f64>() / n as f64;
|
|
let mean_t = target[..n].iter().sum::<f64>() / n as f64;
|
|
|
|
let mut num = 0.0;
|
|
let mut den = 0.0;
|
|
for i in 0..n {
|
|
let dr = reference[i] - mean_r;
|
|
let dt = target[i] - mean_t;
|
|
num += dr * dt;
|
|
den += dt * dt;
|
|
}
|
|
|
|
if den.abs() < 1e-15 {
|
|
return (1.0, mean_r - mean_t);
|
|
}
|
|
|
|
let gain = num / den;
|
|
let offset = mean_r - gain * mean_t;
|
|
(gain, offset)
|
|
}
|