/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- // // Unit tests for the AP_Math euler code // #include #include #include FastSerialPort(Serial, 0); #ifdef DESKTOP_BUILD // all of this is needed to build with SITL #include #include #include #include #include #include #include #include #include #include #include #include Arduino_Mega_ISR_Registry isr_registry; AP_Baro_BMP085_HIL barometer; AP_Compass_HIL compass; #endif #include static float rad_diff(float rad1, float rad2) { float diff = rad1 - rad2; if (diff > PI) { diff -= 2*PI; } if (diff < -PI) { diff += 2*PI; } return fabs(diff); } static void check_result(float roll, float pitch, float yaw, float roll2, float pitch2, float yaw2) { if (isnan(roll2) || isnan(pitch2) || isnan(yaw2)) { Serial.printf("NAN eulers roll=%f pitch=%f yaw=%f\n", roll, pitch, yaw); } if (rad_diff(roll2,roll) > ToRad(179)) { // reverse all 3 roll2 += fmod(roll2+PI, 2*PI); pitch2 += fmod(pitch2+PI, 2*PI); yaw2 += fmod(yaw2+PI, 2*PI); } if (rad_diff(roll2,roll) > 0.01 || rad_diff(pitch2, pitch) > 0.01 || rad_diff(yaw2, yaw) > 0.01) { if (pitch >= PI/2 || pitch <= -PI/2 || ToDeg(rad_diff(pitch, PI/2)) < 1 || ToDeg(rad_diff(pitch, -PI/2)) < 1) { // we expect breakdown at these poles Serial.printf("breakdown eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); } else { Serial.printf("incorrect eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); } } } static void test_euler(float roll, float pitch, float yaw) { Matrix3f m; float roll2, pitch2, yaw2; m.from_euler(roll, pitch, yaw); m.to_euler(&roll2, &pitch2, &yaw2); check_result(roll, pitch, yaw, roll2, pitch2, yaw2); } #define ARRAY_LENGTH(x) (sizeof((x))/sizeof((x)[0])) static const float angles[] = { 0, PI/8, PI/4, PI/2, PI, -PI/8, -PI/4, -PI/2, -PI}; void test_matrix_eulers(void) { uint8_t i, j, k; uint8_t N = ARRAY_LENGTH(angles); Serial.println("rotation matrix unit tests\n"); for (i=0; i 0) { Serial.printf("ERROR: i=%u err=%f\n", (unsigned)i, err); } } } /* euler angle tests */ void setup(void) { Serial.begin(115200); Serial.println("euler unit tests\n"); test_conversion(0, PI, 0); test_frame_transforms(); test_conversions(); test_quaternion_eulers(); test_matrix_eulers(); test_matrix_rotate(); } void loop(void) { }