STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
RobustCalibrationFramework.hpp
Go to the documentation of this file.
1#ifndef ROBUST_CALIBRATION_FRAMEWORK_HPP
2#define ROBUST_CALIBRATION_FRAMEWORK_HPP
3
4#include <Eigen/Dense>
5#include <chrono>
6#include <cstdint>
7#include <deque>
8#include <optional>
9#include <utility>
10#include <vector>
11
14
15namespace fsw {
16namespace calibration {
17
18/** Environmental state [T, H, V, A, M] — scripts/calibration/robust_calibration.py */
20 double temperature = 25.0;
21 double humidity = 50.0;
22 double vibration = 0.0;
23 double aging_factor = 1.0;
24 double mounting_torque = 1.0;
25};
26
28 double adc_code = 0;
29 double pressure = 0;
30 double timestamp = 0;
32 double uncertainty = 0.01;
33};
34
35/**
36 * Port of scripts/calibration/robust_calibration.py RobustCalibrationFramework:
37 * 9-parameter environmental basis, TLS, Bayesian update, RLS, GLR drift, Gauss–Markov bias,
38 * optional Allan σ_meas (AllanVariance.hpp).
39 */
41public:
42 static constexpr int N = 9;
43
45
46 /** Seed θ by ridge LS so Φ·θ ≈ factory cubic P(adc) on an ADC grid (same env as streaming).
47 * The old 2-parameter linear seed could not match a cubic → robust read low vs factory. */
49
50 /** Max |Φ·θ − P_factory(adc)| over a dense ADC grid — sanity-check saved adjustments.json. */
51 double max_abs_error_vs_factory(const PTCalibrationCoeffs& factory_cubic) const;
52
53 void set_theta_from_polynomial(const std::vector<double>& poly_coeffs, double adc_norm_min,
54 double adc_norm_scale);
55
56 void set_noise_coeffs(const NoiseCoefficients& c, double tau0 = 0.01);
57
58 /** Mean + σ; updates bias propagation clock. */
59 std::pair<double, double> predict_pressure_with_uncertainty(double adc_code,
60 const EnvironmentalState& env);
61
62 /** Mean PSI for streaming (default env, used by calibration_service). */
63 double predict_pressure_psi(double adc_code);
64
65 /** Zero / capture / reference — full Python add_calibration_point logic. */
66 void add_calibration_point(const CalibrationPoint& point);
67
68 int sensor_id() const {
69 return sensor_id_;
70 }
71 size_t calibration_points_count() const {
72 return calibration_points_.size();
73 }
74
75 Eigen::VectorXd theta_mean() const {
76 return theta_mean_;
77 }
78 Eigen::MatrixXd theta_cov() const {
79 return theta_cov_;
80 }
81 void set_theta_mean_for_restore(const Eigen::VectorXd& t);
82 void set_theta_cov_for_restore(const Eigen::MatrixXd& cov);
83 Eigen::MatrixXd rls_P_matrix() const {
84 return rls_P_;
85 }
86 void set_rls_P_for_restore(const Eigen::MatrixXd& p);
87
88private:
90
91 std::vector<CalibrationPoint> calibration_points_;
92 static constexpr size_t kCalibrationPointsMax = 50;
93
94 Eigen::VectorXd theta_mean_;
95 Eigen::MatrixXd theta_cov_;
96 Eigen::MatrixXd rls_P_;
97
101
103 double alpha_v_;
105
106 Eigen::MatrixXd env_var_env_; // 5x5
107 Eigen::MatrixXd env_var_interaction_; // 5x5
108
110 double alpha1 = 0.001, alpha2 = 0.0001;
111 double beta1 = 0.0001, beta2 = 0.00001;
112 double gamma1 = 0.0001;
113 double delta1 = 0.001, delta2 = 0.0001;
115
116 // Gauss–Markov bias (3-state)
117 Eigen::Vector3d bias_b_;
118 Eigen::Matrix3d bias_P_;
119 Eigen::Vector3d bias_tau_;
121
122 std::chrono::steady_clock::time_point last_pred_time_;
125
126 std::optional<NoiseCoefficients> noise_coeffs_;
128
129 std::deque<double> recent_residuals_;
130 std::deque<double> recent_uncertainties_;
132
133 Eigen::VectorXd environmental_basis(double adc_code, const EnvironmentalState& env) const;
134
135 std::pair<Eigen::VectorXd, Eigen::MatrixXd> total_least_squares_calibration(
136 const std::vector<CalibrationPoint>& points) const;
137
138 std::pair<Eigen::VectorXd, Eigen::MatrixXd> bayesian_update(
139 const std::vector<CalibrationPoint>& new_points);
140
141 std::pair<Eigen::VectorXd, Eigen::MatrixXd> recursive_least_squares_update(
142 const CalibrationPoint& point);
143
144 std::pair<double, bool> generalized_likelihood_ratio_test(
145 const std::vector<CalibrationPoint>& points) const;
146
147 double extrapolation_variance(double adc_code) const;
148
149 double compute_measurement_variance(double adc_code, double tau) const;
150
151 void bias_propagate(double dt);
152 void bias_update(double residual, double sigma_meas, double dt);
153 double bias_contribution() const;
154 double bias_variance() const;
155};
156
157} // namespace calibration
158} // namespace fsw
159
160#endif
std::pair< double, bool > generalized_likelihood_ratio_test(const std::vector< CalibrationPoint > &points) const
std::pair< Eigen::VectorXd, Eigen::MatrixXd > bayesian_update(const std::vector< CalibrationPoint > &new_points)
Eigen::VectorXd environmental_basis(double adc_code, const EnvironmentalState &env) const
void seed_from_factory_cubic(const PTCalibrationCoeffs &c)
Seed θ by ridge LS so Φ·θ ≈ factory cubic P(adc) on an ADC grid (same env as streaming).
void bias_update(double residual, double sigma_meas, double dt)
struct fsw::calibration::RobustCalibrationFramework::PhysicalParams physical_
double predict_pressure_psi(double adc_code)
Mean PSI for streaming (default env, used by calibration_service).
void set_theta_from_polynomial(const std::vector< double > &poly_coeffs, double adc_norm_min, double adc_norm_scale)
std::pair< double, double > predict_pressure_with_uncertainty(double adc_code, const EnvironmentalState &env)
Mean + σ; updates bias propagation clock.
void add_calibration_point(const CalibrationPoint &point)
Zero / capture / reference — full Python add_calibration_point logic.
double max_abs_error_vs_factory(const PTCalibrationCoeffs &factory_cubic) const
Max |Φ·θ − P_factory(adc)| over a dense ADC grid — sanity-check saved adjustments....
std::pair< Eigen::VectorXd, Eigen::MatrixXd > recursive_least_squares_update(const CalibrationPoint &point)
std::chrono::steady_clock::time_point last_pred_time_
std::pair< Eigen::VectorXd, Eigen::MatrixXd > total_least_squares_calibration(const std::vector< CalibrationPoint > &points) const
double compute_measurement_variance(double adc_code, double tau) const
void set_noise_coeffs(const NoiseCoefficients &c, double tau0=0.01)
int32_t p
Definition flight_e2e.c:78
Output smoothing for calibrated PT pressure, per sensor uid (ESP32 and LabJack T7 alike).
Motorized ball valve position: raw ADC counts -> % open.
Environmental state [T, H, V, A, M] — scripts/calibration/robust_calibration.py.
Noise coefficients from Allan variance fit (scripts/calibration/allan_variance.py).
PT Calibration Coefficients.