-
Notifications
You must be signed in to change notification settings - Fork 0
/
MinIMU9AHRS.h
executable file
·344 lines (275 loc) · 7.66 KB
/
MinIMU9AHRS.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
MinIMU-9-Arduino-AHRS
Pololu MinIMU-9 + Arduino AHRS (Attitude and Heading Reference System)
Copyright (c) 2011 Pololu Corporation.
http://www.pololu.com/
MinIMU-9-Arduino-AHRS is based on sf9domahrs by Doug Weibel and Jose Julio:
http://code.google.com/p/sf9domahrs/
sf9domahrs is based on ArduIMU v1.5 by Jordi Munoz and William Premerlani, Jose
Julio and Doug Weibel:
http://code.google.com/p/ardu-imu/
MinIMU-9-Arduino-AHRS is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
MinIMU-9-Arduino-AHRS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License along
with MinIMU-9-Arduino-AHRS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MinIMU9AHRS_h
#define MinIMU9AHRS_h
#include <LSM303.h>
#include <L3G.h>
#include <Wire.h>
#define ACC_ADDRESS_SA0_A_HIGH (0x32 >> 1)
#define L3GD20_ADDRESS_SA0_HIGH (0xD6 >> 1)
// LSM303 accelerometer: 8g sensitivity
// 3.8 mg/digit; 1 g = 256
// This is equivalent to 1G in the raw data coming from the accelerometer.
#define GRAVITY 256
// Minimum timeout in milliseconds that must elapse between readings.
// 50Hz (20ms)
#define DEFAULT_READING_TIMEOUT_MILLIS 20
// Minimum timeout in milliseconds that must elapse between compass readings.
// 10Hz (100ms)
#define DEFAULT_COMPASS_TIMEOUT_MILLIS 100
// Convert provided value to radians
#define ToRad(x) ((x)*0.01745329252) // *pi/180
// Convert provided value to degrees
#define ToDeg(x) ((x)*57.2957795131) // *180/pi
// L3G4200D gyro: 2000 dps full scale
// 70 mdps/digit; 1 dps = 0.07
#define Gyro_Gain_X 0.07 // X axis Gyro gain
#define Gyro_Gain_Y 0.07 // Y axis Gyro gain
#define Gyro_Gain_Z 0.07 // Z axis Gyro gain
// Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_X(x) ((x)*ToRad(Gyro_Gain_X))
// Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Y(x) ((x)*ToRad(Gyro_Gain_Y))
// Return the scaled ADC raw data of the gyro in radians for second
#define Gyro_Scaled_Z(x) ((x)*ToRad(Gyro_Gain_Z))
// LSM303 magnetometer calibration constants; use the Calibrate example from
// the Pololu LSM303 library to find the right values for your board
#define M_X_MIN -5649
#define M_Y_MIN -3877
#define M_Z_MIN -1468
#define M_X_MAX +463
#define M_Y_MAX +3398
#define M_Z_MAX +6120
#define Kp_ROLLPITCH 0.02
#define Ki_ROLLPITCH 0.00002
#define Kp_YAW 1.2
#define Ki_YAW 0.00002
#define OUTPUTMODE 1
/**
* Interpreted Euler angle from the raw values.
*/
typedef struct EulerAngle {
float roll, pitch, yaw;
};
class MinIMU9AHRS {
public:
/**
* The Attitude, Heading Reference System.
*/
MinIMU9AHRS();
/**
* Initialize the AHRS.
*/
void init(void);
/**
* Get the most recent Euler angle (roll, pitch and yaw) from the AHRS.
*/
EulerAngle getEuler(void);
EulerAngle getGyroEuler(void);
/**
* Update the readings from all inputs.
*/
void updateReadings(void);
private:
/**
* Initialize default instance values.
*/
void _initValues(void);
/**
* Initialize gyroscope.
*/
void _initGyro(void);
/**
* Initialize accelerometer.
*/
void _initAccelerometer(void);
/**
* Initialize compass.
*/
void _initCompass(void);
/**
* Initialize readings.
*/
void _initOffsets(void);
/**
* Read the gyroscope and update values accordingly.
*/
void _readGyro(void);
/**
* Read the accelerometer and update values accordingly.
*/
void _readAccelerometer(void);
/**
* Read the compass and update values accordingly.
*/
void _readCompass(void);
/**
* Update the compass heading after reading values.
*/
void _updateCompassHeading(void);
/**
* Update the Euler angles.
*/
void _updateEulerAngles(void);
/**
* Multiply two 3x3 matrixs. This function developed by Jordi can be easily
* adapted to multiple n*n matrix's. (Pero me da flojera!).
*/
void _matrixMultiply(float a[3][3], float b[3][3], float mat[3][3]);
/**
* Update the data matrices.
*/
void _matrixUpdate(void);
/**
* Compute the dot product of two vectors and put the result into vectorOut.
*/
float _vectorDotProduct(float vector1[3],float vector2[3]);
/**
* Compute the cross product of two vectors and put the result into vectorOut.
*/
void _vectorCrossProduct(float vectorOut[3], float v1[3], float v2[3]);
/**
* Multiply the provided vector by a scalar and put result into vectorOut.
*/
void _vectorScale(float vectorOut[3], float vectorIn[3], float scale2);
/**
* Add the povided vectors and put result into vectorOut.
*/
void _vectorAdd(float vectorOut[3], float vectorIn1[3], float vectorIn2[3]);
/**
* Normalize the matrices.
*/
void _normalize(void);
/**
* Correct matrices for drift.
*/
void _driftCorrection(void);
/**
* Accelerometer instance.
*/
LSM303 _accelerometer;
/**
* Gyroscope instance.
*/
L3G _gyroscope;
/**
* Accelerometer values as a vector.
*/
float _accelValue[3];
/**
* Accelerometer values as a vector.
*/
float _accelVector[3];
/**
* Compass values as a vector.
*/
float _compassValue[3];
/**
* Compass values as a vector.
*/
float _compassVector[3];
/**
* Time in milliseconds since the last compass reading.
*
* The compass shouldn't be read more that 5Hz.
*/
unsigned long _lastCompassReadingTime;
/**
* Gyroscope values as a vector.
*/
float _gyroValue[3];
/**
* Gyroscope values as a vector.
*/
float _gyroVector[3];
/**
* Corrected gyro vector data.
*/
float _omegaVector[3];
/**
* Proportional correction.
*/
float _omegaP[3];
/**
* Omega integration.
*/
float _omegaI[3];
/**
* Omega result.
*/
float _omega[3];
float _rawValues[6];
/**
* Array that stores the offsets of the sensors.
*/
int _offsets[6];
/**
* Array that indicates the direction (or sign) of each axis for each
* of the sensors (Gyro and Accelerometer).
*/
int _sensorDirection[9];
/**
* Time of last reading in milliseconds.
*/
unsigned long _lastReadingTime;
/**
* Time of current reading in milliseconds.
*/
unsigned long _currentReadingTime;
/**
* Integration time in seconds for the DCM algorithm. We will run the
* integration loop at 100Hz if possible.
*/
float _secondsSinceLastReading;
/**
* Matrix for DCM values.
*/
float _dcmMatrix[3][3];
/**
* Temporary matrix to use for multiplication.
*/
float _tempMatrix[3][3];
/**
* Matrix to update.
*
* NOTE(lbayes): These values were globally assigned before:
* {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
*/
float _updateMatrix[3][3];
/**
* Error roll pitch.
*/
float _errorRollPitch[3];
/**
* Error yaw.
*/
float _errorYaw[3];
/**
* Magnetometer heading.
*/
float _magHeading;
/**
* The current Euler angle of the device (roll, pitch and yaw).
*/
EulerAngle _euler;
};
#endif