capacitor-motioncal 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CapacitorMotionCal.podspec +23 -0
  2. package/README.md +126 -0
  3. package/android/build.gradle +67 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/java/com/denizak/motioncalibration/MotionCalibrationPlugin.java +248 -0
  6. package/android/src/main/jniLibs/arm64-v8a/libmotioncalibration.so +0 -0
  7. package/android/src/main/jniLibs/armeabi-v7a/libmotioncalibration.so +0 -0
  8. package/android/src/main/jniLibs/x86/libmotioncalibration.so +0 -0
  9. package/android/src/main/jniLibs/x86_64/libmotioncalibration.so +0 -0
  10. package/common/imuread.h +156 -0
  11. package/common/magcal.c +602 -0
  12. package/common/mahony.c +330 -0
  13. package/common/matrix.c +446 -0
  14. package/common/motioncalibration.c +7 -0
  15. package/common/motioncalibration.h +12 -0
  16. package/common/quality.c +257 -0
  17. package/common/rawdata.c +349 -0
  18. package/common/serialdata.c +501 -0
  19. package/common/visualize.c +131 -0
  20. package/dist/docs.json +292 -0
  21. package/dist/esm/definitions.d.ts +122 -0
  22. package/dist/esm/definitions.js +2 -0
  23. package/dist/esm/definitions.js.map +1 -0
  24. package/dist/esm/index.d.ts +4 -0
  25. package/dist/esm/index.js +7 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/web.d.ts +54 -0
  28. package/dist/esm/web.js +58 -0
  29. package/dist/esm/web.js.map +1 -0
  30. package/dist/plugin.cjs.js +72 -0
  31. package/dist/plugin.cjs.js.map +1 -0
  32. package/dist/plugin.js +75 -0
  33. package/dist/plugin.js.map +1 -0
  34. package/ios/Sources/MotionCalibrationPlugin/MotionCalibration-Bridging-Header.h +26 -0
  35. package/ios/Sources/MotionCalibrationPlugin/MotionCalibrationPlugin.swift +200 -0
  36. package/package.json +83 -0
