Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,22 +233,36 @@ Physics-derived P gain optimization using a Torque-Inertia Profiler that measure
- **P Decrease:** Td faster than target with high noise → P is too high (rare)
- **Investigate:** Measurements suggest mechanical issues or abnormal dynamics

- **Output:** Console report and PNG legend overlay showing: Td mean with `windows=` count (valid step-response windows contributing to the Td mean), target, deviation %, noise level, consistency % (orange warning when CV exceeds `TD_COEFFICIENT_OF_VARIATION_MAX`), `[LOW AUTHORITY]` warning when max setpoint is below `LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S`, and P recommendation with calculated D adjustment. When profiling is skipped (insufficient punch events), a skip reason appears in both outputs. See **Consistency and Reliability Interpretation** below for signal details.
- **Output:** Console and PNG legend overlay (identical content) per axis:
- `Td:` — measured Td mean with target `±tolerance` and `windows=` count
- `Td source:` — `File Group` (multi-file run) or `Single File`, with flight count and throttle-punch count that produced the physics target
- `Noise:` — HF D-term energy level (`LOW` / `MODERATE` / `HIGH` / `UNKNOWN`) for the current flight
- `Deviation:` — % difference between measured Td and physics target, with zone label
- `Current P=` — P gain value from the flight's metadata
- `Recommendation` — one of `(Conservative)`, `(Decrease)`, `Current P is optimal`, or `Investigate —` with reason; includes calculated D adjustment
- `Reliable:` / `Unreliable:` — always shows both `Consistency=N% (⊢≥70%)` and `CV=N% (⊢≤40%)`; `Unreliable` is highlighted in orange when either threshold is not met
- `Setpoint Authority:` — always shown; classifies flight inputs as `LOW`, `MODERATE`, or `HIGH` based on the **mean** of per-window max setpoints (see below). Orange for `LOW`.
- When profiling is skipped (insufficient punch events), a skip reason replaces the above. See **Consistency and Reliability Interpretation** below.

- **Consistency and Reliability Interpretation (CV):**
- **CV (Coefficient of Variation)** = standard deviation / mean of individual Td measurements across all valid step-response windows. It quantifies how scattered the measurements are relative to their average.
- **Low CV:** Td measurements are tightly clustered — the log contains clean, repeatable dynamics and recommendations are trustworthy.
- **High CV (exceeds `TD_COEFFICIENT_OF_VARIATION_MAX`):** Td measurements vary widely across windows — a consistency warning is shown in both console and PNG. Recommendations should be treated with caution.
- **CV = None:** Fewer than `TD_SAMPLES_MIN_FOR_STDDEV` valid Td samples were available; standard deviation cannot be computed. The mean is still reported but no consistency rating is given.
- **Low-authority flight warning:** When the maximum setpoint across all valid windows is below `LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S`, a `[LOW AUTHORITY]` warning is shown in both console and PNG. Hover tests and slow-cruise logs never produce sharp inputs — step-response analysis and Td measurements from such logs are noise-dominated rather than dynamics-dominated, making all recommendations unreliable regardless of CV.
- **High CV (exceeds `TD_COEFFICIENT_OF_VARIATION_MAX`):** Td measurements vary widely across windows — `Unreliable:` is shown (orange) in both console and PNG. Recommendations should be treated with caution.
- **CV = N/A:** Fewer than `TD_SAMPLES_MIN_FOR_STDDEV` valid Td samples were available; standard deviation cannot be computed. The mean is still reported and `CV=N/A` appears in the reliability line.
- **Setpoint Authority classification:** Always-visible line in both console and PNG. Uses the **mean** of per-window max setpoints (not the maximum) to classify the flight:
- `LOW` (`mean < 100 dps`, orange) — hover/slow-cruise inputs; all P:D recommendations are still shown, but the pilot should treat them with caution.
- `MODERATE` (`100–250 dps`) — normal sport/freestyle inputs.
- `HIGH` (`> 250 dps`) — aggressive or race-pace inputs.
Format: `Setpoint Authority: LOW (mean=68dps ⊢≥100dps)`. Using the mean rather than the max prevents a single high-input window from masking an otherwise gentle hover log.
- **Why hover logs produce high CV:** Small setpoint inputs → deconvolution is noise-sensitive → each window captures a different noise realisation. The averaged response may appear plausible (noise averages out) while individual window variance remains high. CV exposes this where the mean alone cannot.
- **Over-P limitation:** **When P is already too high and the aircraft oscillates, the profiler may report "Optimal" rather than "Decrease P."** An oscillatory step response produces a short, aggressive measured Td — which, fed into the physics formula, yields a P_optimal close to the current (excessive) P. The profiler cannot reliably distinguish a well-tuned fast response from an over-tuned oscillating one using Td alone. The indirect signal is CV: severe oscillation typically scatters Td samples widely and triggers the consistency warning. **If your gains feel high or the craft exhibits oscillation, start from a lower P before relying on these recommendations.** Optimal P estimation is most accurate when the craft is in a reasonable tuning range — it is a validator and refinement tool, not a recovery tool for badly mis-tuned aircraft. Only experienced pilots are likely to recognise this situation by feel.
- **High CV without `[LOW AUTHORITY]`:** If the consistency warning fires but `[LOW AUTHORITY]` is not shown, the scatter is not caused by low-energy hover inputs. Remaining causes include propwash, inconsistent maneuvers, and oscillation from over-P. **If gains feel high, treat this combination as a prompt to verify the craft is not oscillating before acting on any recommendation.**
- **High CV without LOW authority:** If the consistency warning fires but `Setpoint Authority` is `MODERATE` or `HIGH`, the scatter is not caused by low-energy hover inputs. Remaining causes include propwash, inconsistent maneuvers, and oscillation from over-P. **If gains feel high, treat this combination as a prompt to verify the craft is not oscillating before acting on any recommendation.**
- **Summary of dependability signals in output:**
- `windows=` on the Td line — number of valid step-response windows contributing to the Td mean; more windows = more statistical weight
- Consistency % and CV — how repeatable individual measurements are
- `[LOW AUTHORITY]` — max setpoint too small for reliable step-response characterisation
- Noise level (`LOW` / `MODERATE` / `HIGH`) — HF D-term energy; high noise limits safe P increase
- `Td source:` — flight and throttle-punch counts that calibrated the physics target; `File Group` means data was pooled across multiple logs
- `Reliable:` / `Unreliable:` with `Consistency %` and `CV` — how repeatable the per-flight step-response measurements are (independent of how many punches fed the physics target)
- `Setpoint Authority:` — mean setpoint level across valid windows; `LOW` indicates hover/gentle inputs that may reduce step-response quality
- Noise level (`LOW` / `MODERATE` / `HIGH`) — HF D-term energy for the current flight; high noise limits safe P increase

