|
|
@ -56,18 +56,15 @@ 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++) { |
|
|
|
// Mostly we are just flashing the LED's here
|
|
|
|
// Mostly we are just flashing the LED's here
|
|
|
|
// to tell the user to keep the IMU still
|
|
|
|
// to tell the user to keep the IMU still
|
|
|
|
FLASH_LEDS(true); |
|
|
|
FLASH_LEDS(true); |
|
|
@ -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++){ |
|
|
|
Serial.printf_P(PSTR("*")); |
|
|
|
prev[j] = _sensor_cal[j]; |
|
|
|
|
|
|
|
adc_in = ins_gyro[j]; |
|
|
|
|
|
|
|
_sensor_cal[j] = adc_in; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 50; i++){ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gyro_sum.zero(); |
|
|
|
|
|
|
|
for (i=0; i<200; i++) { |
|
|
|
_ins->update(); |
|
|
|
_ins->update(); |
|
|
|
_ins->get_gyros(ins_gyro); |
|
|
|
_ins->get_gyros(ins_gyro); |
|
|
|
|
|
|
|
gyro_sum += Vector3f(ins_gyro[0], ins_gyro[1], ins_gyro[2]); |
|
|
|
for (int j = 0; j < 3; j++){ |
|
|
|
if (i % 40 == 20) { |
|
|
|
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("*")); |
|
|
|
|
|
|
|
FLASH_LEDS(true); |
|
|
|
FLASH_LEDS(true); |
|
|
|
} |
|
|
|
} else if (i % 40 == 20) { |
|
|
|
|
|
|
|
|
|
|
|
if(flashcount >= 10) { |
|
|
|
|
|
|
|
flashcount = 0; |
|
|
|
|
|
|
|
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 |
|
|
|