@@ -0,0 +1,330 @@
1
+ //==============================================================================================
2
+ // MahonyAHRS.c
3
+ //==============================================================================================
4
+ //
5
+ // Madgwick's implementation of Mayhony's AHRS algorithm.
6
+ // See: http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/
7
+ //
8
+ // From the x-io website "Open-source resources available on this website are
9
+ // provided under the GNU General Public Licence unless an alternative licence
10
+ // is provided in source."
11
+ //
12
+ // Date Author Notes
13
+ // 29/09/2011 SOH Madgwick Initial release
14
+ // 02/10/2011 SOH Madgwick Optimised for reduced CPU load
15
+ //
16
+ // Algorithm paper:
17
+ // http://ieeexplore.ieee.org/xpl/login.jsp?tp=&arnumber=4608934&url=http%3A%2F%2Fieeexplore.ieee.org%2Fstamp%2Fstamp.jsp%3Ftp%3D%26arnumber%3D4608934
18
+ //
19
+ //==============================================================================================
20
+
21
+ //----------------------------------------------------------------------------------------------
22
+
23
+ #include "imuread.h"
24
+
25
+ #ifdef USE_MAHONY_FUSION
26
+
27
+ //----------------------------------------------------------------------------------------------
28
+ // Definitions
29
+
30
+ #define twoKpDef (2.0f * 0.02f) // 2 * proportional gain
31
+ #define twoKiDef (2.0f * 0.0f) // 2 * integral gain
32
+
33
+ #define INV_SAMPLE_RATE (1.0f / SENSORFS)
34
+
35
+ //----------------------------------------------------------------------------------------------
36
+ // Variable definitions
37
+
38
+ static float twoKp = twoKpDef; // 2 * proportional gain (Kp)
39
+ static float twoKi = twoKiDef; // 2 * integral gain (Ki)
40
+ static float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame
41
+ static float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
42
+
43
+
44
+ //==============================================================================================
45
+ // Functions
46
+
47
+ static float invSqrt(float x);
48
+ static void mahony_init();
49
+ static void mahony_update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
50
+ void mahony_updateIMU(float gx, float gy, float gz, float ax, float ay, float az);
51
+
52
+ static int reset_next_update=0;
53
+
54
+
55
+ void fusion_init(void)
56
+ {
57
+ mahony_init();
58
+ }
59
+
60
+ void fusion_update(const AccelSensor_t *Accel, const MagSensor_t *Mag, const GyroSensor_t *Gyro,
61
+ const MagCalibration_t *MagCal)
62
+ {
63
+ int i;
64
+ float ax, ay, az, gx, gy, gz, mx, my, mz;
65
+ float factor = M_PI / 180.0;
66
+
67
+ ax = Accel->Gp[0];
68
+ ay = Accel->Gp[1];
69
+ az = Accel->Gp[2];
70
+ mx = Mag->Bc[0];
71
+ my = Mag->Bc[1];
72
+ mz = Mag->Bc[2];
73
+ for (i=0; i < OVERSAMPLE_RATIO; i++) {
74
+ gx = Gyro->YpFast[i][0];
75
+ gy = Gyro->YpFast[i][1];
76
+ gz = Gyro->YpFast[i][2];
77
+ gx *= factor;
78
+ gy *= factor;
79
+ gz *= factor;
80
+ mahony_update(gx, gy, gz, ax, ay, az, mx, my, mz);
81
+ }
82
+ }
83
+
84
+ void fusion_read(Quaternion_t *q)
85
+ {
86
+ q->q0 = q0;
87
+ q->q1 = q1;
88
+ q->q2 = q2;
89
+ q->q3 = q3;
90
+ }
91
+
92
+
93
+ //----------------------------------------------------------------------------------------------
94
+ // AHRS algorithm update
95
+
96
+ static void mahony_init()
97
+ {
98
+ static int first=1;
99
+
100
+ twoKp = twoKpDef; // 2 * proportional gain (Kp)
101
+ twoKi = twoKiDef; // 2 * integral gain (Ki)
102
+ if (first) {
103
+ q0 = 1.0f;
104
+ q1 = 0.0f; // TODO: set a flag to immediately capture
105
+ q2 = 0.0f; // magnetic orientation on next update
106
+ q3 = 0.0f;
107
+ first = 0;
108
+ }
109
+ reset_next_update = 1;
110
+ integralFBx = 0.0f;
111
+ integralFBy = 0.0f;
112
+ integralFBz = 0.0f;
113
+ }
114
+
115
+ static void mahony_update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz)
116
+ {
117
+ float recipNorm;
118
+ float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
119
+ float hx, hy, bx, bz;
120
+ float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
121
+ float halfex, halfey, halfez;
122
+ float qa, qb, qc;
123
+
124
+ // Use IMU algorithm if magnetometer measurement invalid
125
+ // (avoids NaN in magnetometer normalisation)
126
+ if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
127
+ mahony_updateIMU(gx, gy, gz, ax, ay, az);
128
+ return;
129
+ }
130
+
131
+ // Compute feedback only if accelerometer measurement valid
132
+ // (avoids NaN in accelerometer normalisation)
133
+ if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
134
+
135
+ // Normalise accelerometer measurement
136
+ recipNorm = invSqrt(ax * ax + ay * ay + az * az);
137
+ ax *= recipNorm;
138
+ ay *= recipNorm;
139
+ az *= recipNorm;
140
+
141
+ // Normalise magnetometer measurement
142
+ recipNorm = invSqrt(mx * mx + my * my + mz * mz);
143
+ mx *= recipNorm;
144
+ my *= recipNorm;
145
+ mz *= recipNorm;
146
+ #if 0
147
+ // crazy experiement - no filter, just use magnetometer...
148
+ q0 = 0;
149
+ q1 = mx;
150
+ q2 = my;
151
+ q3 = mz;
152
+ return;
153
+ #endif
154
+ // Auxiliary variables to avoid repeated arithmetic
155
+ q0q0 = q0 * q0;
156
+ q0q1 = q0 * q1;
157
+ q0q2 = q0 * q2;
158
+ q0q3 = q0 * q3;
159
+ q1q1 = q1 * q1;
160
+ q1q2 = q1 * q2;
161
+ q1q3 = q1 * q3;
162
+ q2q2 = q2 * q2;
163
+ q2q3 = q2 * q3;
164
+ q3q3 = q3 * q3;
165
+
166
+ // Reference direction of Earth's magnetic field
167
+ hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
168
+ hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
169
+ bx = sqrtf(hx * hx + hy * hy);
170
+ bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
171
+
172
+ // Estimated direction of gravity and magnetic field
173
+ halfvx = q1q3 - q0q2;
174
+ halfvy = q0q1 + q2q3;
175
+ halfvz = q0q0 - 0.5f + q3q3;
176
+ halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
177
+ halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
178
+ halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
179
+
180
+ // Error is sum of cross product between estimated direction
181
+ // and measured direction of field vectors
182
+ halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
183
+ halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
184
+ halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
185
+
186
+ // Compute and apply integral feedback if enabled
187
+ if(twoKi > 0.0f) {
188
+ // integral error scaled by Ki
189
+ integralFBx += twoKi * halfex * INV_SAMPLE_RATE;
190
+ integralFBy += twoKi * halfey * INV_SAMPLE_RATE;
191
+ integralFBz += twoKi * halfez * INV_SAMPLE_RATE;
192
+ gx += integralFBx; // apply integral feedback
193
+ gy += integralFBy;
194
+ gz += integralFBz;
195
+ } else {
196
+ integralFBx = 0.0f; // prevent integral windup
197
+ integralFBy = 0.0f;
198
+ integralFBz = 0.0f;
199
+ }
200
+
201
+ //printf("err = %.3f, %.3f, %.3f\n", halfex, halfey, halfez);
202
+
203
+ // Apply proportional feedback
204
+ if (reset_next_update) {
205
+ gx += 2.0f * halfex;
206
+ gy += 2.0f * halfey;
207
+ gz += 2.0f * halfez;
208
+ reset_next_update = 0;
209
+ } else {
210
+ gx += twoKp * halfex;
211
+ gy += twoKp * halfey;
212
+ gz += twoKp * halfez;
213
+ }
214
+ }
215
+
216
+ // Integrate rate of change of quaternion
217
+ gx *= (0.5f * INV_SAMPLE_RATE); // pre-multiply common factors
218
+ gy *= (0.5f * INV_SAMPLE_RATE);
219
+ gz *= (0.5f * INV_SAMPLE_RATE);
220
+ qa = q0;
221
+ qb = q1;
222
+ qc = q2;
223
+ q0 += (-qb * gx - qc * gy - q3 * gz);
224
+ q1 += (qa * gx + qc * gz - q3 * gy);
225
+ q2 += (qa * gy - qb * gz + q3 * gx);
226
+ q3 += (qa * gz + qb * gy - qc * gx);
227
+
228
+ // Normalise quaternion
229
+ recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
230
+ q0 *= recipNorm;
231
+ q1 *= recipNorm;
232
+ q2 *= recipNorm;
233
+ q3 *= recipNorm;
234
+ }
235
+
236
+ //---------------------------------------------------------------------------------------------
237
+ // IMU algorithm update
238
+
239
+ void mahony_updateIMU(float gx, float gy, float gz, float ax, float ay, float az)
240
+ {
241
+ float recipNorm;
242
+ float halfvx, halfvy, halfvz;
243
+ float halfex, halfey, halfez;
244
+ float qa, qb, qc;
245
+
246
+ // Compute feedback only if accelerometer measurement valid
247
+ // (avoids NaN in accelerometer normalisation)
248
+ if (!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
249
+
250
+ // Normalise accelerometer measurement
251
+ recipNorm = invSqrt(ax * ax + ay * ay + az * az);
252
+ ax *= recipNorm;
253
+ ay *= recipNorm;
254
+ az *= recipNorm;
255
+
256
+ // Estimated direction of gravity and vector perpendicular to magnetic flux
257
+ halfvx = q1 * q3 - q0 * q2;
258
+ halfvy = q0 * q1 + q2 * q3;
259
+ halfvz = q0 * q0 - 0.5f + q3 * q3;
260
+
261
+ // Error is sum of cross product between estimated and measured direction of gravity
262
+ halfex = (ay * halfvz - az * halfvy);
263
+ halfey = (az * halfvx - ax * halfvz);
264
+ halfez = (ax * halfvy - ay * halfvx);
265
+
266
+ // Compute and apply integral feedback if enabled
267
+ if(twoKi > 0.0f) {
268
+ // integral error scaled by Ki
269
+ integralFBx += twoKi * halfex * INV_SAMPLE_RATE;
270
+ integralFBy += twoKi * halfey * INV_SAMPLE_RATE;
271
+ integralFBz += twoKi * halfez * INV_SAMPLE_RATE;
272
+ gx += integralFBx; // apply integral feedback
273
+ gy += integralFBy;
274
+ gz += integralFBz;
275
+ } else {
276
+ integralFBx = 0.0f; // prevent integral windup
277
+ integralFBy = 0.0f;
278
+ integralFBz = 0.0f;
279
+ }
280
+
281
+ // Apply proportional feedback
282
+ gx += twoKp * halfex;
283
+ gy += twoKp * halfey;
284
+ gz += twoKp * halfez;
285
+ }
286
+
287
+ // Integrate rate of change of quaternion
288
+ gx *= (0.5f * INV_SAMPLE_RATE); // pre-multiply common factors
289
+ gy *= (0.5f * INV_SAMPLE_RATE);
290
+ gz *= (0.5f * INV_SAMPLE_RATE);
291
+ qa = q0;
292
+ qb = q1;
293
+ qc = q2;
294
+ q0 += (-qb * gx - qc * gy - q3 * gz);
295
+ q1 += (qa * gx + qc * gz - q3 * gy);
296
+ q2 += (qa * gy - qb * gz + q3 * gx);
297
+ q3 += (qa * gz + qb * gy - qc * gx);
298
+
299
+ // Normalise quaternion
300
+ recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
301
+ q0 *= recipNorm;
302
+ q1 *= recipNorm;
303
+ q2 *= recipNorm;
304
+ q3 *= recipNorm;
305
+ }
306
+
307
+ //---------------------------------------------------------------------------------------------
308
+ // Fast inverse square-root
309
+ // See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
310
+
311
+ static float invSqrt(float x) {
312
+ union {
313
+ float f;
314
+ int32_t i;
315
+ } y;
316
+ float halfx = 0.5f * x;
317
+
318
+ y.f = x;
319
+ y.i = 0x5f375a86 - (y.i >> 1);
320
+ y.f = y.f * (1.5f - (halfx * y.f * y.f));
321
+ y.f = y.f * (1.5f - (halfx * y.f * y.f));
322
+ y.f = y.f * (1.5f - (halfx * y.f * y.f));
323
+ return y.f;
324
+ }
325
+
326
+ //==============================================================================================
327
+ // END OF CODE
328
+ //==============================================================================================
329
+
330
+ #endif // USE_MAHONY_FUSION