- **Relationship to P:D Recommendations:**
- P:D ratio recommendations: analyze peak overshoot → adjust D relative to P
Expand Down
8 changes: 5 additions & 3 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ pub const DEFAULT_SETPOINT_THRESHOLD: f64 = 500.0; // Default setpoint threshold

// Constants for filtering data based on movement and flight phase.
pub const MOVEMENT_THRESHOLD_DEG_S: f64 = 20.0; // Minimum setpoint/gyro magnitude (from PTB/PlasmaTree)
/// Max setpoint (deg/s) below which a flight is considered low-authority.
/// Hover tests and slow-cruise logs never produce sharp inputs, so step-response
/// quality and P:D/optimal-P recommendations from such logs are unreliable.
/// Mean window-max setpoint (deg/s) thresholds for Setpoint Authority classification.
/// LOW < 100 dps : hover/slow-cruise — Moderate/Aggressive recommendations suppressed.
/// MODERATE 100–250 dps : normal flight inputs.
/// HIGH > 250 dps : aggressive/race inputs.
pub const LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S: f32 = 100.0;
pub const HIGH_AUTHORITY_SETPOINT_THRESHOLD_DEG_S: f32 = 250.0;
pub const EXCLUDE_START_S: f64 = 3.0; // Exclude seconds from the start of the log
pub const EXCLUDE_END_S: f64 = 3.0; // Exclude seconds from the end of the log

Expand Down
46 changes: 45 additions & 1 deletion src/data_analysis/calc_step_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,57 @@ use crate::types::StepResponseResult;

use crate::constants::{
APPLY_INDIVIDUAL_RESPONSE_Y_CORRECTION, ENABLE_NORMALIZED_STEADY_STATE_MEAN_CHECK,
FRAME_LENGTH_S, INITIAL_GYRO_SMOOTHING_WINDOW, MOVEMENT_THRESHOLD_DEG_S,
FRAME_LENGTH_S, HIGH_AUTHORITY_SETPOINT_THRESHOLD_DEG_S, INITIAL_GYRO_SMOOTHING_WINDOW,
LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S, MOVEMENT_THRESHOLD_DEG_S,
NORMALIZED_STEADY_STATE_MAX_VAL, NORMALIZED_STEADY_STATE_MEAN_MAX,
NORMALIZED_STEADY_STATE_MEAN_MIN, NORMALIZED_STEADY_STATE_MIN_VAL, RESPONSE_LENGTH_S,
STEADY_STATE_END_S, STEADY_STATE_START_S, SUPERPOSITION_FACTOR, TUKEY_ALPHA,
Y_CORRECTION_MIN_UNNORMALIZED_MEAN_ABS,
};

/// Setpoint authority classification derived from the mean of per-window max setpoints.
/// Describes how aggressively the pilot flew during the step-response windows.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SetpointAuthority {
Low, // mean < LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S
Moderate, // LOW..HIGH
High, // >= HIGH_AUTHORITY_SETPOINT_THRESHOLD_DEG_S
}

impl SetpointAuthority {
pub fn name(&self) -> &'static str {
match self {
Self::Low => "LOW",
Self::Moderate => "MODERATE",
Self::High => "HIGH",
}
}

pub fn is_low(&self) -> bool {
matches!(self, Self::Low)
}
}

/// Compute SetpointAuthority and mean window-max setpoint from QC-passed window data.
/// Returns None if the slice is empty.
pub fn compute_setpoint_authority(
valid_window_max_setpoints: &[f32],
) -> Option<(SetpointAuthority, f32)> {
if valid_window_max_setpoints.is_empty() {
return None;
}
let mean =
valid_window_max_setpoints.iter().sum::<f32>() / valid_window_max_setpoints.len() as f32;
let level = if mean < LOW_AUTHORITY_SETPOINT_THRESHOLD_DEG_S {
SetpointAuthority::Low
} else if mean < HIGH_AUTHORITY_SETPOINT_THRESHOLD_DEG_S {
SetpointAuthority::Moderate
} else {
SetpointAuthority::High
};
Some((level, mean))
}

use crate::data_analysis::fft_utils;

// tukeywin, winstacker_contiguous, wiener_deconvolution_window, cumulative_sum,
Expand Down
Loading
Loading