Mercurial > public > hwos_code
comparison src/compass_calib.c @ 628:cd58f7fc86db
3.05 stable work
author | heinrichsweikamp |
---|---|
date | Thu, 19 Sep 2019 12:01:29 +0200 |
parents | c40025d8e750 |
children | 4050675965ea |
comparison
equal
deleted
inserted
replaced
627:bf5fee575701 | 628:cd58f7fc86db |
---|---|
6 // Copyright (c) 2012-2019, JD Gascuel, HeinrichsWeikamp, all rights reserved. | 6 // Copyright (c) 2012-2019, JD Gascuel, HeinrichsWeikamp, all rights reserved. |
7 // | 7 // |
8 ////////////////////////////////////////////////////////////////////////////// | 8 ////////////////////////////////////////////////////////////////////////////// |
9 | 9 |
10 // 2015-05-22 [jDG] Make a smaller calibration code (15.6 --> 6.7 KB). | 10 // 2015-05-22 [jDG] Make a smaller calibration code (15.6 --> 6.7 KB). |
11 // 2019-05-14 [rl] make it even smaller again by another 2.000 byte | 11 // 2019-05-14 [rl] make smaller again |
12 | 12 |
13 #include "configuration.inc" | 13 #include "configuration.inc" |
14 #include "compass.h" | 14 #include "compass.h" |
15 | 15 |
16 | 16 |
37 | 37 |
38 ////////////////////////////////////////////////////////////////////////////// | 38 ////////////////////////////////////////////////////////////////////////////// |
39 | 39 |
40 static unsigned short int compass_N; | 40 static unsigned short int compass_N; |
41 | 41 |
42 static float Su, Sv, Sw; // first order moments | 42 static float Su, Sv, Sw; // first order moments |
43 static float Suu, Svv, Sww, Suv, Suw, Svw; // second order moments | 43 static float Suu, Svv, Sww, Suv, Suw, Svw; // second order moments |
44 static float Saa; // Suu + Svv + Sww | 44 static float Saa; // Suu + Svv + Sww |
45 static float Saau; // Suuu + Svvu + Swwu third order moment | 45 static float Saau; // Suuu + Svvu + Swwu third order moment |
46 static float Saav; // Suuv + Svvv + Swwv third order moment | 46 static float Saav; // Suuv + Svvv + Swwv third order moment |
47 static float Saaw; // Suuw + Svvw + Swww third order moment | 47 static float Saaw; // Suuw + Svvw + Swww third order moment |
48 | 48 |
49 static float yu, yv, yw; // temp solution vector | 49 static float yu, yv, yw; // temp solution vector |
50 static float uc, vc, wc; // temp sphere's center | 50 static float uc, vc, wc; // temp sphere's center |
51 | 51 |
52 static float yh, uh, S0, S1, S2, S3; // transfer vars for compass_solve_helper() | 52 static float yh,uh,S0,S1,S2,S3; // transfer vars for compass_solve_helper() |
53 static float discriminant, delta; // transfer vars for calc_discriminant() | 53 |
54 | 54 ////////////////////////////////////////////////////////////////////////////// |
55 | 55 |
56 ////////////////////////////////////////////////////////////////////////////// | 56 void compass_reset_calibration() |
57 | |
58 #ifndef UNIX | |
59 # pragma code compass_calib | |
60 #endif | |
61 | |
62 ////////////////////////////////////////////////////////////////////////////// | |
63 | |
64 void compass_reset_calibration() // 202 byte | |
65 { | 57 { |
66 RESET_C_STACK; | 58 RESET_C_STACK; |
67 | 59 |
68 compass_N = 0; | 60 compass_N = 0; |
69 Su = Sv = Sw = 0.0; | 61 Su = Sv = Sw = 0.0; |
70 Suu = Svv = Sww = 0.0; | 62 Suu = Svv = Sww = 0.0; |
71 Suv = Suw = Svw = 0.0; | 63 Suv = Suw = Svw = 0.0; |
72 Saau = Saav = Saaw = 0.0; | 64 Saau = Saav = Saaw = 0.0; |
73 compass_CX_f = compass_CY_f = compass_CZ_f = 0; // int16 | 65 compass_CX_f = compass_CY_f = compass_CZ_f = 0; |
74 } | 66 } |
75 | 67 |
76 ////////////////////////////////////////////////////////////////////////////// | 68 ////////////////////////////////////////////////////////////////////////////// |
77 | 69 |
78 void compass_add_calibration() // 1488 byte | 70 void compass_add_calibration() |
79 { | 71 { |
80 overlay float SQR_yu, SQR_yv, SQR_yw; // squared values; | |
81 | |
82 RESET_C_STACK; | 72 RESET_C_STACK; |
83 | 73 |
84 // get filtered/calibrated magnetic direction // 276 byte | 74 // get filtered/calibrated magnetic direction |
85 yu = (compass_DX_f - compass_CX_f) / 32768.0f; | 75 yu = (compass_DX_f - compass_CX_f) / 32768.0f; |
86 yv = (compass_DY_f - compass_CY_f) / 32768.0f; | 76 yv = (compass_DY_f - compass_CY_f) / 32768.0f; |
87 yw = (compass_DZ_f - compass_CZ_f) / 32768.0f; | 77 yw = (compass_DZ_f - compass_CZ_f) / 32768.0f; |
88 | 78 |
89 // compute squared values // 156 byte | 79 // add to all moments |
90 SQR_yu = yu*yu; | |
91 SQR_yv = yv*yv; | |
92 SQR_yw = yw*yw; | |
93 | |
94 // increment count | |
95 compass_N++; | 80 compass_N++; |
96 | 81 |
97 // add to all moments // 156 byte | |
98 Su += yu; | 82 Su += yu; |
99 Sv += yv; | 83 Sv += yv; |
100 Sw += yw; | 84 Sw += yw; |
101 | 85 |
102 // // 156 byte | 86 Suu += yu*yu; |
103 Suu += SQR_yu; | |
104 Svv += SQR_yv; | |
105 Sww += SQR_yw; | |
106 | |
107 // // 312 byte | |
108 Suv += yu*yv; | 87 Suv += yu*yv; |
109 Suw += yu*yw; | 88 Suw += yu*yw; |
89 Svv += yv*yv; | |
110 Svw += yv*yw; | 90 Svw += yv*yw; |
111 | 91 Sww += yw*yw; |
112 // // 104 byte | 92 |
113 Saa = SQR_yu + SQR_yv + SQR_yw; | 93 Saa = yu*yu + yv*yv + yw*yw; |
114 | 94 |
115 | |
116 // // 312 byte | |
117 Saau += yu * Saa; | 95 Saau += yu * Saa; |
118 Saav += yv * Saa; | 96 Saav += yv * Saa; |
119 Saaw += yw * Saa; | 97 Saaw += yw * Saa; |
120 } | 98 } |
121 | 99 |
122 ////////////////////////////////////////////////////////////////////////////// | 100 ////////////////////////////////////////////////////////////////////////////// |
123 | 101 |
124 static void calc_discriminant(PARAMETER char column) | 102 static float compass_discriminent(PARAMETER char column) |
125 { | 103 { |
126 // basic symmetric matrix | 104 // basic symmetric matrix |
127 overlay float a = Suu, d = Suv, g = Suw; | 105 OVERLAY float a = Suu, d = Suv, g = Suw; |
128 overlay float b = Suv, e = Svv, h = Svw; | 106 OVERLAY float b = Suv, e = Svv, h = Svw; |
129 overlay float c = Suw, f = Svw, i = Sww; | 107 OVERLAY float c = Suw, f = Svw, i = Sww; |
108 OVERLAY float result; | |
130 | 109 |
131 // substitute a column, if asked to | 110 // substitute a column, if asked to |
132 if( column==1 ) { a = yu; b = yv; c = yw; } | 111 if( column==1 ) { a = yu; b = yv; c = yw; } |
133 if( column==2 ) { d = yu; e = yv; f = yw; } | 112 if( column==2 ) { d = yu; e = yv; f = yw; } |
134 if( column==3 ) { g = yu; h = yv; i = yw; } | 113 if( column==3 ) { g = yu; h = yv; i = yw; } |
135 | 114 |
136 // do the math in a couple of single terms to reduce | 115 // do the math in a couple of single terms to reduce |
137 // the amount of required ".tmpdata" memory | 116 // the amount of required ".tmpdata" memory |
138 discriminant = a * (e * i - f * h); | 117 result = a * (e * i - f * h); |
139 discriminant -= b * (d * i - f * g); | 118 result -= b * (d * i - f * g); |
140 discriminant += c * (d * h - e * g); | 119 result += c * (d * h - e * g); |
141 | 120 |
142 // apply delta if column = 1/2/3 | 121 return result; |
143 if( column ) discriminant *= delta; | 122 } |
144 } | 123 |
145 | 124 ////////////////////////////////////////////////////////////////////////////// |
146 ////////////////////////////////////////////////////////////////////////////// | 125 |
147 | 126 static void compass_solve_helper(void) |
148 static void compass_solve_helper(void) // 338 byte | |
149 { | 127 { |
150 // computes: | 128 // computes: |
151 // | 129 // |
152 // yh = S0 - Saa*uh - compass_dotc(Su*uh + 2*S1, Sv*uh + 2*S2, Sw*uh + 2*S3); | 130 // yh = S0 - Saa*uh - compass_dotc(Su*uh + 2*S1, Sv*uh + 2*S2, Sw*uh + 2*S3); |
153 // | 131 // |
161 yh = S0; | 139 yh = S0; |
162 yh -= Saa*uh; | 140 yh -= Saa*uh; |
163 yh -= (Su*uh + 2*S1) * uc; | 141 yh -= (Su*uh + 2*S1) * uc; |
164 yh -= (Sv*uh + 2*S2) * vc; | 142 yh -= (Sv*uh + 2*S2) * vc; |
165 yh -= (Sw*uh + 2*S3) * wc; | 143 yh -= (Sw*uh + 2*S3) * wc; |
166 } | 144 |
167 | 145 return; |
168 ////////////////////////////////////////////////////////////////////////////// | 146 } |
169 | 147 |
170 void compass_solve_calibration() // 1738 byte | 148 ////////////////////////////////////////////////////////////////////////////// |
171 { | 149 |
172 overlay float inv_compass_N; | 150 void compass_solve_calibration() |
151 { | |
152 OVERLAY float delta; | |
173 | 153 |
174 RESET_C_STACK; | 154 RESET_C_STACK; |
175 | 155 |
176 // compute center of measured magnetic directions // 200 byte | 156 //---- Compute center of measured magnetic directions -------------------- |
177 inv_compass_N = 1 / compass_N; | 157 uc = Su/compass_N; |
178 uc = Su * inv_compass_N; | 158 vc = Sv/compass_N; |
179 vc = Sv * inv_compass_N; | 159 wc = Sw/compass_N; |
180 wc = Sw * inv_compass_N; | 160 |
181 | 161 //---- Normalize partial sums -------------------------------------------- |
182 // normalize partial sums | |
183 // | 162 // |
184 // We measured the (u, v, w) values, and need the centered (x, y, z) ones | 163 // We measured the (u, v, w) values, and need the centered (x, y, z) ones |
185 // around the sphere center's (uc, vc, wc) as: | 164 // around the sphere center's (uc, vc, wc) as: |
186 // uc = Su / N; The mean value | 165 // uc = Su / N; The mean value |
187 // x = u - uc; The difference to the mean. | 166 // x = u - uc; The difference to the mean. |
220 // = Sxxy - (Suu + Sx*Sx/N)*Sy/N - 2 Suv*Sx/N | 199 // = Sxxy - (Suu + Sx*Sx/N)*Sy/N - 2 Suv*Sx/N |
221 | 200 |
222 Saa = Suu + Svv + Sww; | 201 Saa = Suu + Svv + Sww; |
223 | 202 |
224 // compute yu = Saau - Saa*uc - compass_dotc(Su*uc + 2*Suu, Sv*uc + 2*Suv, Sw*uc + 2*Suw); | 203 // compute yu = Saau - Saa*uc - compass_dotc(Su*uc + 2*Suu, Sv*uc + 2*Suv, Sw*uc + 2*Suw); |
225 // | 204 uh = uc; S0 = Saau; S1 = Suu; S2 = Suv; S3 = Suw; |
226 uh = uc; S0 = Saau; S1 = Suu; S2 = Suv; S3 = Suw; compass_solve_helper(); yu = yh; | 205 compass_solve_helper(); |
206 yu = yh; | |
227 | 207 |
228 // compute yv = Saav - Saa*vc - compass_dotc(Su*vc + 2*Suv, Sv*vc + 2*Svv, Sw*vc + 2*Svw); | 208 // compute yv = Saav - Saa*vc - compass_dotc(Su*vc + 2*Suv, Sv*vc + 2*Svv, Sw*vc + 2*Svw); |
229 // | 209 uh = vc; S0 = Saav; S1 = Suv; S2 = Svv; S3 = Svw; |
230 uh = vc; S0 = Saav; S1 = Suv; S2 = Svv; S3 = Svw; compass_solve_helper(); yv = yh; | 210 compass_solve_helper(); |
211 yv = yh; | |
231 | 212 |
232 // compute yw = Saaw - Saa*wc - compass_dotc(Su*wc + 2*Suw, Sv*wc + 2*Svw, Sw*wc + 2*Sww); | 213 // compute yw = Saaw - Saa*wc - compass_dotc(Su*wc + 2*Suw, Sv*wc + 2*Svw, Sw*wc + 2*Sww); |
233 // | 214 uh = wc; S0 = Saaw; S1 = Suw; S2 = Svw; S3 = Sww; |
234 uh = wc; S0 = Saaw; S1 = Suw; S2 = Svw; S3 = Sww; compass_solve_helper(); yw = yh; | 215 compass_solve_helper(); |
216 yw = yh; | |
235 | 217 |
236 | 218 |
237 //---- Solve the system -------------------------------------------------- | 219 //---- Solve the system -------------------------------------------------- |
238 // uc Suu + vc Suv + wc Suw = (Suuu + Svvu + Swwu) / 2 | 220 // uc Suu + vc Suv + wc Suw = (Suuu + Svvu + Swwu) / 2 |
239 // uc Suv + vc Svv + wc Svw = (Suuv + Svvv + Swwv) / 2 | 221 // uc Suv + vc Svv + wc Svw = (Suuv + Svvv + Swwv) / 2 |
240 // uc Suw + vc Svw + wc Sww = (Suuw + Svvw + Swww) / 2 | 222 // uc Suw + vc Svw + wc Sww = (Suuw + Svvw + Swww) / 2 |
241 // | 223 // |
242 // Note this is symmetric, with a positive diagonal, hence discriminant is always not null | 224 // Note this is symmetric, with a positive diagonal, hence discriminant is always not null |
243 | 225 |
244 //compute delta value | 226 delta = 0.5f / compass_discriminent(0); |
245 calc_discriminant(0); delta = 0.5f / discriminant; | 227 |
246 | 228 // computed new center, with offset values: |
247 // compute new center, with offset values | 229 uc += compass_discriminent(1) * delta; |
248 calc_discriminant(1); uc += discriminant; | 230 vc += compass_discriminent(2) * delta; |
249 calc_discriminant(2); vc += discriminant; | 231 wc += compass_discriminent(3) * delta; |
250 calc_discriminant(3); wc += discriminant; | 232 |
251 | 233 // add correction due to already applied calibration: |
252 // add correction due to already applied calibration | |
253 compass_CX_f += (short)(32768 * uc); | 234 compass_CX_f += (short)(32768 * uc); |
254 compass_CY_f += (short)(32768 * vc); | 235 compass_CY_f += (short)(32768 * vc); |
255 compass_CZ_f += (short)(32768 * wc); | 236 compass_CZ_f += (short)(32768 * wc); |
256 } | 237 } |
257 | 238 |