ESPectre SDK 2.8.0-280-gac7af68
Wi-Fi CSI motion sensing for ESP32 firmware
Loading...
Searching...
No Matches
espectre::LightweightDetector Class Reference

The default detector: self-calibrating, no training data required. More...

#include <lightweight_detector.h>

Inheritance diagram for espectre::LightweightDetector:
espectre::BaseDetector

Public Member Functions

 LightweightDetector (uint16_t window_size=DETECTOR_DEFAULT_WINDOW_SIZE, float threshold=LIGHTWEIGHT_DEFAULT_THRESHOLD, uint16_t autocorr_lag=1U)
 ~LightweightDetector () override=default
 LightweightDetector (LightweightDetector &&other) noexcept=default
LightweightDetectoroperator= (LightweightDetector &&other) noexcept=default
 LightweightDetector (const LightweightDetector &)=delete
LightweightDetectoroperator= (const LightweightDetector &)=delete
void process_packet (const int8_t *csi_data, size_t csi_len, const uint8_t *selected_subcarriers=nullptr, uint8_t num_subcarriers=0, int8_t rssi_dbm=INT8_MIN) override
 Process a CSI packet and update internal state.
void advance_missing_slots (uint32_t count) override
 Advance packet-indexed feature rings for absent temporal slots.
void update_state () override
 Update state machine (call at publish interval).
void reset () override
 Reset detector state.
void clear_buffer () override
 Clear turbulence buffer (cold restart).
void configure_hampel (bool enabled, uint8_t window_size=HAMPEL_TURBULENCE_WINDOW_DEFAULT, float threshold=HAMPEL_TURBULENCE_THRESHOLD_DEFAULT) override
 Configure Hampel filter.
void configure_lowpass (bool enabled, float cutoff_hz=LOWPASS_CUTOFF_DEFAULT) override
 Configure low-pass filter.
bool is_ready () const override
 Check if detector is ready (buffer filled).
bool set_threshold (float threshold) override
 Set detection threshold.
bool set_adaptive_threshold (float threshold) override
 Apply a detector-specific startup-calibrated threshold.
float get_threshold () const override
 Get current threshold.
const char * get_name () const override
 Get detector name for logging.
float get_startup_threshold_factor () const override
 Get the detector-specific automatic startup multiplier.
bool startup_gate_enabled () const override
 Whether startup calibration uses the consistency gate (threshold.h).
void on_startup_calibration_begin () override
 Hook called immediately before startup calibration begins.
void on_startup_calibration_complete () override
 Hook called when startup calibration completes successfully.
float get_turb_autocorr () const
float get_turb_iqr_over_mean_aggr () const
float get_logit () const
Public Member Functions inherited from espectre::BaseDetector
 BaseDetector (uint16_t window_size=DETECTOR_DEFAULT_WINDOW_SIZE)
 Constructor.
virtual ~BaseDetector ()
 BaseDetector (BaseDetector &&other) noexcept
BaseDetectoroperator= (BaseDetector &&other) noexcept
 BaseDetector (const BaseDetector &)=delete
BaseDetectoroperator= (const BaseDetector &)=delete
void set_packet_timestamp_us (uint64_t timestamp_us)
 Supply the monotonic arrival timestamp consumed by time-binned features.
virtual MotionState get_state () const
 Get current motion state.
void set_minimum_valid_samples (uint16_t count)
 Set the valid-slot occupancy floor used by is_ready().
virtual uint32_t get_total_packets () const
 Get total packets processed.
float get_motion_metric () const
 Get current motion metric value.
const float * get_turbulence_buffer () const
 Get turbulence buffer pointer.
uint16_t get_buffer_count () const
 Get number of valid samples in buffer.
uint16_t get_valid_buffer_count () const
uint16_t get_window_size () const
 Get configured window size.
float get_last_turbulence () const
 Get last turbulence value.
bool is_lowpass_enabled () const
 Check if low-pass filter is enabled.
bool is_hampel_enabled () const
 Check if Hampel filter is enabled.

Additional Inherited Members

Protected Member Functions inherited from espectre::BaseDetector
void clear_evaluation_state_ ()
 Drop the last evaluation result.
void process_amplitudes (const float *amplitudes, uint8_t count)
uint64_t packet_timestamp_us_or (uint64_t fallback) const
void add_turbulence_to_buffer (float turbulence)
 Add turbulence value to buffer (with filtering).
const float * ordered_turbulence (uint16_t &count) const
 View the turbulence ring in chronological order.
Static Protected Member Functions inherited from espectre::BaseDetector
static float * alloc_zeroed_floats (uint16_t count)
 Allocate a zeroed float buffer on the heap.
