RuView Coherence Gate Decision-Making Process: How Accept, Reject, and Recalibrate Decisions Work
The RuView coherence gate evaluates Channel State Information (CSI) frame consistency against configurable thresholds to emit Accept, PredictOnly, Reject, or Recalibrate decisions that control Kalman filter updates and trigger SONA/AETHER recalibration when data quality degrades.
The Coherence Gate in the ruvnet/RuView repository serves as a critical safety layer between raw WiFi sensing data and the pose estimation pipeline. Implemented in rust-port/wifi-densepose-rs/crates/wifi-densepose-signal/src/ruvsense/coherence_gate.rs, this component determines whether a newly computed CSI-based pose measurement should be applied to the Kalman filter, ignored, or used to trigger a full system recalibration based on runtime coherence scores and stale-frame counters.
Policy Configuration and Thresholds
The gate's behavior is governed by the GatePolicyConfig struct, which defines static or adaptive thresholds that tune the sensitivity of the decision-making process.
GatePolicyConfig Structure
Located at lines 62-75 in coherence_gate.rs, the configuration struct exposes the following parameters:
pub struct GatePolicyConfig {
pub accept_threshold: f32, // ≥ 0.85 by default
pub reject_threshold: f32, // ≤ 0.5 by default
pub max_stale_frames: u64, // 200 frames ≈ 10 s at 20 Hz
pub predict_only_noise: f32, // 3.0 (noise inflation factor)
pub adaptive: bool, // not used in the default policy
}
A GatePolicy object is instantiated from this configuration via GatePolicy::from_config (lines 19-29). The policy holds mutable runtime state including consecutive_low (tracking how many frames in a row have been PredictOnly or Reject) and last_decision (the most recent GateDecision for debugging).
Decision Types and Enumeration
The gate emits one of four distinct decisions defined in the GateDecision enum.
GateDecision Enum Variants
The enumeration at lines 42-60 in coherence_gate.rs defines the possible outcomes:
pub enum GateDecision {
Accept { noise_multiplier: f32 }, // full Kalman update, multiplier = 1.0
PredictOnly, // only the predict step, inflated noise
Reject, // drop measurement entirely
Recalibrate { stale_frames: u64 } // trigger SONA/AETHER recalibration
}
Helper methods including allows_update, is_rejected, and noise_multiplier allow downstream code to query the decision without exhaustive pattern matching on every call (lines 42-60).
Core Evaluation Algorithm
The decision-making logic centers on the evaluate method, which processes runtime inputs against configured thresholds.
The evaluate Method Logic
The evaluate method (lines 31-50) implements a priority-ordered decision tree that processes three inputs: the coherence_score (a float ∈ [0, 1] computed by the coherence.rs module), the stale_count (consecutive low-coherence frames), and the configured thresholds.
Decision Tree Flow
The algorithm evaluates conditions in the following strict order:
-
Recalibration Override: If
stale_count >= max_stale_frames, the gate immediately returnsGateDecision::Recalibrateregardless of the current coherence score.if stale_count >= self.max_stale_frames { GateDecision::Recalibrate { stale_frames: stale_count } } -
Accept Zone: When
coherence_score >= accept_threshold, the gate returnsGateDecision::Accept, resetsconsecutive_lowto zero, and applies a noise multiplier of1.0.else if coherence_score >= self.accept_threshold { self.consecutive_low = 0; GateDecision::Accept { noise_multiplier: 1.0 } } -
Predict-Only Zone: If the score falls between the reject and accept thresholds, the gate issues
GateDecision::PredictOnlyand increments the low-coherence counter.else if coherence_score >= self.reject_threshold { self.consecutive_low += 1; GateDecision::PredictOnly } -
Reject Zone: For scores below the reject threshold, the gate returns
GateDecision::Rejectand increments the low-coherence counter.else { self.consecutive_low += 1; GateDecision::Reject }
After the decision is selected, it is stored in self.last_decision (line 50) for later introspection.
Adaptive Noise Handling
The gate supports optional adaptive noise scaling for intermediate coherence scores.
Dynamic Noise Multipliers
Although the default policy uses a fixed predict_only_noise value, the module provides adaptive_noise_multiplier (lines 87-109) to compute a smooth noise inflation factor based on how far the coherence score lies between the accept and reject thresholds. Higher-level modules reference this function when GatePolicyConfig.adaptive is set to true, allowing the Kalman filter to receive proportionally scaled measurement noise rather than binary accept/reject behavior.
State Management and Recalibration
The gate maintains internal counters to track data quality degradation over time.
Stale Frame Tracking
The consecutive_low counter increments on every PredictOnly or Reject decision. When this counter exceeds max_stale_frames (default 200 frames, approximately 10 seconds at 20 Hz), the gate triggers the recalibration state regardless of the current coherence score.
Reset and Recovery
The reset() method (lines 74-78) clears consecutive_low and last_decision after a successful SONA/AETHER recalibration, allowing the system to resume normal operation with fresh baseline measurements.
Integration with the Kalman Filter
The coherence gate acts as a pre-filter for the pose estimation pipeline.
From CSI Frame to Filter Update
The integration flow follows this sequence:
- Coherence computation: The
coherence.rsmodule processes raw CSI frames and returns a coherence score float ∈ [0, 1]. - Stale-frame bookkeeping:
CoherenceStateincrements the stale counter each time the gate returns a low-coherence decision. - Gate evaluation:
GatePolicy::evaluate(coherence, stale_counter)returns aGateDecision. - Kalman filter action:
Accept→filter.update(measurement, noise_multiplier = 1.0)PredictOnly→filter.predict()or update with inflated noise viapredict_only_noiseReject→ No filter call; measurement droppedRecalibrate→ System freezes output, launches the SONA/AETHER recalibration pipeline, then callsGatePolicy::reset()
Code Examples
Creating a Gate with Custom Thresholds
use wifi_densepose_signal::ruvsense::{
GatePolicy, GatePolicyConfig,
};
// Custom policy: stricter acceptance, longer stale timeout.
let cfg = GatePolicyConfig {
accept_threshold: 0.90,
reject_threshold: 0.40,
max_stale_frames: 300, // 15 s at 20 Hz
predict_only_noise: 4.0,
adaptive: false,
};
let mut gate = GatePolicy::from_config(&cfg);
Running a Decision Cycle
// Suppose we have a fresh coherence score from the coherence module.
let coherence_score = 0.72_f32;
// The stale-frame counter is maintained elsewhere (e.g., in CoherenceState).
let stale_frames = 5_u64;
let decision = gate.evaluate(coherence_score, stale_frames);
match decision {
GateDecision::Accept { noise_multiplier } => {
println!("Accept – update with noise ×{noise_multiplier}");
// kalman.update(meas, noise_multiplier);
}
GateDecision::PredictOnly => {
println!("PredictOnly – run predict step, inflate noise");
// kalman.predict(); // or update with gate.predict_only_noise
}
GateDecision::Reject => {
println!("Reject – discard measurement");
// ignore this frame
}
GateDecision::Recalibrate { stale_frames } => {
println!("Recalibrate after {stale_frames} low-coherence frames");
// launch SONA/AETHER pipeline, then gate.reset();
}
}
Adaptive Noise Example
// When adaptive mode is enabled, compute the noise multiplier dynamically:
let noise = adaptive_noise_multiplier(
coherence_score,
cfg.accept_threshold,
cfg.reject_threshold,
cfg.predict_only_noise,
);
println!("Adaptive noise multiplier: {noise}");
Key Files and Components
| File | Role |
|---|---|
[coherence_gate.rs](https://github.com/ruvnet/RuView/blob/main/rust-port/wifi-densepose-rs/crates/wifi-densepose-signal/src/ruvsense/coherence_gate.rs) |
Core gate policy, decision enum, evaluation algorithm. |
[coherence.rs](https://github.com/ruvnet/RuView/blob/main/rust-port/wifi-densepose-rs/crates/wifi-densepose-signal/src/ruvsense/coherence.rs) |
Calculates the coherence score from CSI frames. |
[pose_tracker.rs](https://github.com/ruvnet/RuView/blob/main/rust-port/wifi-densepose-rs/crates/wifi-densepose-signal/src/ruvsense/pose_tracker.rs) |
Consumes GateDecision to drive Kalman filter updates. |
GatePolicyConfig |
Configuration struct that tunes the gate thresholds. |
adaptive_noise_multiplier |
Helper for smooth noise inflation when adaptive is true. |
Summary
- The Coherence Gate in
coherence_gate.rsacts as a safety filter between CSI measurements and the Kalman filter, preventing noisy data from corrupting pose estimates. - Four distinct decisions—
Accept,PredictOnly,Reject, andRecalibrate—are determined by comparing coherence scores against configurableaccept_thresholdandreject_thresholdvalues. - Recalibration triggers automatically when
max_stale_frames(default 200 frames) consecutive low-coherence measurements occur, initiating the SONA/AETHER pipeline to restore system accuracy. - Adaptive noise scaling via
adaptive_noise_multiplierallows smooth degradation of measurement confidence rather than binary filtering whenGatePolicyConfig.adaptiveis enabled.
Frequently Asked Questions
What inputs does the RuView coherence gate use to make decisions?
The coherence gate evaluates three primary inputs: the coherence score (a float between 0 and 1 computed by the coherence.rs module), the stale-frame counter (tracking consecutive low-coherence frames maintained in CoherenceState), and the gate policy configuration (GatePolicyConfig struct) containing threshold values and timeout limits.
How does the coherence gate decide when to trigger a full system recalibration?
The gate triggers GateDecision::Recalibrate when the internal stale_count exceeds max_stale_frames (default 200 frames, approximately 10 seconds at 20 Hz), regardless of the current coherence score. This override takes precedence over all other threshold checks in the evaluate method, ensuring the system initiates the SONA/AETHER recalibration pipeline before pose estimates become unreliable.
What is the difference between PredictOnly and Reject decisions in the coherence gate?
PredictOnly indicates the coherence score falls between the reject_threshold and accept_threshold, meaning the measurement is questionable but not useless; the Kalman filter runs only the prediction step (or updates with inflated noise using predict_only_noise), preserving temporal continuity while avoiding measurement corruption. Reject occurs when the coherence score falls below reject_threshold, indicating the frame is too unreliable; the measurement is discarded entirely with no Kalman filter update, though both decisions increment the consecutive_low counter toward potential recalibration.
Can the coherence gate adapt its noise levels based on coherence quality?
Yes, when GatePolicyConfig.adaptive is set to true, the gate utilizes the adaptive_noise_multiplier helper function (lines 87-109 in coherence_gate.rs) to compute a smooth noise inflation factor based on how far the coherence score lies between the accept and reject thresholds. This allows the Kalman filter to receive proportionally scaled measurement noise rather than binary accept/reject behavior, enabling graceful degradation of pose estimate confidence during marginal signal conditions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →