mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-12 02:48:28 -04:00
AP_IMU: improved the gyro calibration code
this should give a much more accurate result
This commit is contained in:
parent
de1cfc8e34
commit
e33bb217bc
@ -56,15 +56,12 @@ AP_IMU_INS::init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(b
|
|||||||
void
|
void
|
||||||
AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(bool on))
|
AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(bool on))
|
||||||
{
|
{
|
||||||
int flashcount = 0;
|
Vector3f last_average, best_avg;
|
||||||
float adc_in;
|
float ins_gyro[3];
|
||||||
float prev[3] = {0,0,0};
|
float best_diff;
|
||||||
float total_change;
|
|
||||||
float max_offset;
|
|
||||||
float ins_gyro[6];
|
|
||||||
|
|
||||||
// cold start
|
// cold start
|
||||||
delay_cb(500);
|
delay_cb(100);
|
||||||
Serial.printf_P(PSTR("Init Gyro"));
|
Serial.printf_P(PSTR("Init Gyro"));
|
||||||
|
|
||||||
for(int c = 0; c < 25; c++) {
|
for(int c = 0; c < 25; c++) {
|
||||||
@ -80,49 +77,62 @@ AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(
|
|||||||
delay_cb(20);
|
delay_cb(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j <= 2; j++)
|
// the strategy is to average 100 points, then do it again and
|
||||||
_sensor_cal[j] = 500; // Just a large value to load prev[j] the first time
|
// see if the 2nd average is within a small margin of the first
|
||||||
|
|
||||||
do {
|
last_average.zero();
|
||||||
|
|
||||||
_ins->update();
|
// we try to get a good calibration estimate for up to 10 seconds
|
||||||
_ins->get_gyros(ins_gyro);
|
// if the gyros are stable, we should get it in 2 seconds
|
||||||
|
for (int j = 0; j <= 10; j++) {
|
||||||
|
Vector3f gyro_sum, gyro_avg, gyro_diff;
|
||||||
|
float diff_norm;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
for (int j = 0; j <= 2; j++){
|
|
||||||
prev[j] = _sensor_cal[j];
|
|
||||||
adc_in = ins_gyro[j];
|
|
||||||
_sensor_cal[j] = adc_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < 50; i++){
|
|
||||||
|
|
||||||
_ins->update();
|
|
||||||
_ins->get_gyros(ins_gyro);
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++){
|
|
||||||
adc_in = ins_gyro[j];
|
|
||||||
// filter
|
|
||||||
_sensor_cal[j] = _sensor_cal[j] * 0.9 + adc_in * 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
delay_cb(20);
|
|
||||||
if(flashcount == 5) {
|
|
||||||
Serial.printf_P(PSTR("*"));
|
Serial.printf_P(PSTR("*"));
|
||||||
FLASH_LEDS(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(flashcount >= 10) {
|
gyro_sum.zero();
|
||||||
flashcount = 0;
|
for (i=0; i<200; i++) {
|
||||||
|
_ins->update();
|
||||||
|
_ins->get_gyros(ins_gyro);
|
||||||
|
gyro_sum += Vector3f(ins_gyro[0], ins_gyro[1], ins_gyro[2]);
|
||||||
|
if (i % 40 == 20) {
|
||||||
|
FLASH_LEDS(true);
|
||||||
|
} else if (i % 40 == 20) {
|
||||||
FLASH_LEDS(false);
|
FLASH_LEDS(false);
|
||||||
}
|
}
|
||||||
flashcount++;
|
delay_cb(5);
|
||||||
|
}
|
||||||
|
gyro_avg = gyro_sum / i;
|
||||||
|
|
||||||
|
gyro_diff = last_average - gyro_avg;
|
||||||
|
diff_norm = gyro_diff.length();
|
||||||
|
|
||||||
|
if (j == 0) {
|
||||||
|
best_diff = diff_norm;
|
||||||
|
best_avg = gyro_avg;
|
||||||
|
} else if (gyro_diff.length() < ToRad(0.04)) {
|
||||||
|
// we want the average to be within 0.1 bit, which is 0.04 degrees/s
|
||||||
|
last_average = (gyro_avg * 0.5) + (last_average * 0.5);
|
||||||
|
_sensor_cal[0] = last_average.x;
|
||||||
|
_sensor_cal[1] = last_average.y;
|
||||||
|
_sensor_cal[2] = last_average.z;
|
||||||
|
// all done
|
||||||
|
return;
|
||||||
|
} else if (diff_norm < best_diff) {
|
||||||
|
best_diff = diff_norm;
|
||||||
|
best_avg = (gyro_avg * 0.5) + (last_average * 0.5);
|
||||||
|
}
|
||||||
|
last_average = gyro_avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
total_change = fabs(prev[0] - _sensor_cal[0]) + fabs(prev[1] - _sensor_cal[1]) +fabs(prev[2] - _sensor_cal[2]);
|
// we've kept the user waiting long enough - use the best pair we
|
||||||
max_offset = (_sensor_cal[0] > _sensor_cal[1]) ? _sensor_cal[0] : _sensor_cal[1];
|
// found so far
|
||||||
max_offset = (max_offset > _sensor_cal[2]) ? max_offset : _sensor_cal[2];
|
Serial.printf_P(PSTR("\ngyro did not converge: diff=%f dps\n"), ToDeg(best_diff));
|
||||||
delay_cb(500);
|
|
||||||
} while ( total_change > _gyro_total_cal_change || max_offset > _gyro_max_cal_offset);
|
_sensor_cal[0] = best_avg.x;
|
||||||
|
_sensor_cal[1] = best_avg.y;
|
||||||
|
_sensor_cal[2] = best_avg.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -75,10 +75,8 @@ private:
|
|||||||
|
|
||||||
float _calibrated(uint8_t channel, float ins_value);
|
float _calibrated(uint8_t channel, float ins_value);
|
||||||
|
|
||||||
// Gyro and Accelerometer calibration criterial
|
// Gyro and Accelerometer calibration criteria
|
||||||
//
|
//
|
||||||
static const float _gyro_total_cal_change = 4.0; // Experimentally derived - allows for some minor motion
|
|
||||||
static const float _gyro_max_cal_offset = 320.0;
|
|
||||||
static const float _accel_total_cal_change = 4.0;
|
static const float _accel_total_cal_change = 4.0;
|
||||||
static const float _accel_max_cal_offset = 250.0;
|
static const float _accel_max_cal_offset = 250.0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user