Protected Attributes inherited from espectre::BaseDetector
float * turbulence_buffer_
float * ordered_turbulence_
uint16_t buffer_index_
uint16_t buffer_count_
uint16_t valid_buffer_count_
uint16_t minimum_valid_samples_
uint16_t window_size_
MotionState state_
float current_metric_
uint32_t total_packets_
uint32_t packet_index_
uint64_t packet_timestamp_us_
bool has_packet_timestamp_
hampel_filter_state_t hampel_state_
lowpass_filter_state_t lowpass_state_

Detailed Description

The default detector: self-calibrating, no training data required.

Fuses turbulence autocorrelation with robust spread from a five-bin aggregated turbulence stream, and adapts its threshold to the room during startup calibration. After that, a long quiet stretch can still lower the live threshold when the opening was noisier than the rest of the session. The full runtime emits IRuntimeListener::on_threshold_changed() for that drop; a core-only integration must re-read get_threshold() after update_state(). Prefer it unless you have a reason to run HighAccuracyDetector.

Most integrations never construct one: RuntimeConfig::detection_algorithm selects it and the runtime owns the lifecycle. Drive it directly only on the core-only path, where your firmware already captures CSI:

// per packet, from your capture callback:
// on your evaluation cadence:
detector.update_state();
if (detector.is_ready() && detector.get_state() == espectre::MotionState::MOTION) { ... }
virtual MotionState get_state() const
Get current motion state.
The default detector: self-calibrating, no training data required.
void update_state() override
Update state machine (call at publish interval).
void process_packet(const int8_t *csi_data, size_t csi_len, const uint8_t *selected_subcarriers=nullptr, uint8_t num_subcarriers=0, int8_t rssi_dbm=INT8_MIN) override
Process a CSI packet and update internal state.
bool is_ready() const override
Check if detector is ready (buffer filled).
constexpr uint8_t HT20_SELECTED_BAND_SIZE
Definition csi_types.h:27
constexpr uint8_t DEFAULT_SUBCARRIERS[HT20_SELECTED_BAND_SIZE]
Definition csi_types.h:29

is_ready() is false until the window fills; results before that are not meaningful. See runtime/esp_idf/csi_pipeline.cpp for the reference normalization, cadence, and hit filtering around these calls, and docs/ALGORITHMS.md for the algorithm itself.

Threading
Not thread-safe. process_packet() and update_state() must not run concurrently.

Definition at line 83 of file lightweight_detector.h.

Constructor & Destructor Documentation

◆ LightweightDetector() [1/3]

espectre::LightweightDetector::LightweightDetector ( uint16_t window_size = DETECTOR_DEFAULT_WINDOW_SIZE,
float threshold = LIGHTWEIGHT_DEFAULT_THRESHOLD,
uint16_t autocorr_lag = 1U )
Parameters
window_sizeDetector window in packets
thresholdMotion probability threshold
autocorr_lagTurbulence autocorrelation distance in packets

Production uses the nominal-rate default. Alternate lags are exposed for replay experiments only: changing the feature offset requires validating the fitted coefficients before deployment. See detector_timing.h.

◆ ~LightweightDetector()

espectre::LightweightDetector::~LightweightDetector ( )
overridedefault

◆ LightweightDetector() [2/3]

espectre::LightweightDetector::LightweightDetector ( LightweightDetector && other)
defaultnoexcept

◆ LightweightDetector() [3/3]

espectre::LightweightDetector::LightweightDetector ( const LightweightDetector & )
delete

Member Function Documentation

◆ operator=() [1/2]

LightweightDetector & espectre::LightweightDetector::operator= ( LightweightDetector && other)
defaultnoexcept

◆ operator=() [2/2]

LightweightDetector & espectre::LightweightDetector::operator= ( const LightweightDetector & )
delete

◆ process_packet()

void espectre::LightweightDetector::process_packet ( const int8_t * csi_data,
size_t csi_len,
const uint8_t * selected_subcarriers = nullptr,
uint8_t num_subcarriers = 0,
int8_t rssi_dbm = INT8_MIN )
overridevirtual

Process a CSI packet and update internal state.

Calculates spatial turbulence from CSI data, applies filtering, and stores in circular buffer.

Parameters
csi_dataRaw CSI data (I/Q interleaved)
csi_lenLength of CSI data
selected_subcarriersArray of subcarrier indices
num_subcarriersNumber of selected subcarriers
rssi_dbmLink RSSI for this packet, or INT8_MIN when unknown

Reimplemented from espectre::BaseDetector.

◆ advance_missing_slots()

void espectre::LightweightDetector::advance_missing_slots ( uint32_t count)
overridevirtual

Advance packet-indexed feature rings for absent temporal slots.

Reimplemented from espectre::BaseDetector.

