Skip to content

Commit f19b2fb

Browse files
nerdCopterclaude
andcommitted
feat: flag ESO ceiling in legend and result struct
Add at_ceiling: bool to EsoResult, set when omega0_opt reaches the stability-constrained search bound (omega0_max_stable - GSS_TOLERANCE). Propagate through AxisEsoData into the plot legend as ' [at ceiling]' so users can see at a glance when the optimizer hit its upper bound rather than finding a true interior optimum. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 32246d2 commit f19b2fb

2 files changed

Lines changed: 13 additions & 4 deletions

File tree

src/eso.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ pub struct EsoResult {
6666
pub b0_auto: bool,
6767
/// N-step-ahead prediction MSE at the optimal omega0.
6868
pub mse: f64,
69+
/// True when omega0_opt is at the search ceiling (result may not be the true optimum).
70+
pub at_ceiling: bool,
6971
/// Number of samples used in the optimization.
7072
#[allow(dead_code)]
7173
pub sample_count: usize,
@@ -362,6 +364,7 @@ pub fn run_eso_optimization(
362364
.best_param
363365
.ok_or("ESO optimization returned no solution")?;
364366
let mse = run_result.state().best_cost;
367+
let at_ceiling = omega0_opt >= omega0_max_stable - ESO_GSS_TOLERANCE;
365368

366369
let (beta1, beta2) = leso2_gains(omega0_opt);
367370

@@ -376,6 +379,7 @@ pub fn run_eso_optimization(
376379
b0,
377380
b0_auto,
378381
mse,
382+
at_ceiling,
379383
sample_count: omega_meas.len(),
380384
timestamps,
381385
omega_meas_trace: omega_meas,

src/plot_functions/plot_eso.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,13 @@ pub fn plot_eso_output(
8080
let mut series = vec![
8181
PlotSeries {
8282
data: hat_data,
83-
label: format!(
84-
"ESO estimate (omega_hat, omega0={:.0} rad/s, b0={:.2})",
85-
data.omega0_opt, data.b0
86-
),
83+
label: {
84+
let ceiling = if data.at_ceiling { " [at ceiling]" } else { "" };
85+
format!(
86+
"ESO estimate (omega_hat, omega0={:.0} rad/s, b0={:.2}){ceiling}",
87+
data.omega0_opt, data.b0
88+
)
89+
},
8790
color: color_hat,
8891
stroke_width: stroke + 1,
8992
},
@@ -123,6 +126,7 @@ pub fn plot_eso_output(
123126
struct AxisEsoData {
124127
omega0_opt: f64,
125128
b0: f64,
129+
at_ceiling: bool,
126130
/// (time, omega_meas, omega_hat) triples
127131
meas_hat: Vec<(f64, f64, f64)>,
128132
/// (time, f_hat_raw) before visual scaling
@@ -158,6 +162,7 @@ fn build_axis_data(eso: &EsoResult) -> AxisEsoData {
158162
AxisEsoData {
159163
omega0_opt: eso.omega0_opt,
160164
b0: eso.b0,
165+
at_ceiling: eso.at_ceiling,
161166
meas_hat,
162167
fhat,
163168
fhat_max_abs,

0 commit comments

Comments
 (0)