Skip to content
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: implement automatic compass orientation #8927

Merged
merged 16 commits into from
Jul 18, 2018
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
2 changes: 1 addition & 1 deletion Tools/ardupilotwaf/chibios.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def build(bld):
bld(
# build hwdef.h and apj.prototype from hwdef.dat. This is needed after a waf clean
source=bld.path.ant_glob(bld.env.HWDEF),
rule="python '${AP_HAL_ROOT}/hwdef/scripts/chibios_hwdef.py' -D '${BUILDROOT}' %s %s" % (bld.env.HWDEF, bld.env.BOOTLOADER_OPTION),
rule="python '${AP_HAL_ROOT}/hwdef/scripts/chibios_hwdef.py' -D '${BUILDROOT}' '%s' %s" % (bld.env.HWDEF, bld.env.BOOTLOADER_OPTION),
group='dynamic_sources',
target=[bld.bldnode.find_or_declare('hwdef.h'),
bld.bldnode.find_or_declare('apj.prototype'),
Expand Down
3 changes: 3 additions & 0 deletions libraries/AP_AHRS/AP_AHRS.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ class AP_AHRS
const Matrix3f& get_rotation_autopilot_body_to_vehicle_body(void) const { return _rotation_autopilot_body_to_vehicle_body; }
const Matrix3f& get_rotation_vehicle_body_to_autopilot_body(void) const { return _rotation_vehicle_body_to_autopilot_body; }

// get rotation matrix specifically from DCM backend (used for compass calibrator)
virtual const Matrix3f &get_DCM_rotation_body_to_ned(void) const = 0;

// get our current position estimate. Return true if a position is available,
// otherwise false. This call fills in lat, lng and alt
virtual bool get_position(struct Location &loc) const = 0;
Expand Down
5 changes: 5 additions & 0 deletions libraries/AP_AHRS/AP_AHRS_DCM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,11 @@ AP_AHRS_DCM::drift_correction_yaw(void)

const AP_GPS &_gps = AP::gps();

if (_compass && _compass->is_calibrating()) {
// don't do any yaw correction while calibrating
return;
}

if (AP_AHRS_DCM::use_compass()) {
/*
we are using compass for yaw
Expand Down
3 changes: 3 additions & 0 deletions libraries/AP_AHRS/AP_AHRS_DCM.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class AP_AHRS_DCM : public AP_AHRS {
return _body_dcm_matrix;
}

// get rotation matrix specifically from DCM backend (used for compass calibrator)
const Matrix3f &get_DCM_rotation_body_to_ned(void) const override { return _body_dcm_matrix; }

// return the current drift correction integrator value
const Vector3f &get_gyro_drift() const override {
return _omega_I;
Expand Down
6 changes: 6 additions & 0 deletions libraries/AP_Compass/AP_Compass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,12 @@ const AP_Param::GroupInfo Compass::var_info[] = {
// @Range: 0 100
// @Increment: 1
AP_GROUPINFO("FLTR_RNG", 34, Compass, _filter_range, HAL_COMPASS_FILTER_DEFAULT),

// @Param: AUTO_ROT
// @DisplayName: Automatically check orientation
// @Description: When enabled this will automatically check the orientation of compasses on successful completion of compass calibration. If set to 2 then external compasses will have their orientation automatically corrected.
// @Values: 0:Disabled,1:CheckOnly,2:CheckAndFix
AP_GROUPINFO("AUTO_ROT", 35, Compass, _rotate_auto, 2),

AP_GROUPEND
};
Expand Down
3 changes: 3 additions & 0 deletions libraries/AP_Compass/AP_Compass.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,9 @@ friend class AP_Compass_Backend;
// 0 = disabled, 1 = enabled for throttle, 2 = enabled for current
AP_Int8 _motor_comp_type;

// automatic compass orientation on calibration
AP_Int8 _rotate_auto;

// throttle expressed as a percentage from 0 ~ 1.0, used for motor compensation
float _thr;

Expand Down
23 changes: 19 additions & 4 deletions libraries/AP_Compass/AP_Compass_Calibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,14 @@ Compass::_start_calibration(uint8_t i, bool retry, float delay)
// lot noisier
_calibrator[i].set_tolerance(_calibration_threshold*2);
}
if (_rotate_auto) {
enum Rotation r = _state[i].external?(enum Rotation)_state[i].orientation.get():ROTATION_NONE;
if (r != ROTATION_CUSTOM) {
_calibrator[i].set_orientation(r, _state[i].external, _rotate_auto>=2);
}
}
_cal_saved[i] = false;
_calibrator[i].start(retry, delay, get_offsets_max());
_calibrator[i].start(retry, delay, get_offsets_max(), i);

// disable compass learning both for calibration and after completion
_learn.set_and_save(0);
Expand Down Expand Up @@ -147,6 +153,10 @@ Compass::_accept_calibration(uint8_t i)
set_and_save_diagonals(i,diag);
set_and_save_offdiagonals(i,offdiag);

if (_state[i].external && _rotate_auto >= 2) {
_state[i].orientation.set_and_save_ifchanged(cal.get_orientation());
}

if (!is_calibrating()) {
AP_Notify::events.compass_cal_saved = 1;
}
Expand Down Expand Up @@ -215,8 +225,9 @@ void Compass::send_mag_cal_report(mavlink_channel_t chan)
}

uint8_t cal_status = _calibrator[compass_id].get_status();
if ((cal_status == COMPASS_CAL_SUCCESS ||
cal_status == COMPASS_CAL_FAILED)) {
if (cal_status == COMPASS_CAL_SUCCESS ||
cal_status == COMPASS_CAL_FAILED ||
cal_status == COMPASS_CAL_BAD_ORIENTATION) {
float fitness = _calibrator[compass_id].get_fitness();
Vector3f ofs, diag, offdiag;
_calibrator[compass_id].get_calibration(ofs, diag, offdiag);
Expand All @@ -229,7 +240,10 @@ void Compass::send_mag_cal_report(mavlink_channel_t chan)
fitness,
ofs.x, ofs.y, ofs.z,
diag.x, diag.y, diag.z,
offdiag.x, offdiag.y, offdiag.z
offdiag.x, offdiag.y, offdiag.z,
_calibrator[compass_id].get_orientation_confidence(),
_calibrator[compass_id].get_original_orientation(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orientation 0 is a valid orientation, is there any mechanism to tell in the MAVLink2 message if we actually got an orientation sent to us? (The old_orientation and new_orientation should also have a MAVLink enum for GCS's to refer to (ideally MAV_SENSOR_ORIENTATION could be used))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only by checking the orientation_confidence is non-zero

_calibrator[compass_id].get_orientation()
);
}
}
Expand All @@ -243,6 +257,7 @@ Compass::is_calibrating() const
case COMPASS_CAL_NOT_STARTED:
case COMPASS_CAL_SUCCESS:
case COMPASS_CAL_FAILED:
case COMPASS_CAL_BAD_ORIENTATION:
break;
default:
return true;
Expand Down
61 changes: 51 additions & 10 deletions libraries/AP_Compass/AP_Compass_SITL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,41 @@ AP_Compass_SITL::AP_Compass_SITL(Compass &compass):
// save so the compass always comes up configured in SITL
save_dev_id(_compass_instance[i]);
}

// make first compass external
set_external(_compass_instance[0], true);

hal.scheduler->register_timer_process(FUNCTOR_BIND(this, &AP_Compass_SITL::_timer, void));
}
}


/*
create correction matrix for diagnonals and off-diagonals
*/
void AP_Compass_SITL::_setup_eliptical_correcion(void)
{
Vector3f diag = _sitl->mag_diag.get();
if (diag.is_zero()) {
diag(1,1,1);
}
const Vector3f &diagonals = diag;
const Vector3f &offdiagonals = _sitl->mag_offdiag;

if (diagonals == _last_dia && offdiagonals == _last_odi) {
return;
}

_eliptical_corr = Matrix3f(diagonals.x, offdiagonals.x, offdiagonals.y,
offdiagonals.x, diagonals.y, offdiagonals.z,
offdiagonals.y, offdiagonals.z, diagonals.z);
if (!_eliptical_corr.invert()) {
_eliptical_corr.identity();
}
_last_dia = diag;
_last_odi = offdiagonals;
}

void AP_Compass_SITL::_timer()
{
// TODO: Refactor delay buffer with AP_Baro_SITL.
Expand Down Expand Up @@ -73,22 +104,33 @@ void AP_Compass_SITL::_timer()
new_mag_data = buffer[best_index].data;
}

_setup_eliptical_correcion();

new_mag_data = _eliptical_corr * new_mag_data;
new_mag_data -= _sitl->mag_ofs.get();

for (uint8_t i=0; i<SITL_NUM_COMPASSES; i++) {
rotate_field(new_mag_data, _compass_instance[i]);
publish_raw_field(new_mag_data, _compass_instance[i]);
correct_field(new_mag_data, _compass_instance[i]);
Vector3f f = new_mag_data;
if (i == 0) {
// rotate the first compass, allowing for testing of external compass rotation
f.rotate_inverse((enum Rotation)_sitl->mag_orient.get());
}
rotate_field(f, _compass_instance[i]);
publish_raw_field(f, _compass_instance[i]);
correct_field(f, _compass_instance[i]);

_mag_accum[i] += f;
}

if (!_sem->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
return;
}

_mag_accum += new_mag_data;
_accum_count++;
if (_accum_count == 10) {
_mag_accum /= 2;
for (uint8_t i=0; i<SITL_NUM_COMPASSES; i++) {
_mag_accum[i] /= 2;
}
_accum_count = 5;
_has_sample = true;
}
Expand All @@ -103,14 +145,13 @@ void AP_Compass_SITL::read()
return;
}

Vector3f field(_mag_accum);
field /= _accum_count;
_mag_accum.zero();
_accum_count = 0;

for (uint8_t i=0; i<SITL_NUM_COMPASSES; i++) {
Vector3f field(_mag_accum[i]);
field /= _accum_count;
_mag_accum[i].zero();
publish_filtered_field(field, _compass_instance[i]);
}
_accum_count = 0;

_has_sample = false;
_sem->give();
Expand Down
8 changes: 6 additions & 2 deletions libraries/AP_Compass/AP_Compass_SITL.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ class AP_Compass_SITL : public AP_Compass_Backend {
bool _has_sample;
uint32_t _last_sample_time;

Vector3f _mag_accum;
Vector3f _mag_accum[SITL_NUM_COMPASSES];
uint32_t _accum_count;


void _setup_eliptical_correcion();

Matrix3f _eliptical_corr;
Vector3f _last_dia;
Vector3f _last_odi;
};
#endif // CONFIG_HAL_BOARD
Loading