◆ update_state()

void espectre::LightweightDetector::update_state ( )
overridevirtual

Update state machine (call at publish interval).

Subclasses implement their detection algorithm here.

Implements espectre::BaseDetector.

◆ reset()

void espectre::LightweightDetector::reset ( )
overridevirtual

Reset detector state.

Resets state machine but preserves buffer ("warm" restart).

Reimplemented from espectre::BaseDetector.

◆ clear_buffer()

void espectre::LightweightDetector::clear_buffer ( )
overridevirtual

Clear turbulence buffer (cold restart).

Virtual so detectors with additional state (e.g. L1-Delta profile rings) can extend the cold clear.

Reimplemented from espectre::BaseDetector.

◆ configure_hampel()

void espectre::LightweightDetector::configure_hampel ( bool enabled,
uint8_t window_size = HAMPEL_TURBULENCE_WINDOW_DEFAULT,
float threshold = HAMPEL_TURBULENCE_THRESHOLD_DEFAULT )
overridevirtual

Configure Hampel filter.

Parameters
enabledWhether to enable the filter
window_sizeWindow size (3-11)
thresholdMAD multiplier threshold

Reimplemented from espectre::BaseDetector.

◆ configure_lowpass()

void espectre::LightweightDetector::configure_lowpass ( bool enabled,
float cutoff_hz = LOWPASS_CUTOFF_DEFAULT )
overridevirtual

Configure low-pass filter.

Parameters
enabledWhether to enable the filter
cutoff_hzCutoff frequency (5.0-20.0 Hz)

Reimplemented from espectre::BaseDetector.

◆ is_ready()

bool espectre::LightweightDetector::is_ready ( ) const
overridevirtual

Check if detector is ready (buffer filled).

Reimplemented from espectre::BaseDetector.

◆ set_threshold()

bool espectre::LightweightDetector::set_threshold ( float threshold)
overridevirtual

Set detection threshold.

Parameters
thresholdNew threshold value
Returns
true if value was accepted

Implements espectre::BaseDetector.

◆ set_adaptive_threshold()

bool espectre::LightweightDetector::set_adaptive_threshold ( float threshold)
overridevirtual

Apply a detector-specific startup-calibrated threshold.

Reimplemented from espectre::BaseDetector.

◆ get_threshold()

float espectre::LightweightDetector::get_threshold ( ) const
inlineoverridevirtual

Get current threshold.

Implements espectre::BaseDetector.

Definition at line 120 of file lightweight_detector.h.

◆ get_name()

const char * espectre::LightweightDetector::get_name ( ) const
inlineoverridevirtual

Get detector name for logging.

Implements espectre::BaseDetector.

Definition at line 121 of file lightweight_detector.h.

◆ get_startup_threshold_factor()

float espectre::LightweightDetector::get_startup_threshold_factor ( ) const
inlineoverridevirtual

Get the detector-specific automatic startup multiplier.

threshold = threshold_metric x factor. Matches the Python runtime's detector STARTUP_THRESHOLD_FACTOR convention, where threshold_metric comes from the shared startup calibrator.

Reimplemented from espectre::BaseDetector.

Definition at line 122 of file lightweight_detector.h.

◆ startup_gate_enabled()

bool espectre::LightweightDetector::startup_gate_enabled ( ) const
inlineoverridevirtual

Whether startup calibration uses the consistency gate (threshold.h).

Enabled only for detectors with a tight quiet floor (l1_delta). Matches the Python runtime's detector STARTUP_GATE convention.

Reimplemented from espectre::BaseDetector.

Definition at line 125 of file lightweight_detector.h.

◆ on_startup_calibration_begin()

void espectre::LightweightDetector::on_startup_calibration_begin ( )
overridevirtual

Hook called immediately before startup calibration begins.

Reimplemented from espectre::BaseDetector.

◆ on_startup_calibration_complete()

void espectre::LightweightDetector::on_startup_calibration_complete ( )
overridevirtual

Hook called when startup calibration completes successfully.

Detectors can freeze session-specific state here before the runtime performs its warm clear between calibration and steady-state detection.

Reimplemented from espectre::BaseDetector.

◆ get_turb_autocorr()

float espectre::LightweightDetector::get_turb_autocorr ( ) const
inline

Definition at line 129 of file lightweight_detector.h.

◆ get_turb_iqr_over_mean_aggr()

float espectre::LightweightDetector::get_turb_iqr_over_mean_aggr ( ) const
inline

Definition at line 130 of file lightweight_detector.h.

◆ get_logit()

float espectre::LightweightDetector::get_logit ( ) const
inline

Definition at line 131 of file lightweight_detector.h.


The documentation for this class was generated from the following file: