Mercurial > public > hwos_code
comparison src/Tests/compass_test.cpp @ 282:7d9edd3b8c86
Make a more compact COMPASS calibration code (<7KB), and add more tests.
| author | jDG |
|---|---|
| date | Fri, 22 May 2015 14:50:40 +0200 |
| parents | |
| children | cd2320cd6f9a |
comparison
equal
deleted
inserted
replaced
| 281:eb758a5b44eb | 282:7d9edd3b8c86 |
|---|---|
| 1 ////////////////////////////////////////////////////////////////////////////// | |
| 2 /// compass_test.cpp | |
| 3 /// Unit test for compass calibration. | |
| 4 /// Copyright (c) 2012-2015, JD Gascuel, HeinrichsWeikamp, all right reserved. | |
| 5 ////////////////////////////////////////////////////////////////////////////// | |
| 6 // HISTORY | |
| 7 // 2015-05-23 jDG: Rewrite compass testing, to allow reducing code size. | |
| 8 | |
| 9 extern "C" { | |
| 10 # include "compass.h" | |
| 11 } | |
| 12 | |
| 13 #include <gtest/gtest.h> | |
| 14 | |
| 15 #include <math.h> | |
| 16 #include <iostream> | |
| 17 | |
| 18 ////////////////////////////////////////////////////////////////////////////// | |
| 19 | |
| 20 inline float uniform() { | |
| 21 return (rand() & 0xFFFF) / 65536.0f; | |
| 22 } | |
| 23 inline float sqr(float x) { | |
| 24 return x*x; | |
| 25 } | |
| 26 | |
| 27 static float radius = 0.21f; | |
| 28 static float cx = 0, cy = 0, cz = 0; | |
| 29 | |
| 30 ////////////////////////////////////////////////////////////////////////////// | |
| 31 | |
| 32 static void check_calib() | |
| 33 { | |
| 34 compass_reset_calibration(); | |
| 35 | |
| 36 //---- Generates random points on a sphere ------------------------------- | |
| 37 // of radius,center (cx, cy, cz): | |
| 38 for(int i=0; i<100; ++i) | |
| 39 { | |
| 40 float theta = uniform()*360.0f; | |
| 41 float phi = uniform()*180.0f - 90.0f; | |
| 42 | |
| 43 float x = cx + radius * cosf(phi)*cosf(theta); | |
| 44 float y = cy + radius * cosf(phi)*sinf(theta); | |
| 45 float z = cz + radius * sinf(phi); | |
| 46 | |
| 47 compass_DX_f = short(32768 * x); | |
| 48 compass_DY_f = short(32768 * y); | |
| 49 compass_DZ_f = short(32768 * z); | |
| 50 compass_add_calibration(); | |
| 51 } | |
| 52 | |
| 53 compass_solve_calibration(); | |
| 54 float r2 = sqr(compass_CX_f/32768.0f - cx) | |
| 55 + sqr(compass_CY_f/32768.0f - cy) | |
| 56 + sqr(compass_CZ_f/32768.0f - cz); | |
| 57 | |
| 58 // Calibration error less than 2 bits: | |
| 59 EXPECT_NEAR(0, sqrtf(r2), 3.0f/32768.0f) | |
| 60 << "Center at (" << compass_CX_f/32768.0f << ", " | |
| 61 << compass_CY_f/32768.0f << ", " | |
| 62 << compass_CZ_f/32768.0f << ")." | |
| 63 << " Error = " << sqrtf(r2); | |
| 64 } | |
| 65 | |
| 66 ////////////////////////////////////////////////////////////////////////////// | |
| 67 | |
| 68 TEST(compass, calibration_centered) | |
| 69 { | |
| 70 compass_CX_f = compass_CY_f = compass_CZ_f = 0; | |
| 71 | |
| 72 // Half-unit, centered, sphere: | |
| 73 radius = 0.5f; | |
| 74 | |
| 75 // Try 10 recalibration passes: | |
| 76 for(int p=0; p<10; ++p) | |
| 77 check_calib(); | |
| 78 } | |
| 79 | |
| 80 ////////////////////////////////////////////////////////////////////////////// | |
| 81 | |
| 82 TEST(compass, calibration_near_centered) | |
| 83 { | |
| 84 // Put magnetic center elsewhere, but keep position+radius < 1.0, to | |
| 85 // avoid Q15 overflow... | |
| 86 radius = 0.21f; | |
| 87 cx = 0.019f, cy = -0.026f, cz = 0.004f; | |
| 88 | |
| 89 // Try 10 recalibration passes: | |
| 90 for(int p=0; p<10; ++p) | |
| 91 check_calib(); | |
| 92 } | |
| 93 | |
| 94 ////////////////////////////////////////////////////////////////////////////// | |
| 95 | |
| 96 TEST(compass, calibration_far_centered) | |
| 97 { | |
| 98 // Put magnetic center elsewhere, but keep position+radius < 1.0, to | |
| 99 // avoid Q15 overflow... | |
| 100 radius = 0.21f; | |
| 101 cx = -0.79f, cy = 0.79f, cz = 0.79f; | |
| 102 | |
| 103 // Try 10 recalibration passes: | |
| 104 for(int p=0; p<10; ++p) | |
| 105 check_calib(); | |
| 106 } | |
| 107 | |
| 108 ////////////////////////////////////////////////////////////////////////////// | |
| 109 | |
| 110 TEST(compass, calibration_small_centered_signal) | |
| 111 { | |
| 112 // use a very very small magnetic signal, centered: | |
| 113 radius = 0.001f; | |
| 114 cx = 0.000f, cy = 0.000f, cz = 0.000f; | |
| 115 | |
| 116 // Try 10 recalibration passes: | |
| 117 for(int p=0; p<10; ++p) | |
| 118 check_calib(); | |
| 119 } | |
| 120 | |
| 121 ////////////////////////////////////////////////////////////////////////////// | |
| 122 | |
| 123 TEST(compass, calibration_small_off_centered_signal) | |
| 124 { | |
| 125 // Have a rather small sphere radius (20%), off-centered buy 80% | |
| 126 radius = 0.200f; | |
| 127 cx = 0.800f, cy = -0.800f, cz = 0.800f; | |
| 128 | |
| 129 // Try 10 recalibration passes: | |
| 130 for(int p=0; p<10; ++p) | |
| 131 check_calib(); | |
| 132 } |
