How to Implement Temporal Logic Verification (LTL) on CSI Event Streams in RuView
RuView processes Channel State Information (CSI) frames through a WebAssembly edge module that evaluates Linear Temporal Logic (LTL) safety rules at 20 Hz, emitting violation events when sensor data violates globally- or eventually-operators defined in tmp_temporal_logic_guard.rs.
RuView’s Wi-Fi-DensePose stack transforms raw CSI into structured event streams suitable for real-time safety monitoring. The repository implements temporal logic verification on CSI event streams through a deterministic state-machine interpreter that evaluates eight LTL invariants on every processed frame snapshot.
LTL Guard Architecture in the RuView Pipeline
The temporal logic guard operates as a stateful middleware between signal processing and visualization layers. According to the RuView source code, the data flows through the wifi-densepose-signal crate before reaching the verification stage.
CSI capture → wifi-densepose-signal → wifi-densepose-wasm-edge
│
└─► TemporalLogicGuard (per‑frame)
The wifi-densepose-signal crate extracts subcarrier amplitudes and builds a temporal CSI matrix. It forwards a condensed FrameInput snapshot to the WASM edge layer, where TemporalLogicGuard::on_frame(&FrameInput) executes once per frame at approximately 20 Hz.
Understanding G-Rules and F-Rules in RuView
The guard encodes two distinct classes of LTL formulas with different violation semantics:
- G-rules (globally): These specify conditions that must never hold on any single frame. Violations trigger immediately upon detection through direct boolean checks (e.g.,
presence == 0 && fall_alert). - F-rules (eventually): These define deadlines where a trigger condition must be followed by a required state within a specific timeframe. The implementation uses state machines transitioning from
Pending→ deadline →ViolatedorSatisfied.
The source header in tmp_temporal_logic_guard.rs documents the eight safety rules:
//! Encodes 8 safety rules as state machines monitoring CSI‑derived events.
//! G‑rules (globally) are violated on any single frame; F‑rules (eventually)
//! have deadlines. Emits violations with counterexample frame indices.
Key timing constants defined in the implementation include:
FAST_BREATH_DEADLINE = 100(5 seconds at 20 Hz)SEIZURE_EXCLUSION = 1200(60 seconds)MOTION_STOP_DEADLINE = 6000(300 seconds)
FrameInput Structure and CSI Event Schema
The FrameInput struct aggregates the minimal sensor features required for LTL evaluation. This structure bridges the CSI processing layer and the temporal logic engine:
pub struct FrameInput {
pub presence: i32,
pub n_persons: i32,
pub motion_energy: f32,
pub coherence: f32,
pub breathing_bpm: f32,
pub heartrate_bpm: f32,
pub fall_alert: bool,
pub intrusion_alert: bool,
pub person_id_active: bool,
pub vital_signs_active: bool,
pub seizure_detected: bool,
pub normal_gait: bool,
}
Higher-level CSI processing results populate these fields from motion detection and vital-sign extraction algorithms before passing the snapshot to the guard.
Event Emission and Real-Time Monitoring
TemporalLogicGuard::on_frame returns a slice of (event_id, payload) tuples. The guard caps emitted vectors at 12 entries per frame, ensuring bounded memory footprint for WASM execution.
Critical event identifiers include:
| ID | Constant | Meaning |
|---|---|---|
| 795 | EVENT_LTL_VIOLATION |
Rule violated; payload contains rule index (0-7) |
| 796 | EVENT_LTL_SATISFACTION |
Periodic heartbeat; payload = count of satisfied rules |
| 797 | EVENT_COUNTEREXAMPLE |
Frame index causing violation (debugging) |
After a violation, the affected rule remains in Violated state until the offending condition clears (e.g., fall_alert becomes false). Every report_interval (default 200 frames ≈ 10 seconds), the guard emits satisfaction events, allowing downstream health monitoring without per-frame polling.
Implementing LTL Verification in Rust
Instantiation and Frame Processing
Instantiate the guard once and reuse it across frames, as demonstrated in tests/vendor_modules_test.rs:
use wifi_densepose_wasm_edge::tmp_temporal_logic_guard::{
TemporalLogicGuard, FrameInput, RuleState,
};
fn main() {
// Create the guard once.
let mut guard = TemporalLogicGuard::new();
// Build a normal frame.
let mut frame = FrameInput::default();
frame.presence = 1;
frame.n_persons = 1;
frame.motion_energy = 0.05;
frame.coherence = 0.9;
frame.breathing_bpm = 12.0;
frame.heartrate_bpm = 70.0;
// Feed the frame.
let events = guard.on_frame(&frame);
// Inspect emitted events.
for (id, payload) in events {
match *id {
wifi_densepose_wasm_edge::tmp_temporal_logic_guard::EVENT_LTL_VIOLATION => {
println!("LTL violation of rule {}", payload);
}
wifi_densepose_wasm_edge::tmp_temporal_logic_guard::EVENT_LTL_SATISFACTION => {
println!("All {} rules satisfied", payload);
}
_ => {}
}
}
// Trigger G-rule 0: fall alert with no presence.
frame.presence = 0;
frame.fall_alert = true;
guard.on_frame(&frame);
assert_eq!(guard.rule_state(0), RuleState::Violated);
}
Handling Violations and Satisfactions
The on_frame method evaluates all eight rules against the current FrameInput. For G-rules, any boolean condition evaluating to true immediately generates an EVENT_LTL_VIOLATION with the corresponding rule index. For F-rules, the guard maintains internal counters tracking deadlines since trigger conditions activated.
Web Assembly Integration for Browser Dashboards
The WASM edge module exposes the guard through wifi_densepose_wasm_edge::tmp_temporal_logic_guard, enabling JavaScript consumption for web-based dashboards:
import init, { TemporalLogicGuard, FrameInput } from './wifi_densepose_wasm_edge.js';
async function runLTL() {
await init();
const guard = TemporalLogicGuard.new();
function makeFrame(data) {
const f = FrameInput.default();
f.presence = data.presence;
f.n_persons = data.n_persons;
f.motion_energy = data.motion_energy;
f.coherence = data.coherence;
f.breathing_bpm = data.breathing_bpm;
f.heartrate_bpm = data.heartrate_bpm;
f.fall_alert = data.fall_alert;
f.intrusion_alert = data.intrusion_alert;
f.person_id_active = data.person_id_active;
f.vital_signs_active = data.vital_signs_active;
f.seizure_detected = data.seizure_detected;
f.normal_gait = data.normal_gait;
return f;
}
const csiStream = getCsiStream();
for await (const snapshot of csiStream) {
const frame = makeFrame(snapshot);
const events = guard.on_frame(frame);
for (let i = 0; i < events.length; i++) {
const [id, payload] = events[i];
if (id === 795) {
console.warn(`LTL rule ${payload} violated`);
} else if (id === 796) {
console.log(`Health check: ${payload} rules satisfied`);
}
}
}
}
runLTL();
Extending the Rule Set with Custom Safety Policies
To add a new F-rule requiring presence > 0 within 10 seconds of an intrusion_alert:
// Add deadline constant (20 Hz × 10 seconds).
const INTRUSION_DEADLINE: u32 = 200;
// In TemporalLogicGuard::new(), increment NUM_RULES and initialize state.
// In on_frame(), after G-rule processing:
if self.check_deadline_rule(8, input.intrusion_alert, INTRUSION_DEADLINE) {
// Violation emitted automatically with EVENT_LTL_VIOLATION and rule index 8.
}
Re-run cargo test --workspace to verify the extended logic. The guard will emit EVENT_LTL_VIOLATION with payload 8 and populate EVENT_COUNTEREXAMPLE with the violating frame index.
Summary
- RuView implements LTL verification through
tmp_temporal_logic_guard.rsin the WASM edge crate, processing CSI-derivedFrameInputstructures at 20 Hz. - Two rule types govern behavior: G-rules (immediate violation) and F-rules (deadline-based eventual conditions) with configurable timeouts like
FAST_BREATH_DEADLINEandSEIZURE_EXCLUSION. - Event-driven architecture emits IDs
795(violation),796(satisfaction), and797(counterexample) with bounded 12-entry buffers per frame. - Dual deployment supports both native Rust integration and WebAssembly browser execution via the same
TemporalLogicGuardAPI. - Extensible design allows adding custom safety policies by defining new deadline constants and invoking
check_deadline_rulewith incremented rule indices.
Frequently Asked Questions
What is the processing frequency of the LTL guard in RuView?
The guard evaluates on_frame once per frame at approximately 20 Hz, corresponding to the CSI capture rate. This timing determines the real-world interpretation of deadline constants: FAST_BREATH_DEADLINE = 100 equals 5 seconds, while MOTION_STOP_DEADLINE = 6000 equals 300 seconds.
How does RuView distinguish between immediate and deadline-based LTL violations?
G-rules trigger instantly when boolean conditions evaluate true on any single frame, while F-rules use internal state machines that track time since a trigger event. When the deadline expires without the required condition being met, the guard transitions from Pending to Violated and emits EVENT_LTL_VIOLATION.
Can the LTL guard run outside of WebAssembly in pure Rust?
Yes. The TemporalLogicGuard struct lives in wifi-densepose-wasm-edge/src/tmp_temporal_logic_guard.rs but compiles as standard Rust. Unit tests in tests/vendor_modules_test.rs demonstrate pure Rust usage without WASM bindings, though the module is optimized for edge deployment where it can be called from JavaScript via the generated WASM interface.
Where are the safety rule deadlines configured in the source code?
Deadlines are defined as const values at the top of tmp_temporal_logic_guard.rs. For example, const FAST_BREATH_DEADLINE: u32 = 100 and const SEIZURE_EXCLUSION: u32 = 1200. These frame-count values assume the 20 Hz processing rate documented in the pipeline architecture.
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 →