New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compass Ordering Improvement #12629
Compass Ordering Improvement #12629
Changes from 1 commit
4eba9f7
c03bf68
28a09d1
3f1a7be
1ea4d9e
4106b51
7d97ed8
4f439b3
8aba8a5
54f2535
d7fda5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
#include "CompassCalibrator.h" | ||
#include "AP_Compass_Backend.h" | ||
#include "Compass_PerMotor.h" | ||
#include <AP_Common/TSIndex.h> | ||
|
||
// motor compensation types (for use with motor_comp_enabled) | ||
#define AP_COMPASS_MOT_COMP_DISABLED 0x00 | ||
|
@@ -45,8 +46,17 @@ | |
maximum number of compass instances available on this platform. If more | ||
than 1 then redundant sensors may be available | ||
*/ | ||
#ifndef HAL_BUILD_AP_PERIPH | ||
#define COMPASS_MAX_INSTANCES 3 | ||
#define COMPASS_MAX_BACKEND 3 | ||
#define COMPASS_MAX_UNREG_DEV 5 | ||
#else | ||
#define COMPASS_MAX_INSTANCES 1 | ||
#define COMPASS_MAX_BACKEND 1 | ||
#define COMPASS_MAX_UNREG_DEV 0 | ||
#endif | ||
|
||
#define MAX_CONNECTED_MAGS (COMPASS_MAX_UNREG_DEV+COMPASS_MAX_INSTANCES) | ||
|
||
class CompassLearn; | ||
|
||
|
@@ -87,7 +97,7 @@ friend class AP_Compass_Backend; | |
/// @returns heading in radians | ||
/// | ||
float calculate_heading(const Matrix3f &dcm_matrix) const { | ||
return calculate_heading(dcm_matrix, get_primary()); | ||
return calculate_heading(dcm_matrix, 0); | ||
} | ||
float calculate_heading(const Matrix3f &dcm_matrix, uint8_t i) const; | ||
|
||
|
@@ -107,6 +117,7 @@ friend class AP_Compass_Backend; | |
void set_and_save_diagonals(uint8_t i, const Vector3f &diagonals); | ||
void set_and_save_offdiagonals(uint8_t i, const Vector3f &diagonals); | ||
void set_and_save_scale_factor(uint8_t i, float scale_factor); | ||
void set_and_save_orientation(uint8_t i, Rotation orientation); | ||
|
||
/// Saves the current offset x/y/z values for one or all compasses | ||
/// | ||
|
@@ -122,8 +133,8 @@ friend class AP_Compass_Backend; | |
uint8_t get_count(void) const { return _compass_count; } | ||
|
||
/// Return the current field as a Vector3f in milligauss | ||
const Vector3f &get_field(uint8_t i) const { return _state[i].field; } | ||
const Vector3f &get_field(void) const { return get_field(get_primary()); } | ||
const Vector3f &get_field(uint8_t i) const { return _get_state(Priority(i)).field; } | ||
const Vector3f &get_field(void) const { return get_field(0); } | ||
|
||
/// Return true if we have set a scale factor for a compass | ||
bool have_scale_factor(uint8_t i) const; | ||
|
@@ -166,22 +177,22 @@ friend class AP_Compass_Backend; | |
bool consistent() const; | ||
|
||
/// Return the health of a compass | ||
bool healthy(uint8_t i) const { return _state[i].healthy; } | ||
bool healthy(void) const { return healthy(get_primary()); } | ||
bool healthy(uint8_t i) const { return _get_state(Priority(i)).healthy; } | ||
bool healthy(void) const { return healthy(0); } | ||
uint8_t get_healthy_mask() const; | ||
|
||
/// Returns the current offset values | ||
/// | ||
/// @returns The current compass offsets in milligauss. | ||
/// | ||
const Vector3f &get_offsets(uint8_t i) const { return _state[i].offset; } | ||
const Vector3f &get_offsets(void) const { return get_offsets(get_primary()); } | ||
const Vector3f &get_offsets(uint8_t i) const { return _get_state(Priority(i)).offset; } | ||
const Vector3f &get_offsets(void) const { return get_offsets(0); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry if I'm misunderstanding but previously I think get_offsets() (with no argument field) would return the highest priority compass. I think now though it returns the 0th compass. Maybe I'm just confused about what "Priority()" does. Does it take an instance and convert it to a priority? or does it take a Priority and convert it to an instance? Maybe as mentioned in another comment we just need to renamed "Priority" to make it more clear what it's converting to what. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To Consumers of Compass frontend now 0 == Primary. There's no distinction between primary and 0th instance and secondary and 1st instance and so forth. We take care of that in the frontend. |
||
|
||
const Vector3f &get_diagonals(uint8_t i) const { return _state[i].diagonals; } | ||
const Vector3f &get_diagonals(void) const { return get_diagonals(get_primary()); } | ||
const Vector3f &get_diagonals(uint8_t i) const { return _get_state(Priority(i)).diagonals; } | ||
const Vector3f &get_diagonals(void) const { return get_diagonals(0); } | ||
|
||
const Vector3f &get_offdiagonals(uint8_t i) const { return _state[i].offdiagonals; } | ||
const Vector3f &get_offdiagonals(void) const { return get_offdiagonals(get_primary()); } | ||
const Vector3f &get_offdiagonals(uint8_t i) const { return _get_state(Priority(i)).offdiagonals; } | ||
const Vector3f &get_offdiagonals(void) const { return get_offdiagonals(0); } | ||
|
||
// learn offsets accessor | ||
bool learn_offsets_enabled() const { return _learn == LEARN_INFLIGHT; } | ||
|
@@ -190,9 +201,7 @@ friend class AP_Compass_Backend; | |
bool use_for_yaw(uint8_t i) const; | ||
bool use_for_yaw(void) const; | ||
|
||
void set_use_for_yaw(uint8_t i, bool use) { | ||
_state[i].use_for_yaw.set(use); | ||
} | ||
void set_use_for_yaw(uint8_t i, bool use); | ||
|
||
/// Sets the local magnetic field declination. | ||
/// | ||
|
@@ -227,8 +236,8 @@ friend class AP_Compass_Backend; | |
void set_motor_compensation(uint8_t i, const Vector3f &motor_comp_factor); | ||
|
||
/// get motor compensation factors as a vector | ||
const Vector3f& get_motor_compensation(uint8_t i) const { return _state[i].motor_compensation; } | ||
const Vector3f& get_motor_compensation(void) const { return get_motor_compensation(get_primary()); } | ||
const Vector3f& get_motor_compensation(uint8_t i) const { return _get_state(Priority(i)).motor_compensation; } | ||
const Vector3f& get_motor_compensation(void) const { return get_motor_compensation(0); } | ||
|
||
/// Saves the current motor compensation x/y/z values. | ||
/// | ||
|
@@ -240,8 +249,8 @@ friend class AP_Compass_Backend; | |
/// | ||
/// @returns The current compass offsets in milligauss. | ||
/// | ||
const Vector3f &get_motor_offsets(uint8_t i) const { return _state[i].motor_offset; } | ||
const Vector3f &get_motor_offsets(void) const { return get_motor_offsets(get_primary()); } | ||
const Vector3f &get_motor_offsets(uint8_t i) const { return _get_state(Priority(i)).motor_offset; } | ||
const Vector3f &get_motor_offsets(void) const { return get_motor_offsets(0); } | ||
|
||
/// Set the throttle as a percentage from 0.0 to 1.0 | ||
/// @param thr_pct throttle expressed as a percentage from 0 to 1.0 | ||
|
@@ -263,13 +272,7 @@ friend class AP_Compass_Backend; | |
/// @returns True if compass has been configured | ||
/// | ||
bool configured(uint8_t i); | ||
bool configured(void); | ||
|
||
/// Returns the instance of the primary compass | ||
/// | ||
/// @returns the instance number of the primary compass | ||
/// | ||
uint8_t get_primary(void) const { return _primary; } | ||
bool configured(char *failure_msg, uint8_t failure_msg_len); | ||
|
||
// HIL methods | ||
void setHIL(uint8_t instance, float roll, float pitch, float yaw); | ||
|
@@ -281,11 +284,11 @@ friend class AP_Compass_Backend; | |
void set_hil_mode(void) { _hil_mode = true; } | ||
|
||
// return last update time in microseconds | ||
uint32_t last_update_usec(void) const { return _state[get_primary()].last_update_usec; } | ||
uint32_t last_update_usec(uint8_t i) const { return _state[i].last_update_usec; } | ||
uint32_t last_update_usec(void) const { return last_update_usec(0); } | ||
uint32_t last_update_usec(uint8_t i) const { return _get_state(Priority(i)).last_update_usec; } | ||
|
||
uint32_t last_update_ms(void) const { return _state[get_primary()].last_update_ms; } | ||
uint32_t last_update_ms(uint8_t i) const { return _state[i].last_update_ms; } | ||
uint32_t last_update_ms(void) const { return last_update_ms(0); } | ||
uint32_t last_update_ms(uint8_t i) const { return _get_state(Priority(i)).last_update_ms; } | ||
|
||
static const struct AP_Param::GroupInfo var_info[]; | ||
|
||
|
@@ -333,10 +336,20 @@ friend class AP_Compass_Backend; | |
|
||
private: | ||
static Compass *_singleton; | ||
|
||
// Use Priority and StateIndex typesafe index types | ||
// to distinguish between two different type of indexing | ||
// We use StateIndex for access by Backend | ||
// and Priority for access by Frontend | ||
DECLARE_TYPESAFE_INDEX(Priority, uint8_t); | ||
DECLARE_TYPESAFE_INDEX(StateIndex, uint8_t); | ||
|
||
/// Register a new compas driver, allocating an instance number | ||
/// | ||
/// @return number of compass instances | ||
uint8_t register_compass(void); | ||
/// @param dev_id Dev ID of compass to register against | ||
/// | ||
/// @return instance number saved against the dev id or first available empty instance number | ||
bugobliterator marked this conversation as resolved.
Show resolved
Hide resolved
|
||
bool register_compass(int32_t dev_id, uint8_t& instance); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the register_compass's first argument really a device id or a bus_id? should it be a uint32_t instead of an int32_t? I think this may be an existing issue with a poorly name accessor in AP_HAL::Device so I've created an issue for it here: #13575 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We store this parameter as an int32_t, so its right to be consistent across the board. |
||
|
||
// load backend drivers | ||
bool _add_backend(AP_Compass_Backend *backend); | ||
|
@@ -364,7 +377,7 @@ friend class AP_Compass_Backend; | |
|
||
#if COMPASS_CAL_ENABLED | ||
//keep track of which calibrators have been saved | ||
bool _cal_saved[COMPASS_MAX_INSTANCES]; | ||
RestrictIDTypeArray<bool, COMPASS_MAX_INSTANCES, Priority> _cal_saved; | ||
bool _cal_autosave; | ||
#endif | ||
|
||
|
@@ -405,16 +418,16 @@ friend class AP_Compass_Backend; | |
// number of registered compasses. | ||
uint8_t _compass_count; | ||
|
||
// number of unregistered compasses. | ||
uint8_t _unreg_compass_count; | ||
|
||
// settable parameters | ||
AP_Int8 _learn; | ||
|
||
// board orientation from AHRS | ||
enum Rotation _board_orientation = ROTATION_NONE; | ||
Matrix3f* _custom_rotation; | ||
|
||
// primary instance | ||
AP_Int8 _primary; | ||
|
||
// declination in radians | ||
AP_Float _declination; | ||
|
||
|
@@ -427,9 +440,6 @@ friend class AP_Compass_Backend; | |
// stores which bit is used to indicate we should log compass readings | ||
uint32_t _log_bit = -1; | ||
|
||
// used by offset correction | ||
static const uint8_t _mag_history_size = 20; | ||
|
||
// motor compensation type | ||
// 0 = disabled, 1 = enabled for throttle, 2 = enabled for current | ||
AP_Int8 _motor_comp_type; | ||
|
@@ -443,6 +453,8 @@ friend class AP_Compass_Backend; | |
struct mag_state { | ||
AP_Int8 external; | ||
bool healthy; | ||
bool registered; | ||
Compass::Priority priority; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's perhaps error prone to have a variable called "priority" and a TSIndex object called "Priority" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Priority" is not a TSIndex object, but a typedef that is created using template class TSIndex. its a type that is used to keep distinction between different types of indexes. And make it compile time strict. |
||
AP_Int8 orientation; | ||
AP_Vector3f offset; | ||
AP_Vector3f diagonals; | ||
|
@@ -453,13 +465,8 @@ friend class AP_Compass_Backend; | |
// saved to eeprom when offsets are saved allowing ram & | ||
// eeprom values to be compared as consistency check | ||
AP_Int32 dev_id; | ||
AP_Int32 expected_dev_id; | ||
int32_t detected_dev_id; | ||
|
||
AP_Int8 use_for_yaw; | ||
|
||
uint8_t mag_history_index; | ||
Vector3i mag_history[_mag_history_size]; | ||
int32_t expected_dev_id; | ||
|
||
// factors multiplied by throttle and added to compass outputs | ||
AP_Vector3f motor_compensation; | ||
|
@@ -480,7 +487,32 @@ friend class AP_Compass_Backend; | |
// accumulated samples, protected by _sem, used by AP_Compass_Backend | ||
Vector3f accum; | ||
uint32_t accum_count; | ||
} _state[COMPASS_MAX_INSTANCES]; | ||
// We only copy persistent params | ||
void copy_from(const mag_state& state); | ||
}; | ||
|
||
//Create an Array of mag_state to be accessible by StateIndex only | ||
RestrictIDTypeArray<mag_state, COMPASS_MAX_INSTANCES+1, StateIndex> _state; | ||
|
||
//Convert Priority to StateIndex | ||
StateIndex _get_state_id(Priority priority) const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we get some comments added around these new members and methods to clarify their purpose? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||
//Get State Struct by Priority | ||
const struct mag_state& _get_state(Priority priority) const { return _state[_get_state_id(priority)]; } | ||
//Convert StateIndex to Priority | ||
Priority _get_priority(StateIndex state_id) { return _state[state_id].priority; } | ||
//Method to detect compass beyond initialisation stage | ||
void _detect_runtime(void); | ||
// This method reorganises devid list to match | ||
// priority list, only call before detection at boot | ||
void _reorder_compass_params(); | ||
// Update Priority List for Mags, by default, we just | ||
// load them as they come up the first time | ||
Priority _update_priority_list(int32_t dev_id); | ||
|
||
//Create Arrays to be accessible by Priority only | ||
RestrictIDTypeArray<AP_Int8, COMPASS_MAX_INSTANCES, Priority> _use_for_yaw; | ||
RestrictIDTypeArray<AP_Int32, COMPASS_MAX_INSTANCES, Priority> _priority_did_stored_list; | ||
RestrictIDTypeArray<int32_t, COMPASS_MAX_INSTANCES, Priority> _priority_did_list; | ||
|
||
AP_Int16 _offset_max; | ||
|
||
|
@@ -491,7 +523,7 @@ friend class AP_Compass_Backend; | |
AP_Int16 _options; | ||
|
||
#if COMPASS_CAL_ENABLED | ||
CompassCalibrator _calibrator[COMPASS_MAX_INSTANCES]; | ||
RestrictIDTypeArray<CompassCalibrator, COMPASS_MAX_INSTANCES, Priority> _calibrator; | ||
#endif | ||
|
||
#if COMPASS_MOT_ENABLED | ||
|
@@ -506,7 +538,12 @@ friend class AP_Compass_Backend; | |
|
||
// mask of driver types to not load. Bit positions match DEVTYPE_ in backend | ||
AP_Int32 _driver_type_mask; | ||
|
||
|
||
#if COMPASS_MAX_UNREG_DEV | ||
// Put extra dev ids detected | ||
AP_Int32 extra_dev_id[COMPASS_MAX_UNREG_DEV]; | ||
#endif | ||
|
||
AP_Int8 _filter_range; | ||
|
||
CompassLearn *learn; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should make it more clear in all the modified accessors what the argument is. So leaving it as "i" makes it appear that it is still an instance number that is being provided but in fact it's a priority number. Perhaps the argument should be renamed to "priority" or "pri" or something that makes it more clear that we are expecting a priority number. Another way to do it would be to add a new typedef so the argument could then be something like, "get_offsets(priority_num p) const ... ".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, nevermind, I guess this "i" really is an instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its not an instance, it is priority. As far as consumers of frontend are concerned all operations are via Priority, there is no concept of instance and priority like before. It is not possible for consumers to fetch details by instance number, that is reserved only for backends. "Priority()" call is a constructor which creates Priority type instance. This method was introduced, to make it compile time illegal to fetch anything by Instance or plain int by mistake. This ensures the coder understands that a priority number is expected.