35 #include "physical_constants.h"
40 #include <QMainWindow>
41 #include <QMessageBox>
46 #include <QApplication>
49 #include "attitudesettings.h"
51 #include "homelocation.h"
52 #include "magnetometer.h"
53 #include "sensorsettings.h"
54 #include "subtrimsettings.h"
55 #include "flighttelemetrystats.h"
58 #include <Eigen/Cholesky>
63 #define META_OPERATIONS_TIMEOUT 5000
67 #define sign(x) ((x < 0) ? -1 : 1)
70 : calibrateMags(false)
71 , accelLength(GRAVITY)
87 this->calibrateAccels = calibrateAccels;
88 this->calibrateMags = calibrateMags;
101 Accels *accels = Accels::GetInstance(getObjectManager());
104 assignUpdateRate(accels, SENSOR_UPDATE_PERIOD);
109 Magnetometer *mag = Magnetometer::GetInstance(getObjectManager());
112 assignUpdateRate(mag, SENSOR_UPDATE_PERIOD);
117 Gyros *gyros = Gyros::GetInstance(getObjectManager());
120 assignUpdateRate(gyros, SENSOR_UPDATE_PERIOD);
127 Accels *accels = Accels::GetInstance(getObjectManager());
134 Magnetometer *mag = Magnetometer::GetInstance(getObjectManager());
141 Gyros *gyros = Gyros::GetInstance(getObjectManager());
156 void Calibration::assignUpdateRate(
UAVObject *obj, quint32 updatePeriod)
162 mdata.flightTelemetryUpdatePeriod =
static_cast<quint16
>(updatePeriod);
164 QTimer::singleShot(META_OPERATIONS_TIMEOUT, &loop, &QEventLoop::quit);
182 void Calibration::dataUpdated(
UAVObject *obj)
185 if (!timer.isActive()) {
190 switch (calibration_state) {
192 case SIX_POINT_WAIT1:
193 case SIX_POINT_WAIT2:
194 case SIX_POINT_WAIT3:
195 case SIX_POINT_WAIT4:
196 case SIX_POINT_WAIT5:
197 case SIX_POINT_WAIT6:
200 case YAW_ORIENTATION:
206 setMetadata(originalMetaData);
208 calibration_state = IDLE;
213 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
223 setMetadata(originalMetaData);
225 calibration_state = IDLE;
230 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
233 case SIX_POINT_COLLECT1:
238 calibration_state = SIX_POINT_WAIT2;
242 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
245 case SIX_POINT_COLLECT2:
248 calibration_state = SIX_POINT_WAIT3;
252 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
255 case SIX_POINT_COLLECT3:
258 calibration_state = SIX_POINT_WAIT4;
262 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
265 case SIX_POINT_COLLECT4:
268 calibration_state = SIX_POINT_WAIT5;
272 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
275 case SIX_POINT_COLLECT5:
278 calibration_state = SIX_POINT_WAIT6;
282 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
285 case SIX_POINT_COLLECT6:
293 calibration_state = IDLE;
294 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
302 setMetadata(originalMetaData);
312 SensorSettings *sensorSettings = SensorSettings::GetInstance(getObjectManager());
313 SensorSettings::DataFields sensorSettingsData = sensorSettings->getData();
316 QString accelCalibrationResults =
"";
317 QString magCalibrationResults =
"";
318 if (calibrateAccels ==
true) {
319 accelCalibrationResults =
320 QString(tr(
"Accelerometer bias, in [m/s^2]: x=%1, y=%2, z=%3\n"))
321 .arg(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X], -9)
322 .arg(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y], -9)
323 .arg(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z], -9)
324 + QString(tr(
"Accelerometer scale, in [-]: x=%1, y=%2, z=%3\n"))
325 .arg(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X], -9)
326 .arg(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y], -9)
327 .arg(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z], -9);
329 if (calibrateMags ==
true) {
330 magCalibrationResults =
331 QString(tr(
"Magnetometer bias, in [mG]: x=%1, y=%2, z=%3\n"))
332 .arg(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X], -9)
333 .arg(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y], -9)
334 .arg(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z], -9)
335 + QString(tr(
"Magnetometer scale, in [-]: x=%4, y=%5, z=%6"))
336 .arg(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X], -9)
337 .arg(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y], -9)
338 .arg(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z], -9);
343 + accelCalibrationResults + QString(
"\n")
344 + magCalibrationResults);
351 tr(
"Acceleromter calibration failed. Original values have been written "
352 "back to device. Perhaps you moved too much during the calculation? "
353 "Please repeat calibration."));
356 tr(
"Magnetometer calibration failed. Original values have been written "
357 "back to device. Perhaps you performed the calibration near iron? "
358 "Please repeat calibration."));
368 setMetadata(originalMetaData);
370 calibration_state = IDLE;
387 void Calibration::timeout()
390 setMetadata(originalMetaData);
392 switch (calibration_state) {
396 case YAW_ORIENTATION:
399 calibration_state = IDLE;
407 calibration_state = IDLE;
411 case SIX_POINT_WAIT1:
412 case SIX_POINT_WAIT2:
413 case SIX_POINT_WAIT3:
414 case SIX_POINT_WAIT4:
415 case SIX_POINT_WAIT5:
416 case SIX_POINT_WAIT6:
419 case SIX_POINT_COLLECT1:
420 case SIX_POINT_COLLECT2:
421 case SIX_POINT_COLLECT3:
422 case SIX_POINT_COLLECT4:
423 case SIX_POINT_COLLECT5:
424 case SIX_POINT_COLLECT6:
430 calibration_state = IDLE;
436 calibration_state = IDLE;
445 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
448 tr(
"Calibration failed"),
449 tr(
"Calibration timed out before receiving required updates."));
457 accel_accum_x.clear();
458 accel_accum_y.clear();
459 accel_accum_z.clear();
461 calibration_state = YAW_ORIENTATION;
471 tr(
"Pitch vehicle forward approximately 30 degrees. Ensure it absolutely does not roll"));
474 timer.setSingleShot(
true);
475 timer.start(8000 + (NUM_SENSOR_UPDATES_YAW_ORIENTATION * SENSOR_UPDATE_PERIOD));
476 connect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
489 zeroVertical =
false;
496 void Calibration::doStartLeveling()
498 accel_accum_x.clear();
499 accel_accum_y.clear();
500 accel_accum_z.clear();
501 gyro_accum_x.clear();
502 gyro_accum_y.clear();
503 gyro_accum_z.clear();
504 gyro_accum_temp.clear();
507 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
508 Q_ASSERT(attitudeSettings);
509 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
510 attitudeSettingsData.BiasCorrectGyro = AttitudeSettings::BIASCORRECTGYRO_FALSE;
511 attitudeSettings->setData(attitudeSettingsData);
512 attitudeSettings->updated();
514 calibration_state = LEVELING;
526 timer.setSingleShot(
true);
527 timer.start(8000 + (NUM_SENSOR_UPDATES_LEVELING * SENSOR_UPDATE_PERIOD));
528 connect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
540 SensorSettings *sensorSettings = SensorSettings::GetInstance(getObjectManager());
541 Q_ASSERT(sensorSettings);
542 SensorSettings::DataFields sensorSettingsData = sensorSettings->getData();
545 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
546 Q_ASSERT(attitudeSettings);
547 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
549 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL] *
DEG2RAD / 100.0,
550 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH] *
DEG2RAD / 100.0,
551 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] *
DEG2RAD / 100.0
553 Euler2R(rpy, boardRotationMatrix);
556 if (calibrateAccels) {
557 initialAccelsScale[0] = sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X];
558 initialAccelsScale[1] = sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y];
559 initialAccelsScale[2] = sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z];
560 initialAccelsBias[0] = sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X];
561 initialAccelsBias[1] = sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y];
562 initialAccelsBias[2] = sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z];
565 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X] = 1.0;
566 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y] = 1.0;
567 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z] = 1.0;
568 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X] = 0.0;
569 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y] = 0.0;
570 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z] = 0.0;
571 sensorSettingsData.ZAccelOffset = 0.0;
576 initialMagsScale[0] = sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X];
577 initialMagsScale[1] = sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y];
578 initialMagsScale[2] = sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z];
579 initialMagsBias[0] = sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X];
580 initialMagsBias[1] = sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y];
581 initialMagsBias[2] = sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z];
584 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X] = 1;
585 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y] = 1;
586 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z] = 1;
587 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X] = 0;
588 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y] = 0;
589 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z] = 0;
592 sensorSettings->setData(sensorSettingsData);
595 accel_accum_x.clear();
596 accel_accum_y.clear();
597 accel_accum_z.clear();
603 QThread::usleep(100000);
622 calibration_state = SIX_POINT_WAIT1;
640 setMetadata(originalMetaData);
642 calibration_state = IDLE;
647 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
657 switch (calibration_state) {
658 case SIX_POINT_WAIT1:
661 calibration_state = SIX_POINT_COLLECT1;
663 case SIX_POINT_WAIT2:
666 calibration_state = SIX_POINT_COLLECT2;
668 case SIX_POINT_WAIT3:
671 calibration_state = SIX_POINT_COLLECT3;
673 case SIX_POINT_WAIT4:
676 calibration_state = SIX_POINT_COLLECT4;
678 case SIX_POINT_WAIT5:
681 calibration_state = SIX_POINT_COLLECT5;
683 case SIX_POINT_WAIT6:
686 calibration_state = SIX_POINT_COLLECT6;
695 timer.setSingleShot(
true);
696 timer.start(8000 + (NUM_SENSOR_UPDATES_SIX_POINT * SENSOR_UPDATE_PERIOD));
697 connect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
705 gyro_accum_x.clear();
706 gyro_accum_y.clear();
707 gyro_accum_z.clear();
708 gyro_accum_temp.clear();
711 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
712 Q_ASSERT(attitudeSettings);
713 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
714 attitudeSettingsData.BiasCorrectGyro = AttitudeSettings::BIASCORRECTGYRO_FALSE;
716 attitudeSettings->setData(attitudeSettingsData);
717 attitudeSettings->updated();
721 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL] *
DEG2RAD / 100.0,
722 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH] *
DEG2RAD / 100.0,
723 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] *
DEG2RAD / 100.0
725 Euler2R(rpy, boardRotationMatrix);
727 calibration_state = GYRO_TEMP_CAL;
734 emit
showTempCalMessage(tr(
"Leave board flat and very still while it changes temperature"));
738 timer.setSingleShot(
true);
739 timer.start(1800000);
740 connect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
748 if (calibration_state == GYRO_TEMP_CAL) {
749 qDebug() <<
"Accepting";
752 setMetadata(originalMetaData);
754 calibration_state = IDLE;
760 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
771 if (calibration_state == GYRO_TEMP_CAL) {
772 qDebug() <<
"Canceling";
775 setMetadata(originalMetaData);
778 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
779 Q_ASSERT(attitudeSettings);
780 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
781 attitudeSettings->setData(attitudeSettingsData);
782 attitudeSettings->updated();
783 QThread::usleep(100000);
788 calibration_state = IDLE;
794 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
805 min_temperature_range = r;
815 Accels *accels = Accels::GetInstance(getObjectManager());
818 if (obj->
getObjID() == Accels::OBJID) {
819 Accels::DataFields accelsData = accels->getData();
820 accel_accum_x.append(accelsData.x);
821 accel_accum_y.append(accelsData.y);
822 accel_accum_z.append(accelsData.z);
827 / NUM_SENSOR_UPDATES_YAW_ORIENTATION);
830 if (accel_accum_x.size() >= NUM_SENSOR_UPDATES_YAW_ORIENTATION) {
832 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
835 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
836 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
848 psi = atan2(a_body[1], -a_body[0]);
850 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] +=
854 while (attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW]
856 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] -= 360 * 100;
857 while (attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] < -180 * 100)
858 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] += 360 * 100;
860 attitudeSettings->setData(attitudeSettingsData);
861 attitudeSettings->updated();
878 Accels *accels = Accels::GetInstance(getObjectManager());
879 Gyros *gyros = Gyros::GetInstance(getObjectManager());
882 if (obj->
getObjID() == Accels::OBJID) {
883 Accels::DataFields accelsData = accels->getData();
884 accel_accum_x.append(accelsData.x);
885 accel_accum_y.append(accelsData.y);
886 accel_accum_z.append(accelsData.z);
887 }
else if (obj->
getObjID() == Gyros::OBJID) {
888 Gyros::DataFields gyrosData = gyros->getData();
889 gyro_accum_x.append(gyrosData.x);
890 gyro_accum_y.append(gyrosData.y);
891 gyro_accum_z.append(gyrosData.z);
892 gyro_accum_temp.append(gyrosData.temperature);
897 / NUM_SENSOR_UPDATES_LEVELING);
900 if (accel_accum_x.size() >= NUM_SENSOR_UPDATES_LEVELING
901 && gyro_accum_x.size() >= NUM_SENSOR_UPDATES_LEVELING) {
903 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
905 double x_gyro_bias =
listMean(gyro_accum_x);
906 double y_gyro_bias =
listMean(gyro_accum_y);
907 double z_gyro_bias =
listMean(gyro_accum_z);
908 double temp =
listMean(gyro_accum_temp);
911 AttitudeSettings::DataFields attitudeSettingsData =
912 AttitudeSettings::GetInstance(getObjectManager())->getData();
913 SensorSettings::DataFields sensorSettingsData =
914 SensorSettings::GetInstance(getObjectManager())->getData();
921 double rpy[3] = { attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL]
923 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH]
925 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW]
931 double psi, theta, phi;
934 psi = attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] *
DEG2RAD
940 phi = atan2(-a_sensor[1], -a_sensor[2]);
941 theta = atan(-a_sensor[0] / (sin(phi) * a_sensor[1] + cos(phi) * a_sensor[2]));
943 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL] =
944 static_cast<qint16
>(phi *
RAD2DEG * 100.0);
945 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH] =
946 static_cast<qint16
>(theta *
RAD2DEG * 100.0);
954 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_ROLL] *
DEG2RAD
956 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_PITCH] *
DEG2RAD
958 attitudeSettingsData.BoardRotation[AttitudeSettings::BOARDROTATION_YAW] *
DEG2RAD
961 double a_body_new[3];
966 sensorSettingsData.ZAccelOffset += -(a_body_new[2] + accelLength);
970 double gyro_sensor[3];
971 double gyro_body[3] = { x_gyro_bias, y_gyro_bias, z_gyro_bias };
975 sensorSettingsData.XGyroTempCoeff[0] =
976 static_cast<float>(gyro_sensor[0] - temp * sensorSettingsData.XGyroTempCoeff[1]
977 - pow(temp, 2) * sensorSettingsData.XGyroTempCoeff[2]
978 - pow(temp, 3) * sensorSettingsData.XGyroTempCoeff[3]);
979 sensorSettingsData.YGyroTempCoeff[0] =
980 static_cast<float>(gyro_sensor[1] - temp * sensorSettingsData.YGyroTempCoeff[1]
981 - pow(temp, 2) * sensorSettingsData.YGyroTempCoeff[2]
982 - pow(temp, 3) * sensorSettingsData.YGyroTempCoeff[3]);
983 sensorSettingsData.ZGyroTempCoeff[0] =
984 static_cast<float>(gyro_sensor[2] - temp * sensorSettingsData.ZGyroTempCoeff[1]
985 - pow(temp, 2) * sensorSettingsData.ZGyroTempCoeff[2]
986 - pow(temp, 3) * sensorSettingsData.ZGyroTempCoeff[3]);
987 SensorSettings::GetInstance(getObjectManager())->setData(sensorSettingsData);
991 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
992 Q_ASSERT(attitudeSettings);
993 attitudeSettingsData.BiasCorrectGyro = AttitudeSettings::BIASCORRECTGYRO_TRUE;
994 attitudeSettings->setData(attitudeSettingsData);
995 attitudeSettings->updated();
998 SubTrimSettings *trimSettings = SubTrimSettings::GetInstance(getObjectManager());
999 Q_ASSERT(trimSettings);
1000 SubTrimSettings::DataFields trim = trimSettings->getData();
1003 trimSettings->setData(trim);
1021 Q_ASSERT(position >= 1 && position <= 6);
1024 if (calibrateAccels && obj->
getObjID() == Accels::OBJID) {
1025 Accels *accels = Accels::GetInstance(getObjectManager());
1027 Accels::DataFields accelsData = accels->getData();
1029 accel_accum_x.append(accelsData.x);
1030 accel_accum_y.append(accelsData.y);
1031 accel_accum_z.append(accelsData.z);
1034 if (calibrateMags && obj->
getObjID() == Magnetometer::OBJID) {
1035 Magnetometer *mag = Magnetometer::GetInstance(getObjectManager());
1037 Magnetometer::DataFields magData = mag->getData();
1039 mag_accum_x.append(magData.x);
1040 mag_accum_y.append(magData.y);
1041 mag_accum_z.append(magData.z);
1045 int progress_percentage;
1046 if (calibrateAccels && !calibrateMags)
1047 progress_percentage = (100 * accel_accum_x.size()) / NUM_SENSOR_UPDATES_SIX_POINT;
1048 else if (!calibrateAccels && calibrateMags)
1049 progress_percentage = (100 * mag_accum_x.size()) / NUM_SENSOR_UPDATES_SIX_POINT;
1051 progress_percentage = (100 * std::min(mag_accum_x.size(), accel_accum_x.size()))
1052 / NUM_SENSOR_UPDATES_SIX_POINT;
1056 if ((!calibrateAccels || accel_accum_x.size() >= NUM_SENSOR_UPDATES_SIX_POINT)
1057 && (!calibrateMags || mag_accum_x.size() >= NUM_SENSOR_UPDATES_SIX_POINT)) {
1060 if (calibrateAccels) {
1064 double accel_sensor[3];
1065 rotate_vector(boardRotationMatrix, accel_body, accel_sensor,
false);
1067 accel_data_x[position] = accel_sensor[0];
1068 accel_data_y[position] = accel_sensor[1];
1069 accel_data_z[position] = accel_sensor[2];
1070 accel_accum_x.clear();
1071 accel_accum_y.clear();
1072 accel_accum_z.clear();
1076 if (calibrateMags) {
1080 double mag_sensor[3];
1081 rotate_vector(boardRotationMatrix, mag_body, mag_sensor,
false);
1083 mag_data_x[position] = mag_sensor[0];
1084 mag_data_y[position] = mag_sensor[1];
1085 mag_data_z[position] = mag_sensor[2];
1086 mag_accum_x.clear();
1087 mag_accum_y.clear();
1088 mag_accum_z.clear();
1116 if (obj->
getObjID() == Gyros::OBJID) {
1117 Gyros *gyros = Gyros::GetInstance(getObjectManager());
1119 Gyros::DataFields gyrosData = gyros->getData();
1120 double gyros_body[3] = { gyrosData.x, gyrosData.y, gyrosData.z };
1121 double gyros_sensor[3];
1122 rotate_vector(boardRotationMatrix, gyros_body, gyros_sensor,
false);
1123 gyro_accum_x.append(gyros_sensor[0]);
1124 gyro_accum_y.append(gyros_sensor[1]);
1125 gyro_accum_z.append(gyros_sensor[2]);
1126 gyro_accum_temp.append(gyrosData.temperature);
1129 auto m = std::minmax_element(gyro_accum_temp.begin(), gyro_accum_temp.end());
1130 double range = *
m.second - *
m.first;
1133 if ((gyro_accum_temp.size() % 10) == 0) {
1138 if (range >= min_temperature_range) {
1150 int n_samples = gyro_accum_temp.size();
1153 Eigen::Matrix<double, Eigen::Dynamic, 4> X(n_samples, 4);
1156 Eigen::Matrix<double, Eigen::Dynamic, 3> Y(n_samples, 3);
1158 for (
int i = 0;
i < n_samples; ++
i) {
1160 X(
i, 1) = gyro_accum_temp[
i];
1161 X(
i, 2) = pow(gyro_accum_temp[
i], 2);
1162 X(i, 3) = pow(gyro_accum_temp[i], 3);
1163 Y(i, 0) = gyro_accum_x[
i];
1164 Y(i, 1) = gyro_accum_y[
i];
1165 Y(i, 2) = gyro_accum_z[
i];
1170 Eigen::Matrix<double, 4, 3> result = (X.transpose() * X).ldlt().solve(X.transpose() * Y);
1174 xCoeffs.append(result(0, 0));
1175 xCoeffs.append(result(1, 0));
1176 xCoeffs.append(result(2, 0));
1177 xCoeffs.append(result(3, 0));
1179 yCoeffs.append(result(0, 1));
1180 yCoeffs.append(result(1, 1));
1181 yCoeffs.append(result(2, 1));
1182 yCoeffs.append(result(3, 1));
1184 zCoeffs.append(result(0, 2));
1185 zCoeffs.append(result(1, 2));
1186 zCoeffs.append(result(2, 2));
1187 zCoeffs.append(result(3, 2));
1190 xCurve->
plotData(gyro_accum_temp, gyro_accum_x, xCoeffs);
1192 yCurve->
plotData(gyro_accum_temp, gyro_accum_y, yCoeffs);
1194 zCurve->
plotData(gyro_accum_temp, gyro_accum_z, zCoeffs);
1205 disconnect(&timer, &QTimer::timeout,
this, &Calibration::timeout);
1208 AttitudeSettings *attitudeSettings = AttitudeSettings::GetInstance(getObjectManager());
1209 Q_ASSERT(attitudeSettings);
1210 AttitudeSettings::DataFields attitudeSettingsData = attitudeSettings->getData();
1211 attitudeSettingsData.BiasCorrectGyro = AttitudeSettings::BIASCORRECTGYRO_TRUE;
1212 attitudeSettings->setData(attitudeSettingsData);
1213 attitudeSettings->updated();
1215 int n_samples = gyro_accum_temp.size();
1218 Eigen::Matrix<double, Eigen::Dynamic, 4> X(n_samples, 4);
1221 Eigen::Matrix<double, Eigen::Dynamic, 3> Y(n_samples, 3);
1223 for (
int i = 0;
i < n_samples; ++
i) {
1225 X(
i, 1) = gyro_accum_temp[
i];
1226 X(
i, 2) = pow(gyro_accum_temp[
i], 2);
1227 X(i, 3) = pow(gyro_accum_temp[i], 3);
1228 Y(i, 0) = gyro_accum_x[
i];
1229 Y(i, 1) = gyro_accum_y[
i];
1230 Y(i, 2) = gyro_accum_z[
i];
1235 Eigen::Matrix<double, 4, 3> result = (X.transpose() * X).ldlt().solve(X.transpose() * Y);
1237 std::stringstream str;
1238 str << result.format(Eigen::IOFormat(4, 0,
", ",
"\n",
"[",
"]"));
1239 qDebug().noquote() <<
"Solution:\n" << QString::fromStdString(str.str());
1242 SensorSettings *sensorSettings = SensorSettings::GetInstance(getObjectManager());
1243 Q_ASSERT(sensorSettings);
1244 SensorSettings::DataFields sensorSettingsData = sensorSettings->getData();
1245 sensorSettingsData.XGyroTempCoeff[0] =
static_cast<float>(result(0, 0));
1246 sensorSettingsData.XGyroTempCoeff[1] =
static_cast<float>(result(1, 0));
1247 sensorSettingsData.XGyroTempCoeff[2] =
static_cast<float>(result(2, 0));
1248 sensorSettingsData.XGyroTempCoeff[3] =
static_cast<float>(result(3, 0));
1249 sensorSettingsData.YGyroTempCoeff[0] =
static_cast<float>(result(0, 1));
1250 sensorSettingsData.YGyroTempCoeff[1] =
static_cast<float>(result(1, 1));
1251 sensorSettingsData.YGyroTempCoeff[2] =
static_cast<float>(result(2, 1));
1252 sensorSettingsData.YGyroTempCoeff[3] =
static_cast<float>(result(3, 1));
1253 sensorSettingsData.ZGyroTempCoeff[0] =
static_cast<float>(result(0, 2));
1254 sensorSettingsData.ZGyroTempCoeff[1] =
static_cast<float>(result(1, 2));
1255 sensorSettingsData.ZGyroTempCoeff[2] =
static_cast<float>(result(2, 2));
1256 sensorSettingsData.ZGyroTempCoeff[3] =
static_cast<float>(result(3, 2));
1257 sensorSettings->setData(sensorSettingsData);
1261 xCoeffs.append(result(0, 0));
1262 xCoeffs.append(result(1, 0));
1263 xCoeffs.append(result(2, 0));
1264 xCoeffs.append(result(3, 0));
1266 yCoeffs.append(result(0, 1));
1267 yCoeffs.append(result(1, 1));
1268 yCoeffs.append(result(2, 1));
1269 yCoeffs.append(result(3, 1));
1271 zCoeffs.append(result(0, 2));
1272 zCoeffs.append(result(1, 2));
1273 zCoeffs.append(result(2, 2));
1274 zCoeffs.append(result(3, 2));
1277 xCurve->
plotData(gyro_accum_temp, gyro_accum_x, xCoeffs);
1279 yCurve->
plotData(gyro_accum_temp, gyro_accum_y, yCoeffs);
1281 zCurve->
plotData(gyro_accum_temp, gyro_accum_z, zCoeffs);
1322 SensorSettings *sensorSettings = SensorSettings::GetInstance(getObjectManager());
1323 Q_ASSERT(sensorSettings);
1324 SensorSettings::DataFields sensorSettingsData = sensorSettings->getData();
1326 bool good_calibration =
true;
1329 if (calibrateAccels) {
1330 good_calibration =
true;
1332 qDebug() <<
"Accel measurements";
1333 for (
int i = 0;
i < 6;
i++)
1334 qDebug() << accel_data_x[
i] <<
", " << accel_data_y[
i] <<
", " << accel_data_z[
i]
1341 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X] += (-sign(S[0]) * b[0]);
1342 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y] += (-sign(S[1]) * b[1]);
1343 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z] += (-sign(S[2]) * b[2]);
1345 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X] *= fabs(S[0]);
1346 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y] *= fabs(S[1]);
1347 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z] *= fabs(S[2]);
1351 !std::isnan(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X]);
1353 !std::isnan(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y]);
1355 !std::isnan(sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z]);
1356 good_calibration &= !std::isnan(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X]);
1357 good_calibration &= !std::isnan(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y]);
1358 good_calibration &= !std::isnan(sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z]);
1361 if ((S[0] + S[1] + S[2]) < 0.0001) {
1362 good_calibration =
false;
1365 if (good_calibration) {
1366 qDebug() <<
"Accel bias: " << sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X]
1367 <<
" " << sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y] <<
" "
1368 << sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z];
1374 if (calibrateMags) {
1375 good_calibration =
true;
1377 qDebug() <<
"Mag measurements";
1378 for (
int i = 0;
i < 6;
i++)
1379 qDebug() << mag_data_x[
i] <<
", " << mag_data_y[
i] <<
", " << mag_data_z[
i] <<
";";
1383 double m_x = 0, m_y = 0, m_z = 0, len = 0;
1384 for (
int i = 0;
i < 6;
i++) {
1385 m_x += mag_data_x[
i];
1386 m_y += mag_data_x[
i];
1387 m_z += mag_data_x[
i];
1392 for (
int i = 0;
i < 6;
i++) {
1393 len += sqrt(pow(mag_data_x[
i] - m_x, 2) + pow(mag_data_y[
i] - m_y, 2)
1394 + pow(mag_data_z[
i] - m_z, 2));
1403 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X] += (-sign(S[0]) * b[0]);
1404 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y] += (-sign(S[1]) * b[1]);
1405 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z] += (-sign(S[2]) * b[2]);
1406 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X] *= fabs(S[0]);
1407 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y] *= fabs(S[1]);
1408 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z] *= fabs(S[2]);
1411 good_calibration &= !std::isnan(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X]);
1412 good_calibration &= !std::isnan(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y]);
1413 good_calibration &= !std::isnan(sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z]);
1414 good_calibration &= !std::isnan(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X]);
1415 good_calibration &= !std::isnan(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y]);
1416 good_calibration &= !std::isnan(sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z]);
1419 if ((S[0] + S[1] + S[2]) < 0.0001) {
1420 good_calibration =
false;
1423 if (good_calibration) {
1424 qDebug() <<
"Mag bias: " << sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X] <<
" "
1425 << sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y] <<
" "
1426 << sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z];
1433 sensorSettings->setData(sensorSettingsData);
1448 SensorSettings *sensorSettings = SensorSettings::GetInstance(getObjectManager());
1449 Q_ASSERT(sensorSettings);
1450 SensorSettings::DataFields sensorSettingsData = sensorSettings->getData();
1452 if (calibrateAccels) {
1453 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_X] =
1454 static_cast<float>(initialAccelsScale[0]);
1455 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Y] =
1456 static_cast<float>(initialAccelsScale[1]);
1457 sensorSettingsData.AccelScale[SensorSettings::ACCELSCALE_Z] =
1458 static_cast<float>(initialAccelsScale[2]);
1459 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_X] =
1460 static_cast<float>(initialAccelsBias[0]);
1461 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Y] =
1462 static_cast<float>(initialAccelsBias[1]);
1463 sensorSettingsData.AccelBias[SensorSettings::ACCELBIAS_Z] =
1464 static_cast<float>(initialAccelsBias[2]);
1467 if (calibrateMags) {
1469 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_X] =
1470 static_cast<float>(initialMagsScale[0]);
1471 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Y] =
1472 static_cast<float>(initialMagsScale[1]);
1473 sensorSettingsData.MagScale[SensorSettings::MAGSCALE_Z] =
1474 static_cast<float>(initialMagsScale[2]);
1475 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_X] =
1476 static_cast<float>(initialMagsBias[0]);
1477 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Y] =
1478 static_cast<float>(initialMagsBias[1]);
1479 sensorSettingsData.MagBias[SensorSettings::MAGBIAS_Z] =
1480 static_cast<float>(initialMagsBias[2]);
1483 sensorSettings->setData(sensorSettingsData);
1484 sensorSettings->updated();
1495 double sF = sin(rpy[0]), cF = cos(rpy[0]);
1496 double sT = sin(rpy[1]), cT = cos(rpy[1]);
1497 double sP = sin(rpy[2]), cP = cos(rpy[2]);
1499 Rbe[0][0] = cT * cP;
1500 Rbe[0][1] = cT * sP;
1502 Rbe[1][0] = sF * sT * cP - cF * sP;
1503 Rbe[1][1] = sF * sT * sP + cF * cP;
1504 Rbe[1][2] = cT * sF;
1505 Rbe[2][0] = cF * sT * cP + sF * sP;
1506 Rbe[2][1] = cF * sT * sP - sF * cP;
1507 Rbe[2][2] = cT * cF;
1518 bool transpose =
true)
1521 vec_out[0] = R[0][0] * vec[0] + R[0][1] * vec[1] + R[0][2] * vec[2];
1522 vec_out[1] = R[1][0] * vec[0] + R[1][1] * vec[1] + R[1][2] * vec[2];
1523 vec_out[2] = R[2][0] * vec[0] + R[2][1] * vec[1] + R[2][2] * vec[2];
1525 vec_out[0] = R[0][0] * vec[0] + R[1][0] * vec[1] + R[2][0] * vec[2];
1526 vec_out[1] = R[0][1] * vec[0] + R[1][1] * vec[1] + R[2][1] * vec[2];
1527 vec_out[2] = R[0][2] * vec[0] + R[1][2] * vec[1] + R[2][2] * vec[2];
1552 double S[3],
double b[3])
1554 Eigen::Matrix<double, 5, 5> A;
1555 Eigen::Matrix<double, 5, 1> f;
1556 double xp, yp, zp, Sx;
1565 for (
int i = 0;
i < 5;
i++) {
1566 A(
i, 0) = 2.0 * (x[
i + 1] - x[
i]);
1567 A(
i, 1) = y[
i + 1] * y[
i + 1] - y[
i] * y[
i];
1568 A(
i, 2) = 2.0 * (y[
i + 1] - y[
i]);
1569 A(
i, 3) = z[
i + 1] * z[
i + 1] - z[
i] * z[
i];
1570 A(
i, 4) = 2.0 * (z[
i + 1] - z[
i]);
1571 f[
i] = x[
i] * x[
i] - x[
i + 1] * x[
i + 1];
1575 Eigen::Matrix<double, 5, 1> c = A.fullPivHouseholderQr().solve(f);
1582 Sx = sqrt(ConstMag * ConstMag
1583 / (xp * xp + 2 * c[0] * xp + c[0] * c[0] + c[1] * yp * yp + 2 * c[2] * yp
1584 + c[2] * c[2] / c[1] + c[3] * zp * zp + 2 * c[4] * zp + c[4] * c[4] / c[3]));
1588 S[1] = sqrt(c[1] * Sx * Sx);
1589 b[1] = c[2] * Sx * Sx / S[1];
1590 S[2] = sqrt(c[3] * Sx * Sx);
1591 b[2] = c[4] * Sx * Sx / S[2];
1596 void Calibration::setMetadata(QMap<QString, UAVObject::Metadata> metaList)
1599 QTimer::singleShot(META_OPERATIONS_TIMEOUT, &loop, &QEventLoop::quit);
void updatePlane(int position)
Change the UAV visualization.
virtual void setMetadata(const Metadata &mdata)=0
bool storeTempCalMeasurement(UAVObject *obj)
Store a sample for temperature compensation.
void doSaveSixPointPosition()
Indicates UAV is in a position to collect data during 6pt calibration.
void calibrationCompleted()
Indicate that a calibration process has successfully completed and the results saved to UAVO...
void completedMetadataWrite(bool)
void doStartSixPoint()
Start the six point calibration routine.
static double listMean(QList< double > list)
Compute the mean value of a list.
Core plugin system that manages the plugins, their life cycle and their registered objects...
int computeScaleBias()
Computes the scale and bias for the accelerometer and mag.
void setTempCalRange(int r)
Set temperature calibration range.
bool storeLevelingMeasurement(UAVObject *obj)
Store leveling sample and compute level if finished.
void showLevelingMessage(QString message)
Show an instruction to the user for leveling.
void plotData(QList< double > temp, QList< double > gyro, QList< double > coefficients)
Show calibration data for one of the channels.
void tempCalProgressChanged(int)
Indicate what the progress is for temperature calibration.
void objectUpdated(UAVObject *obj)
Signal sent whenever any field of the object is updated.
QMap< QString, UAVObject::Metadata > readAllNonSettingsMetadata()
UAVObjectUtilManager::readAllNonSettingsMetadata Convenience function for calling readMetadata...
static void SetFlightTelemetryUpdateMode(Metadata &meta, UpdateMode val)
void connectSensor(sensor_type sensor, bool connect)
Connect and speed up or disconnect a sensor.
virtual Metadata getMetadata()=0
int SixPointInConstFieldCal(double ConstMag, double x[6], double y[6], double z[6], double S[3], double b[3])
void levelingProgressChanged(int)
Indicate what the progress is for leveling.
UAVMetaObject * getMetaObject()
bool setAllNonSettingsMetadata(QMap< QString, UAVObject::Metadata >)
UAVObjectUtilManager::setAllNonSettingsMetadata Convenience function for calling setMetadata.
void initialize(bool calibrateAccels, bool calibrateMags)
Calibration::initialize Configure whether to calibrate the magnetometer and/or accelerometer during 6...
void showYawOrientationMessage(QString message)
Show an instruction to the user for yaw orientation.
void doStartOrientation()
Start collecting data while vehicle is in pure pitch.
void doStartNoBiasLeveling()
Start collecting data while vehicle is level.
void showTempCalMessage(QString message)
Show an instruction or message from temperature calibration.
void transactionCompleted(UAVObject *obj, bool success)
transactionCompleted. Triggered by a call to emitTransactionCompleted - done in telemetry.cpp whenever a transaction finishes.
static ICore * instance()
void sixPointProgressChanged(int)
Indicate what the progress is for six point collection.
void rotate_vector(double R[3][3], const double vec[3], double vec_out[3], bool transpose)
Rotate a vector by the rotation matrix, optionally trasposing.
calibrationSuccessMessages
void doCancelSixPoint()
Cancels the six point calibration routine.
void showSixPointMessage(QString message)
Show an instruction to the user for six point calibration.
void Euler2R(double rpy[3], double Rbe[3][3])
Compute a rotation matrix from a set of euler angles.
void doCancelTempCalPoint()
Cancels the temperature calibration routine.
void yawOrientationProgressChanged(int)
Indicate what the progress is for yaw orientation.
bool storeSixPointMeasurement(UAVObject *obj, int position)
Store a measurement at this position and indicate if it is the last one.
Gui-less support class for calibration.
void doStartBiasAndLeveling()
Start collecting data while vehicle is level.
void updateTempCompCalibrationDisplay()
Update the graphs with the temperature compensation.
void toggleSavePosition(bool enable)
Indicate whether to enable or disable controls.
void calibrationBusy(bool busy)
Indicate whether the calibration is busy.
void doAcceptTempCal()
Accept gyro temp calibration data.
void toggleControls(bool enable)
Indicate whether to enable or disable controls.
int computeTempCal()
Compute temperature compensation factors.
void configureTempCurves(TempCompCurve *x, TempCompCurve *y, TempCompCurve *z)
Set up the curves.
bool storeYawOrientationMeasurement(UAVObject *obj)
Store yaw orientation sample and compute orientation if finished.
void resetSensorCalibrationToOriginalValues()
Reset sensor settings to pre-calibration values.
void doStartTempCal()
Start collecting gyro temp calibration data.