Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_Compass/CompassCalibrator.h
Views: 1798
#pragma once12#include "AP_Compass_config.h"34#if COMPASS_CAL_ENABLED56#include <AP_Math/AP_Math.h>78#define COMPASS_CAL_NUM_SPHERE_PARAMS 49#define COMPASS_CAL_NUM_ELLIPSOID_PARAMS 910#define COMPASS_CAL_NUM_SAMPLES 300 // number of samples required before fitting begins1112class CompassCalibrator {13public:14CompassCalibrator();1516// start or stop the calibration17void start(bool retry, float delay, uint16_t offset_max, uint8_t compass_idx, float tolerance);18void stop();1920// Update point sample21void new_sample(const Vector3f& sample);2223// set compass's initial orientation and whether it should be automatically fixed (if required)24void set_orientation(enum Rotation orientation, bool is_external, bool fix_orientation, bool always_45_deg);2526// running is true if actively calculating offsets, diagonals or offdiagonals27bool running();2829// failed is true if either of the failure states are hit30bool failed();313233// update the state machine and calculate offsets, diagonals and offdiagonals34void update();3536// compass calibration states - these correspond to the mavlink37// MAG_CAL_STATUS enumeration38enum class Status {39NOT_STARTED = 0,40WAITING_TO_START = 1,41RUNNING_STEP_ONE = 2,42RUNNING_STEP_TWO = 3,43SUCCESS = 4,44FAILED = 5,45BAD_ORIENTATION = 6,46BAD_RADIUS = 7,47};4849// get completion mask for mavlink reporting (a bitmask of faces/directions for which we have compass samples)50typedef uint8_t completion_mask_t[10];5152// Structure accessed for cal status update via mavlink53struct State {54Status status;55uint8_t attempt;56float completion_pct;57completion_mask_t completion_mask;58} cal_state;5960// Structure accessed after calibration is finished/failed61struct Report {62Status status;63float fitness;64Vector3f ofs;65Vector3f diag;66Vector3f offdiag;67float orientation_confidence;68Rotation original_orientation;69Rotation orientation;70float scale_factor;71bool check_orientation;72} cal_report;7374// Structure setup to set calibration run settings75struct Settings {76float tolerance;77bool check_orientation;78enum Rotation orientation;79enum Rotation orig_orientation;80bool is_external;81bool fix_orientation;82uint16_t offset_max;83uint8_t attempt;84bool retry;85float delay_start_sec;86uint32_t start_time_ms;87uint8_t compass_idx;88bool always_45_deg;89} cal_settings;9091// Get calibration result92const Report get_report();9394// Get current Calibration state95const State get_state();9697protected:98// convert index to rotation, this allows to skip some rotations99// protected so CompassCalibrator_index_test can see it100Rotation auto_rotation_index(uint8_t n) const;101102// return true if this is a right angle rotation103bool right_angle_rotation(Rotation r) const;104105private:106107// results108class param_t {109public:110float* get_sphere_params() {111return &radius;112}113114float* get_ellipsoid_params() {115return &offset.x;116}117118float radius; // magnetic field strength calculated from samples119Vector3f offset; // offsets120Vector3f diag; // diagonal scaling121Vector3f offdiag; // off diagonal scaling122float scale_factor; // scaling factor to compensate for radius error123};124125// compact class for approximate attitude, to save memory126class AttitudeSample {127public:128Matrix3f get_rotmat() const;129void set_from_ahrs();130private:131int8_t roll;132int8_t pitch;133int8_t yaw;134};135136// compact class to hold compass samples, to save memory137class CompassSample {138public:139Vector3f get() const;140void set(const Vector3f &in);141AttitudeSample att;142private:143int16_t x;144int16_t y;145int16_t z;146};147148// set status including any required initialisation149bool set_status(Status status);150151// consume point raw sample from intermediate structure152void pull_sample();153154// returns true if sample should be added to buffer155bool accept_sample(const Vector3f &sample, uint16_t skip_index = UINT16_MAX);156bool accept_sample(const CompassSample &sample, uint16_t skip_index = UINT16_MAX);157158// returns true if fit is acceptable159bool fit_acceptable() const;160161// clear sample buffer and reset offsets and scaling to their defaults162void reset_state();163164// initialize fitness before starting a fit165void initialize_fit();166167// true if enough samples have been collected and fitting has begun (aka runniong())168bool _fitting() const;169170// thins out samples between step one and step two171void thin_samples();172173// calc the fitness of a single sample vs a set of parameters (offsets, diagonals, off diagonals)174float calc_residual(const Vector3f& sample, const param_t& params) const;175176// calc the fitness of the parameters (offsets, diagonals, off diagonals) vs all the samples collected177// returns 1.0e30f if the sample buffer is empty178float calc_mean_squared_residuals(const param_t& params) const;179180// calculate initial offsets by simply taking the average values of the samples181void calc_initial_offset();182183// run sphere fit to calculate diagonals and offdiagonals184void calc_sphere_jacob(const Vector3f& sample, const param_t& params, float* ret) const;185void run_sphere_fit();186187// run ellipsoid fit to calculate diagonals and offdiagonals188void calc_ellipsoid_jacob(const Vector3f& sample, const param_t& params, float* ret) const;189void run_ellipsoid_fit();190191// update the completion mask based on a single sample192void update_completion_mask(const Vector3f& sample);193194// reset and updated the completion mask using all samples in the sample buffer195void update_completion_mask();196197// calculate compass orientation198Vector3f calculate_earth_field(CompassSample &sample, enum Rotation r);199bool calculate_orientation();200201// fix radius to compensate for sensor scaling errors202bool fix_radius();203204// update methods to read write intermediate structures, called inside thread205inline void update_cal_status();206inline void update_cal_report();207inline void update_cal_settings();208209// running method for use in thread210bool _running() const;211212uint8_t _compass_idx; // index of the compass providing data213Status _status; // current state of calibrator214215// values provided by caller216float _delay_start_sec; // seconds to delay start of calibration (provided by caller)217bool _retry; // true if calibration should be restarted on failured (provided by caller)218float _tolerance = 5.0; // worst acceptable RMS tolerance (aka fitness). see set_tolerance()219uint16_t _offset_max; // maximum acceptable offsets (provided by caller)220221// behavioral state222uint32_t _start_time_ms; // system time start() function was last called223uint8_t _attempt; // number of attempts have been made to calibrate224completion_mask_t _completion_mask; // bitmask of directions in which we have samples225CompassSample *_sample_buffer; // buffer of sensor values226uint16_t _samples_collected; // number of samples in buffer227uint16_t _samples_thinned; // number of samples removed by the thin_samples() call (called before step 2 begins)228229// fit state230class param_t _params; // latest calibration outputs231uint16_t _fit_step; // step during RUNNING_STEP_ONE/TWO which performs sphere fit and ellipsoid fit232float _fitness; // fitness (mean squared residuals) of current parameters233float _initial_fitness; // fitness before latest "fit" was attempted (used to determine if fit was an improvement)234float _sphere_lambda; // sphere fit's lambda235float _ellipsoid_lambda; // ellipsoid fit's lambda236237// variables for orientation checking238enum Rotation _orientation; // latest detected orientation239enum Rotation _orig_orientation; // original orientation provided by caller240enum Rotation _orientation_solution; // latest solution241bool _is_external; // true if compass is external (provided by caller)242bool _check_orientation; // true if orientation should be automatically checked243bool _fix_orientation; // true if orientation should be fixed if necessary244bool _always_45_deg; // true if orientation should consider 45deg with equal tolerance245float _orientation_confidence; // measure of confidence in automatic orientation detection246CompassSample _last_sample;247248Status _requested_status;249bool _status_set_requested;250251bool _new_sample;252253// Semaphore for state related intermediate structures254HAL_Semaphore state_sem;255256// Semaphore for intermediate structure for point sample collection257HAL_Semaphore sample_sem;258};259260#endif // COMPASS_CAL_ENABLED261262263