ISSDK  1.7
IoT Sensing Software Development Kit
sensor_fusion.h
Go to the documentation of this file.
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  * that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  * of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  * list of conditions and the following disclaimer in the documentation and/or
16  * other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from this
20  * software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 // Sensor fusion requires a fairly extensive set of data structures, which are
36 // defined in this file. The top level structure is shown near the bottom. The
37 // size of this structure (SensorFusionGlobals) varies dramatically as a function
38 // of which fusion variations have been selected in build.h.
39 
40 /*! \file sensor_fusion.h
41  \brief The sensor_fusion.h file implements the top level programming interface
42 */
43 
44 #ifndef SENSOR_FUSION_TYPES_H
45 #define SENSOR_FUSION_TYPES_H
46 
47 // Standard includes that everyone needs
48 #include "math.h"
49 #include "stdbool.h"
50 #include "stdio.h"
51 #include "stdint.h"
52 
53 
54 #include "issdk_hal.h" // Hardware Abstraction Layer board dependencies beyond those generated in board.h by PEX
55 #include "build.h" // This is where the build parameters are defined
56 #include "magnetic.h" // Magnetic calibration functions/structures
57 #include "precisionAccelerometer.h" // Accel calibration functions/structures
58 #include "orientation.h" // Functions for manipulating orientations
59 #include "register_io_spi.h"
60 
61 /// @name Integer Typedefs
62 /// Typedefs to map common integer types to standard form
63 ///@{
64 typedef unsigned char byte;
65 typedef int8_t int8;
66 typedef int16_t int16;
67 typedef int32_t int32;
68 typedef uint8_t uint8;
69 typedef uint16_t uint16;
70 typedef uint32_t uint32;
71 ///@}
72 
73 /// the quaternion type to be transmitted
74 typedef enum quaternion {
75  Q3, ///< Quaternion derived from 3-axis accel (tilt)
76  Q3M, ///< Quaternion derived from 3-axis mag only (auto compass algorithm)
77  Q3G, ///< Quaternion derived from 3-axis gyro only (rotation)
78  Q6MA, ///< Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
79  Q6AG, ///< Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
80  Q9 ///< Quaternion derived from full 9-axis sensor fusion
82 
83 /// @name Vector Components
84 /// Index values for accessing vector terms
85 ///@{
86 #define CHX 0 ///< Used to access X-channel entries in various data data structures
87 #define CHY 1 ///< Used to access Y-channel entries in various data data structures
88 #define CHZ 2 ///< Used to access Z-channel entries in various data data structures
89 ///@}
90 
91 // booleans
92 #define true 1 ///< Boolean TRUE
93 #define false 0 ///< Boolean FALSE
94 
95 /// @name Generic bit-field values
96 /// Generic bit-field values
97 ///@{
98 #define B0 (1 << 0)
99 #define B1 (1 << 1)
100 #define B2 (1 << 2)
101 #define B3 (1 << 3)
102 ///@}
103 
104 /// @name Math Constants
105 /// useful multiplicative conversion constants
106 ///@{
107 #define PI 3.141592654F ///< pi
108 #define PIOVER2 1.570796327F ///< pi / 2
109 #define FPIOVER180 0.01745329251994F ///< degrees to radians conversion = pi / 180
110 #define F180OVERPI 57.2957795130823F ///< radians to degrees conversion = 180 / pi
111 #define F180OVERPISQ 3282.8063500117F ///< square of F180OVERPI
112 #define ONETHIRD 0.33333333F ///< one third
113 #define ONESIXTH 0.166666667F ///< one sixth
114 #define ONESIXTEENTH 0.0625F ///< one sixteenth
115 #define ONEOVER12 0.083333333F ///< 1 / 12
116 #define ONEOVER48 0.02083333333F ///< 1 / 48
117 #define ONEOVER120 0.0083333333F ///< 1 / 120
118 #define ONEOVER3840 0.0002604166667F ///< 1 / 3840
119 #define ONEOVERSQRT2 0.707106781F ///< 1/sqrt(2)
120 #define SQRT15OVER4 0.968245837F ///< sqrt(15)/4
121 #define GTOMSEC2 9.80665 ///< standard gravity in m/s2
122 ///@}
123 
124 // Placeholder structures (redefined later, but needed now for pointer definitions)
125 struct SensorFusionGlobals; ///< Top level structure has pointers to everything else
126 struct StatusSubsystem; ///< Application-specific status subsystem
127 struct PhysicalSensor; ///< We'll have one of these for each physical sensor (FXOS8700 = 1 physical sensor)
128 struct ControlSubsystem; ///< Application-specific serial communications system
129 
130 typedef enum { /// These are the state definitions for the status subsystem
131  OFF, ///< Application hasn't started
132  INITIALIZING, ///< Initializing sensors and algorithms
133  LOWPOWER, ///< Running in reduced power mode
134  NORMAL, ///< Operation is Nominal
135  RECEIVING_WIRED, ///< Receiving commands over wired interface (momentary)
136  RECEIVING_WIRELESS, ///< Receiving commands over wireless interface (momentary)
137  HARD_FAULT, ///< Non-recoverable FAULT = something went very wrong
138  SOFT_FAULT ///< Recoverable FAULT = something went wrong, but we can keep going
140 
141 // declare typedefs for function prototypes that need to be installed
142 typedef int8_t (initializeSensor_t) (
143  struct PhysicalSensor *sensor,
144  struct SensorFusionGlobals *sfg
145 ) ;
146 typedef int8_t (readSensor_t) (
147  struct PhysicalSensor *sensor,
148  struct SensorFusionGlobals *sfg
149 ) ;
150 typedef int8_t (readSensors_t) (
151  struct SensorFusionGlobals *sfg,
152  uint16_t read_loop_counter
153 ) ;
154 typedef int8_t (installSensor_t) (
155  struct SensorFusionGlobals *sfg, ///< Global data structure pointer
156  struct PhysicalSensor *sensor, ///< SF Structure to store sensor configuration
157  uint16_t addr, ///< I2C address or SPI_ADDR
158  uint16_t schedule, ///< Specifies sampling interval
159  void *bus_driver, ///< I2C or SPI handle
160  registerDeviceInfo_t *busInfo, ///< information required for bus power management
161  initializeSensor_t *initialize, ///< SF Sensor Initialization Function pointer
162  readSensor_t *read ///< SF Sensor Read Function pointer
163 );
164 #define SPI_ADDR 0x00 // Use SPI_ADDR as the address parameter to the installSensor function for SPI-based sensors.
165  // 0x00 is reserved for I2C General Call, and will therefore never occur for any sensor type
166 
168 typedef void (runFusion_t) (struct SensorFusionGlobals *sfg);
169 typedef void (clearFIFOs_t) (struct SensorFusionGlobals *sfg);
171 typedef void (applyPerturbation_t) (struct SensorFusionGlobals *sfg) ;
173 typedef void (updateStatus_t) (struct SensorFusionGlobals *sfg);
174 typedef void (ssSetStatus_t) (struct StatusSubsystem *pStatus, fusion_status_t status);
175 typedef void (ssUpdateStatus_t) (struct StatusSubsystem *pStatus);
176 
177 /// \brief An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo devices = 1)
178 ///
179 /// These structures sit 'on-top-of' the pre-7.0 sensor fusion structures and give us the ability to do run
180 /// time driver installation.
182  registerDeviceInfo_t deviceInfo; ///< I2C device context
183  void *bus_driver; ///< should be of type (ARM_DRIVER_I2C* for I2C-based sensors, ARM_DRIVER_SPI* for SPI)
184  registerDeviceInfo_t *busInfo; ///< information required for bus power management
185  uint16_t addr; ///< I2C address if applicable
186  uint16_t isInitialized; ///< Bitfields to indicate sensor is active (use SensorBitFields from build.h)
187  spiSlaveSpecificParams_t slaveParams; ///< SPI specific parameters. Not used for I2C.
188  struct PhysicalSensor *next; ///< pointer to next sensor in this linked list
189  uint16_t schedule; ///< Parameter to control sensor sampling rate
190  initializeSensor_t *initialize; ///< pointer to function to initialize sensor using the supplied drivers
191  readSensor_t *read; ///< pointer to function to read sensor using the supplied drivers
192 };
193 
194 // Now start "standard" sensor fusion structure definitions
195 
196 /// \brief The PressureSensor structure stores raw and processed measurements for an altimeter.
197 ///
198 /// The PressureSensor structure stores raw and processed measurements, as well as
199 /// metadata for a pressure sensor/altimeter.
201 {
202  uint8_t iWhoAmI; ///< sensor whoami
203  bool isEnabled; ///< true if the device is sampling
204  int32_t iH; ///< most recent unaveraged height (counts)
205  int32_t iP; ///< most recent unaveraged pressure (counts)
206  float fH; ///< most recent unaveraged height (m)
207  float fT; ///< most recent unaveraged temperature (C)
208  float fmPerCount; ///< meters per count
209  float fCPerCount; ///< degrees Celsius per count
210  int16_t iT; ///< most recent unaveraged temperature (counts)
211 };
212 
213 /// \brief The AccelSensor structure stores raw and processed measurements for a 3-axis accelerometer.
214 ///
215 /// The AccelSensor structure stores raw and processed measurements, as well as metadata
216 /// for a single 3-axis accelerometer. This structure is
217 /// normally "fed" by the sensor driver and "consumed" by the fusion routines.
219 {
220  uint8_t iWhoAmI; ///< sensor whoami
221  bool isEnabled; ///< true if the device is sampling
222  uint8_t iFIFOCount; ///< number of measurements read from FIFO
223  uint16_t iFIFOExceeded; ///< Number of samples received in excess of software FIFO size
224  int16_t iGsFIFO[ACCEL_FIFO_SIZE][3]; ///< FIFO measurements (counts)
225  // End of common fields which can be referenced via FifoSensor union type
226  float fGs[3]; ///< averaged measurement (g)
227  float fGc[3]; ///< averaged precision calibrated measurement (g)
228  float fgPerCount; ///< g per count
229  float fCountsPerg; ///< counts per g
230  int16_t iGs[3]; ///< averaged measurement (counts)
231  int16_t iGc[3]; ///< averaged precision calibrated measurement (counts)
232  int16_t iCountsPerg; ///< counts per g
233 };
234 
235 /// \brief The MagSensor structure stores raw and processed measurements for a 3-axis magnetic sensor.
236 ///
237 /// The MagSensor structure stores raw and processed measurements, as well as metadata
238 /// for a single 3-axis magnetometer. This structure is
239 /// normally "fed" by the sensor driver and "consumed" by the fusion routines.
240 struct MagSensor
241 {
242  uint8_t iWhoAmI; ///< sensor whoami
243  bool isEnabled; ///< true if the device is sampling
244  uint8_t iFIFOCount; ///< number of measurements read from FIFO
245  uint16_t iFIFOExceeded; ///< Number of samples received in excess of software FIFO size
246  int16_t iBsFIFO[MAG_FIFO_SIZE][3]; ///< FIFO measurements (counts)
247  // End of common fields which can be referenced via FifoSensor union type
248  float fBs[3]; ///< averaged un-calibrated measurement (uT)
249  float fBc[3]; ///< averaged calibrated measurement (uT)
250  float fuTPerCount; ///< uT per count
251  float fCountsPeruT; ///< counts per uT
252  int16_t iBs[3]; ///< averaged uncalibrated measurement (counts)
253  int16_t iBc[3]; ///< averaged calibrated measurement (counts)
254  int16_t iCountsPeruT; ///< counts per uT
255 };
256 
257 /// \brief The GyroSensor structure stores raw and processed measurements for a 3-axis gyroscope.
258 ///
259 /// The GyroSensor structure stores raw and processed measurements, as well as metadata
260 /// for a single 3-axis gyroscope. This structure is
261 /// normally "fed" by the sensor driver and "consumed" by the fusion routines.
263 {
264  uint8_t iWhoAmI; ///< sensor whoami
265  bool isEnabled; ///< true if the device is sampling
266  uint8_t iFIFOCount; ///< number of measurements read from FIFO
267  uint16_t iFIFOExceeded; ///< Number of samples received in excess of software FIFO size
268  int16_t iYsFIFO[GYRO_FIFO_SIZE][3]; ///< FIFO measurements (counts)
269  // End of common fields which can be referenced via FifoSensor union type
270  float fYs[3]; ///< averaged measurement (deg/s)
271  float fDegPerSecPerCount; ///< deg/s per count
272  int16_t iCountsPerDegPerSec; ///< counts per deg/s
273  int16_t iYs[3]; ///< average measurement (counts)
274 };
275 
276 /// \brief The FifoSensor union allows us to use common pointers for Accel, Mag & Gyro logical sensor structures.
277 ///
278 /// Common elements include: iWhoAmI, isEnabled, iFIFOCount, iFIFOExceeded and the FIFO itself.
279 union FifoSensor {
280  struct GyroSensor Gyro;
281  struct MagSensor Mag;
282  struct AccelSensor Accel;
283 };
284 
285 /// The SV_1DOF_P_BASIC structure contains state information for a pressure sensor/altimeter.
287 {
288  float fLPH; ///< low pass filtered height (m)
289  float fLPT; ///< low pass filtered temperature (C)
290  float fdeltat; ///< fusion time interval (s)
291  float flpf; ///< low pass filter coefficient
292  int32_t systick; ///< systick timer
293  int8_t resetflag; ///< flag to request re-initialization on next pass
294 };
295 
296 /// This is the 3DOF basic accelerometer state vector structure.
298 {
299  // start: elements common to all motion state vectors
300  float fLPPhi; ///< low pass roll (deg)
301  float fLPThe; ///< low pass pitch (deg)
302  float fLPPsi; ///< low pass yaw (deg)
303  float fLPRho; ///< low pass compass (deg)
304  float fLPChi; ///< low pass tilt from vertical (deg)
305  float fLPR[3][3]; ///< low pass filtered orientation matrix
306  Quaternion fLPq; ///< low pass filtered orientation quaternion
307  float fLPRVec[3]; ///< rotation vector
308  float fOmega[3]; ///< angular velocity (deg/s)
309  int32_t systick; ///< systick timer
310  // end: elements common to all motion state vectors
311  float fR[3][3]; ///< unfiltered orientation matrix
312  Quaternion fq; ///< unfiltered orientation quaternion
313  float fdeltat; ///< fusion time interval (s)
314  float flpf; ///< low pass filter coefficient
315  int8_t resetflag; ///< flag to request re-initialization on next pass
316 };
317 
318 /// This is the 3DOF basic magnetometer state vector structure/
320 {
321  // start: elements common to all motion state vectors
322  float fLPPhi; ///< low pass roll (deg)
323  float fLPThe; ///< low pass pitch (deg)
324  float fLPPsi; ///< low pass yaw (deg)
325  float fLPRho; ///< low pass compass (deg)
326  float fLPChi; ///< low pass tilt from vertical (deg)
327  float fLPR[3][3]; ///< low pass filtered orientation matrix
328  Quaternion fLPq; ///< low pass filtered orientation quaternion
329  float fLPRVec[3]; ///< rotation vector
330  float fOmega[3]; ///< angular velocity (deg/s)
331  int32_t systick; ///< systick timer
332  // end: elements common to all motion state vectors
333  float fR[3][3]; ///< unfiltered orientation matrix
334  Quaternion fq; ///< unfiltered orientation quaternion
335  float fdeltat; ///< fusion time interval (s)
336  float flpf; ///< low pass filter coefficient
337  int8_t resetflag; ///< flag to request re-initialization on next pass
338 };
339 
340 /// SV_3DOF_Y_BASIC structure is the 3DOF basic gyroscope state vector structure.
342 {
343  // start: elements common to all motion state vectors
344  float fPhi; ///< roll (deg)
345  float fThe; ///< pitch (deg)
346  float fPsi; ///< yaw (deg)
347  float fRho; ///< compass (deg)
348  float fChi; ///< tilt from vertical (deg)
349  float fR[3][3]; ///< unfiltered orientation matrix
350  Quaternion fq; ///< unfiltered orientation quaternion
351  float fRVec[3]; ///< rotation vector
352  float fOmega[3]; ///< angular velocity (deg/s)
353  int32_t systick; ///< systick timer
354  // end: elements common to all motion state vectors
355  float fdeltat; ///< fusion filter sampling interval (s)
356  int8_t resetflag; ///< flag to request re-initialization on next pass
357 };
358 
359 /// SV_6DOF_GB_BASIC is the 6DOF basic accelerometer and magnetometer state vector structure.
361 {
362  // start: elements common to all motion state vectors
363  float fLPPhi; ///< low pass roll (deg)
364  float fLPThe; ///< low pass pitch (deg)
365  float fLPPsi; ///< low pass yaw (deg)
366  float fLPRho; ///< low pass compass (deg)
367  float fLPChi; ///< low pass tilt from vertical (deg)
368  float fLPR[3][3]; ///< low pass filtered orientation matrix
369  Quaternion fLPq; ///< low pass filtered orientation quaternion
370  float fLPRVec[3]; ///< rotation vector
371  float fOmega[3]; ///< virtual gyro angular velocity (deg/s)
372  int32_t systick; ///< systick timer
373  // end: elements common to all motion state vectors
374  float fR[3][3]; ///< unfiltered orientation matrix
375  Quaternion fq; ///< unfiltered orientation quaternion
376  float fDelta; ///< unfiltered inclination angle (deg)
377  float fLPDelta; ///< low pass filtered inclination angle (deg)
378  float fdeltat; ///< fusion time interval (s)
379  float flpf; ///< low pass filter coefficient
380  int8_t resetflag; ///< flag to request re-initialization on next pass
381 };
382 
383 /// SV_6DOF_GY_KALMAN is the 6DOF Kalman filter accelerometer and gyroscope state vector structure.
385 {
386  // start: elements common to all motion state vectors
387  float fPhiPl; ///< roll (deg)
388  float fThePl; ///< pitch (deg)
389  float fPsiPl; ///< yaw (deg)
390  float fRhoPl; ///< compass (deg)
391  float fChiPl; ///< tilt from vertical (deg)
392  float fRPl[3][3]; ///< a posteriori orientation matrix
393  Quaternion fqPl; ///< a posteriori orientation quaternion
394  float fRVecPl[3]; ///< rotation vector
395  float fOmega[3]; ///< average angular velocity (deg/s)
396  int32_t systick; ///< systick timer;
397  // end: elements common to all motion state vectors
398  float fQw6x6[6][6]; ///< covariance matrix Qw
399  float fK6x3[6][3]; ///< kalman filter gain matrix K
400  float fQwCT6x3[6][3]; ///< Qw.C^T matrix
401  float fQv; ///< measurement noise covariance matrix leading diagonal
402  float fZErr[3]; ///< measurement error vector
403  float fqgErrPl[3]; ///< gravity vector tilt orientation quaternion error (dimensionless)
404  float fbPl[3]; ///< gyro offset (deg/s)
405  float fbErrPl[3]; ///< gyro offset error (deg/s)
406  float fAccGl[3]; ///< linear acceleration (g) in global frame
407  float fdeltat; ///< sensor fusion interval (s)
408  float fAlphaOver2; ///< PI / 180 * fdeltat / 2
409  float fAlphaSqOver4; ///< (PI / 180 * fdeltat)^2 / 4
410  float fAlphaSqQvYQwbOver12; ///< (PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
411  float fAlphaQwbOver6; ///< (PI / 180 * fdeltat) * Qwb / 6
412  float fQwbOver3; ///< Qwb / 3
413  float fMaxGyroOffsetChange; ///< maximum permissible gyro offset change per iteration (deg/s)
414  int8_t resetflag; ///< flag to request re-initialization on next pass
415 };
416 
417 /// SV_9DOF_GBY_KALMAN is the 9DOF Kalman filter accelerometer, magnetometer and gyroscope state vector structure.
419 {
420  // start: elements common to all motion state vectors
421  float fPhiPl; ///< roll (deg)
422  float fThePl; ///< pitch (deg)
423  float fPsiPl; ///< yaw (deg)
424  float fRhoPl; ///< compass (deg)
425  float fChiPl; ///< tilt from vertical (deg)
426  float fRPl[3][3]; ///< a posteriori orientation matrix
427  Quaternion fqPl; ///< a posteriori orientation quaternion
428  float fRVecPl[3]; ///< rotation vector
429  float fOmega[3]; ///< average angular velocity (deg/s)
430  int32_t systick; ///< systick timer;
431  // end: elements common to all motion state vectors
432  float fQw9x9[9][9]; ///< covariance matrix Qw
433  float fK9x6[9][6]; ///< kalman filter gain matrix K
434  float fQwCT9x6[9][6]; ///< Qw.C^T matrix
435  float fZErr[6]; ///< measurement error vector
436  float fQv6x1[6]; ///< measurement noise covariance matrix leading diagonal
437  float fDeltaPl; ///< a posteriori inclination angle from Kalman filter (deg)
438  float fsinDeltaPl; ///< sin(fDeltaPl)
439  float fcosDeltaPl; ///< cos(fDeltaPl)
440  float fqgErrPl[3]; ///< gravity vector tilt orientation quaternion error (dimensionless)
441  float fqmErrPl[3]; ///< geomagnetic vector tilt orientation quaternion error (dimensionless)
442  float fbPl[3]; ///< gyro offset (deg/s)
443  float fbErrPl[3]; ///< gyro offset error (deg/s)
444  float fAccGl[3]; ///< linear acceleration (g) in global frame
445  float fVelGl[3]; ///< velocity (m/s) in global frame
446  float fDisGl[3]; ///< displacement (m) in global frame
447  float fdeltat; ///< sensor fusion interval (s)
448  float fgdeltat; ///< g (m/s2) * fdeltat
449  float fAlphaOver2; ///< PI / 180 * fdeltat / 2
450  float fAlphaSqOver4; ///< (PI / 180 * fdeltat)^2 / 4
451  float fAlphaSqQvYQwbOver12; ///< (PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
452  float fAlphaQwbOver6; ///< (PI / 180 * fdeltat) * Qwb / 6
453  float fQwbOver3; ///< Qwb / 3
454  float fMaxGyroOffsetChange; ///< maximum permissible gyro offset change per iteration (deg/s)
455  int8_t iFirstAccelMagLock; ///< denotes that 9DOF orientation has locked to 6DOF eCompass
456  int8_t resetflag; ///< flag to request re-initialization on next pass
457 };
458 
459 /// Excluding SV_1DOF_P_BASIC, Any of the SV_ fusion structures above could
460 /// be cast to type SV_COMMON for dereferencing.
461 struct SV_COMMON {
462  float fPhi; ///< roll (deg)
463  float fThe; ///< pitch (deg)
464  float fPsi; ///< yaw (deg)
465  float fRho; ///< compass (deg)
466  float fChi; ///< tilt from vertical (deg)
467  float fRM[3][3]; ///< orientation matrix
468  Quaternion fq; ///< orientation quaternion
469  float fRVec[3]; ///< rotation vector
470  float fOmega[3]; ///< average angular velocity (deg/s)
471  int32_t systick; ///< systick timer;
472 };
473 typedef struct SV_COMMON *SV_ptr;
474 
475 /// \brief The top level fusion structure
476 ///
477 /// The top level fusion structure grows/shrinks based upon flag definitions
478 /// contained in build.h. These same flags will populate the .iFlags field for
479 /// run-time access.
480 typedef struct SensorFusionGlobals
481 {
482  // Subsystem Pointers
483  ///@{
484  /// @name SubsystemPointers
485  /// The Status and Control subsystems can be used as-is, or completely
486  /// replaced with alternate implementations, as long as those implementations
487  /// provide the same interfaces defined in control.h and status.h.
490  ///@}
491  ///@{
492  /// @name MiscFields
493  uint32_t iFlags; ///< a bit-field of sensors and algorithms used
494  struct PhysicalSensor *pSensors; ///< a linked list of physical sensors
495  volatile uint8_t iPerturbation; ///< test perturbation to be applied
496  // Book-keeping variables
497  int32_t loopcounter; ///< counter incrementing each iteration of sensor fusion (typically 25Hz)
498  int32_t systick_I2C; ///< systick counter to benchmark I2C reads
499  int32_t systick_Spare; ///< systick counter for counts spare waiting for timing interrupt
500  ///@}
501  ///@{
502  /// @name SensorRelatedStructures
503  /// These structures provide homes for sensor readings, as well as
504  /// various calibration functions. Only those needed for a specific
505  /// build are included.
506 #if F_1DOF_P_BASIC
507  struct PressureSensor Pressure; ///< pressure sensor storage
508 #endif
509 #if F_USING_ACCEL
510  struct AccelSensor Accel; ///< accelerometer storage
511  struct AccelCalibration AccelCal; ///< structures for accel calibration
512  struct AccelBuffer AccelBuffer; ///< storage for points used for calibration
513 #endif
514 #if F_USING_MAG
515  struct MagSensor Mag; ///< magnetometer storage
516  struct MagCalibration MagCal; ///< mag cal storage
517  struct MagBuffer MagBuffer; ///< mag cal constellation points
518 #endif
519 #if F_USING_GYRO
520  struct GyroSensor Gyro; ///< gyro storage
521 #endif
522  ///@}
523  ///@{
524  /// @name FusionSpecificStructures
525 #if F_1DOF_P_BASIC
526  struct SV_1DOF_P_BASIC SV_1DOF_P_BASIC; ///< Pressure
527 #endif
528 #if F_3DOF_G_BASIC
529  struct SV_3DOF_G_BASIC SV_3DOF_G_BASIC; ///< Gravity
530 #endif
531 #if F_3DOF_B_BASIC
532  struct SV_3DOF_B_BASIC SV_3DOF_B_BASIC; ///< Magnetic
533 #endif
534 #if F_3DOF_Y_BASIC
535  struct SV_3DOF_Y_BASIC SV_3DOF_Y_BASIC; ///< Gyro
536 #endif
537 #if F_6DOF_GB_BASIC // 6DOF accel and mag eCompass: (accel + mag)
538  struct SV_6DOF_GB_BASIC SV_6DOF_GB_BASIC; ///< eCompass (Gravity + Magnetic)
539 #endif
540 #if F_6DOF_GY_KALMAN
541  struct SV_6DOF_GY_KALMAN SV_6DOF_GY_KALMAN; ///< 6-axis gravity + angular rates Kalman storage
542 #endif
543 #if F_9DOF_GBY_KALMAN
544  struct SV_9DOF_GBY_KALMAN SV_9DOF_GBY_KALMAN; ///< 9-axis storage
545 #endif
546  ///@}
547  ///@{
548  /// @name FunctionPointers
549  /// Function pointers (the SF library external interface)
550  installSensor_t *installSensor; ///< function for installing a new sensor into t
551  initializeFusionEngine_t *initializeFusionEngine ; ///< set sensor fusion structures to initial values
552  applyPerturbation_t *applyPerturbation ; ///< apply step function for testing purposes
553  readSensors_t *readSensors; ///< read all physical sensors
554  runFusion_t *runFusion; ///< run the fusion routines
555  conditionSensorReadings_t *conditionSensorReadings; ///< preprocessing step for sensor fusion
556  clearFIFOs_t *clearFIFOs; ///< clear sensor FIFOs
557  setStatus_t *setStatus; ///< change status indicator immediately
558  setStatus_t *queueStatus; ///< queue status change for next regular interval
559  updateStatus_t *updateStatus; ///< status=next status
560  updateStatus_t *testStatus; ///< increment to next enumerated status value (test only)
561  ///@}
563 
564 // The following functions are defined in sensor_fusion.c
566  SensorFusionGlobals *sfg, ///< Global data structure pointer
567  struct StatusSubsystem *pStatusSubsystem, ///< Status subsystem pointer
568  struct ControlSubsystem *pControlSubsystem ///< Control subsystem pointer
569 );
572 /// conditionSensorReadings() transforms raw software FIFO readings into forms that
573 /// can be consumed by the sensor fusion engine. This include sample averaging
574 /// and (in the case of the gyro) integrations, applying hardware abstraction layers,
575 /// and calibration functions.
576 /// This function is normally involved via the "sfg." global pointer.
578  SensorFusionGlobals *sfg ///< Global data structure pointer
579 );
580 void clearFIFOs(
581  SensorFusionGlobals *sfg ///< Global data structure pointer
582 );
585 void zeroArray(
586  struct StatusSubsystem *pStatus, ///< Status subsystem pointer
587  void* data, ///< pointer to array to be zeroed
588  uint16_t size, ///< data type size = 8, 16 or 32
589  uint16_t numElements, ///< number of elements to zero out
590  uint8_t check ///< true if you would like to verify writes, false otherwise
591 );
592 /// \brief conditionSample ensures that we never encounter the maximum negative two's complement
593 /// value for a 16-bit variable (-32768).
594 ///
595 /// conditionSample ensures that we never encounter the maximum negative two's complement
596 /// value for a 16-bit variable (-32768). This value cannot be negated, because the maximum
597 /// positive value is +32767. We need the ability to negate to gaurantee that subsequent
598 /// HAL operations can be run successfully.
599 void conditionSample(
600  int16_t sample[3] ///< 16-bit register value from triaxial sensor read
601 );
602 
603 // The following functions are defined in <hal_board_name>.c.
604 // Please note that these are board-dependent
605 
606 /// \brief addToFifo is called from within sensor driver read functions
607 ///
608 /// addToFifo is called from within sensor driver read functions to transfer new readings into
609 /// the sensor structure corresponding to accel, gyro or mag. This function ensures that the software
610 /// FIFOs are not overrun.
611 ///
612 /// example usage: if (status==SENSOR_ERROR_NONE) addToFifo((FifoSensor*) &(sfg->Mag), MAG_FIFO_SIZE, sample);
613 void addToFifo(
614  union FifoSensor *sensor, ///< pointer to structure of type AccelSensor, MagSensor or GyroSensor
615  uint16_t maxFifoSize, ///< the size of the software (not hardware) FIFO
616  int16_t sample[3] ///< the sample to add
617 );
618 /// \brief Apply the accelerometer Hardware Abstraction Layer
619 void ApplyAccelHAL(
620  struct AccelSensor *Accel ///< pointer to accelerometer logical sensor
621 );
622 /// \brief Apply the magnetometer Hardware Abstraction Layer
623 void ApplyMagHAL(
624  struct MagSensor *Mag ///< pointer to magnetometer logical sensor
625 );
626 /// \brief Apply the gyroscope Hardware Abstraction Layer
627 void ApplyGyroHAL(
628  struct GyroSensor *Gyro ///< pointer to gyroscope logical sensor
629 );
630 /// \brief ApplyPerturbation is a reverse unit-step test function
631 ///
632 /// The ApplyPerturbation function applies a user-specified step function to
633 /// prior fusion results which is then "released" in the next fusion cycle.
634 /// When used in conjuction with the NXP Sensor Fusion Toolbox, this provides
635 /// a visual indication of the dynamic behavior of the library. ApplyPerturbation()
636 /// is defined in debug.c.
637 
638 // The following function is defined in debug.c:
640 
641 #include "matrix.h" // this is only down here so we can take advantage of _t style typedefs above
642 
643 #endif // SENSOR_FUSION_TYPES_H
float fCPerCount
degrees Celsius per count
float fgPerCount
g per count
void() ssUpdateStatus_t(struct StatusSubsystem *pStatus)
Initializing sensors and algorithms.
float fDeltaPl
a posteriori inclination angle from Kalman filter (deg)
void() conditionSensorReadings_t(struct SensorFusionGlobals *sfg)
enum quaternion quaternion_type
the quaternion type to be transmitted
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:80
void ApplyMagHAL(struct MagSensor *Mag)
Apply the magnetometer Hardware Abstraction Layer.
float fAlphaSqOver4
(PI / 180 * fdeltat)^2 / 4
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
float fChi
tilt from vertical (deg)
float fThePl
pitch (deg)
int8_t() readSensor_t(struct PhysicalSensor *sensor, struct SensorFusionGlobals *sfg)
void conditionSensorReadings(SensorFusionGlobals *sfg)
void * bus_driver
should be of type (ARM_DRIVER_I2C* for I2C-based sensors, ARM_DRIVER_SPI* for SPI) ...
int32_t systick
systick timer
float fMaxGyroOffsetChange
maximum permissible gyro offset change per iteration (deg/s)
float fMaxGyroOffsetChange
maximum permissible gyro offset change per iteration (deg/s)
float fAlphaQwbOver6
(PI / 180 * fdeltat) * Qwb / 6
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
float fdeltat
fusion time interval (s)
updateStatus_t * testStatus
increment to next enumerated status value (test only)
float fPsi
yaw (deg)
float fmPerCount
meters per count
float fsinDeltaPl
sin(fDeltaPl)
float fDegPerSecPerCount
deg/s per count
void ApplyAccelHAL(struct AccelSensor *Accel)
Apply the accelerometer Hardware Abstraction Layer.
struct PhysicalSensor * next
pointer to next sensor in this linked list
SensorFusionGlobals sfg
float fQv
measurement noise covariance matrix leading diagonal
volatile uint8_t iPerturbation
test perturbation to be applied
float fPsiPl
yaw (deg)
void initSensorFusionGlobals(SensorFusionGlobals *sfg, struct StatusSubsystem *pStatusSubsystem, struct ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
Definition: sensor_fusion.c:77
int32_t systick
systick timer
int32_t systick
systick timer;
Receiving commands over wireless interface (momentary)
bool isEnabled
true if the device is sampling
int32_t systick_Spare
systick counter for counts spare waiting for timing interrupt
float fLPPsi
low pass yaw (deg)
Functions to convert between various orientation representations.
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:76
uint8_t data[FXLS8962_DATA_SIZE]
float fH
most recent unaveraged height (m)
void conditionSample(int16_t sample[3])
conditionSample ensures that we never encounter the maximum negative two&#39;s complement value for a 16-...
uint16_t schedule
Parameter to control sensor sampling rate.
int32_t status
uint16_t iFIFOExceeded
Number of samples received in excess of software FIFO size.
int16_t iCountsPerg
counts per g
int32_t systick
systick timer
void() updateStatus_t(struct SensorFusionGlobals *sfg)
float fLPPhi
low pass roll (deg)
installSensor_t * installSensor
function for installing a new sensor into t
float fuTPerCount
uT per count
Quaternion fLPq
low pass filtered orientation quaternion
registerDeviceInfo_t * busInfo
information required for bus power management
struct SV_COMMON * SV_ptr
float fdeltat
fusion time interval (s)
This is the 3DOF basic magnetometer state vector structure/.
Quaternion fq
unfiltered orientation quaternion
#define MAG_FIFO_SIZE
FXOS8700 (mag), MAG3110 have no FIFO so equivalent to 1 element FIFO.
void clearFIFOs(SensorFusionGlobals *sfg)
Function to clear FIFO at the end of each fusion computation.
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:77
These are the state definitions for the status subsystem.
uint8_t iWhoAmI
sensor whoami
float fThe
pitch (deg)
updateStatus_t * updateStatus
status=next status
int16_t iT
most recent unaveraged temperature (counts)
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:78
int8_t resetflag
flag to request re-initialization on next pass
The AccelSensor structure stores raw and processed measurements for a 3-axis accelerometer.
uint8_t uint8
Definition: sensor_fusion.h:68
float fAlphaSqQvYQwbOver12
(PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
int32_t int32
Definition: sensor_fusion.h:67
he ControlSubsystem encapsulates command and data streaming functions.
Definition: control.h:68
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:79
#define ACCEL_FIFO_SIZE
FXOS8700 (accel), MMA8652, FXLS8952 all have 32 element FIFO.
void() initializeFusionEngine_t(struct SensorFusionGlobals *sfg)
Quaternion fq
unfiltered orientation quaternion
SV_9DOF_GBY_KALMAN is the 9DOF Kalman filter accelerometer, magnetometer and gyroscope state vector s...
float fDelta
unfiltered inclination angle (deg)
int16_t iCountsPerDegPerSec
counts per deg/s
The MagSensor structure stores raw and processed measurements for a 3-axis magnetic sensor...
float fRho
compass (deg)
runFusion_t runFusion
bool isEnabled
true if the device is sampling
uint32_t uint32
Definition: sensor_fusion.h:70
StatusSubsystem() provides an object-like interface for communicating status to the user...
Definition: status.h:48
The top level fusion structure.
struct PhysicalSensor * pSensors
a linked list of physical sensors
int8_t() initializeSensor_t(struct PhysicalSensor *sensor, struct SensorFusionGlobals *sfg)
void() clearFIFOs_t(struct SensorFusionGlobals *sfg)
float fT
most recent unaveraged temperature (C)
#define GYRO_FIFO_SIZE
FXAX21000, FXAS21002 have 32 element FIFO.
The SV_1DOF_P_BASIC structure contains state information for a pressure sensor/altimeter.
float fgdeltat
g (m/s2) * fdeltat
Recoverable FAULT = something went wrong, but we can keep going.
initializeSensor_t * initialize
pointer to function to initialize sensor using the supplied drivers
float fQwbOver3
Qwb / 3.
float flpf
low pass filter coefficient
accelerometer measurement buffer
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
float fPsi
yaw (deg)
float fAlphaOver2
PI / 180 * fdeltat / 2.
SV_6DOF_GY_KALMAN is the 6DOF Kalman filter accelerometer and gyroscope state vector structure...
initializeFusionEngine_t initializeFusionEngine
int8_t iFirstAccelMagLock
denotes that 9DOF orientation has locked to 6DOF eCompass
int32_t systick
systick timer
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
float fLPThe
low pass pitch (deg)
float fLPChi
low pass tilt from vertical (deg)
float fLPPhi
low pass roll (deg)
uint16_t addr
I2C address if applicable.
int8_t resetflag
flag to request re-initialization on next pass
Quaternion fqPl
a posteriori orientation quaternion
quaternion
the quaternion type to be transmitted
Definition: sensor_fusion.h:74
int32_t systick
systick timer
float fAlphaSqQvYQwbOver12
(PI / 180 * fdeltat)^2 * (QvY + Qwb) / 12
Quaternion fq
unfiltered orientation quaternion
uint8_t iFIFOCount
number of measurements read from FIFO
int32_t iP
most recent unaveraged pressure (counts)
int8_t resetflag
flag to request re-initialization on next pass
setStatus_t * setStatus
change status indicator immediately
float fdeltat
fusion filter sampling interval (s)
Quaternion fqPl
a posteriori orientation quaternion
int32_t systick
systick timer;
float fPhi
roll (deg)
The FifoSensor union allows us to use common pointers for Accel, Mag & Gyro logical sensor structures...
SV_3DOF_Y_BASIC structure is the 3DOF basic gyroscope state vector structure.
float flpf
low pass filter coefficient
float fLPT
low pass filtered temperature (C)
Implements accelerometer calibration routines.
float fRho
compass (deg)
Receiving commands over wired interface (momentary)
Running in reduced power mode.
uint16_t isInitialized
Bitfields to indicate sensor is active (use SensorBitFields from build.h)
spiSlaveSpecificParams_t slaveParams
SPI specific parameters. Not used for I2C.
precision accelerometer calibration structure
Matrix manipulation functions.
Lower level magnetic calibration interface.
registerDeviceInfo_t deviceInfo
I2C device context.
float flpf
low pass filter coefficient
float fAlphaSqOver4
(PI / 180 * fdeltat)^2 / 4
Quaternion fq
orientation quaternion
float fThePl
pitch (deg)
bool isEnabled
true if the device is sampling
unsigned char byte
Definition: sensor_fusion.h:64
clearFIFOs_t * clearFIFOs
clear sensor FIFOs
float fPhiPl
roll (deg)
struct StatusSubsystem * pStatusSubsystem
float fCountsPerg
counts per g
float fLPRho
low pass compass (deg)
int8_t resetflag
flag to request re-initialization on next pass
void addToFifo(union FifoSensor *sensor, uint16_t maxFifoSize, int16_t sample[3])
addToFifo is called from within sensor driver read functions
float fAlphaOver2
PI / 180 * fdeltat / 2.
float fChi
tilt from vertical (deg)
int8_t() readSensors_t(struct SensorFusionGlobals *sfg, uint16_t read_loop_counter)
float fChiPl
tilt from vertical (deg)
uint8_t iFIFOCount
number of measurements read from FIFO
uint32_t iFlags
a bit-field of sensors and algorithms used
int16_t iCountsPeruT
counts per uT
Quaternion fLPq
low pass filtered orientation quaternion
float fLPThe
low pass pitch (deg)
int32_t iH
most recent unaveraged height (counts)
runFusion_t * runFusion
run the fusion routines
float fAlphaQwbOver6
(PI / 180 * fdeltat) * Qwb / 6
readSensors_t readSensors
struct SensorFusionGlobals SensorFusionGlobals
The top level fusion structure.
float fRhoPl
compass (deg)
Non-recoverable FAULT = something went very wrong.
Magnetic Calibration Structure.
Definition: magnetic.h:81
Quaternion fLPq
low pass filtered orientation quaternion
int8_t resetflag
flag to request re-initialization on next pass
float fRhoPl
compass (deg)
float fPhi
roll (deg)
typedef int32_t(DATA_FORMAT_Append_t))(void *pData
The interface function to append the data on the formated stream.
uint32_t size
float fcosDeltaPl
cos(fDeltaPl)
quaternion structure definition
Definition: orientation.h:46
void ApplyGyroHAL(struct GyroSensor *Gyro)
Apply the gyroscope Hardware Abstraction Layer.
uint16_t uint16
Definition: sensor_fusion.h:69
int8_t() installSensor_t(struct SensorFusionGlobals *sfg, struct PhysicalSensor *sensor, uint16_t addr, uint16_t schedule, void *bus_driver, registerDeviceInfo_t *busInfo, initializeSensor_t *initialize, readSensor_t *read)
installSensor_t installSensor
int32_t systick_I2C
systick counter to benchmark I2C reads
uint8_t iWhoAmI
sensor whoami
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:75
readSensors_t * readSensors
read all physical sensors
void() applyPerturbation_t(struct SensorFusionGlobals *sfg)
float fdeltat
sensor fusion interval (s)
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
float fQwbOver3
Qwb / 3.
float fPhiPl
roll (deg)
struct ControlSubsystem * pControlSubsystem
float fdeltat
fusion time interval (s)
float fLPRho
low pass compass (deg)
void() setStatus_t(struct SensorFusionGlobals *sfg, fusion_status_t status)
float fChiPl
tilt from vertical (deg)
readSensor_t * read
pointer to function to read sensor using the supplied drivers
float fLPChi
low pass tilt from vertical (deg)
fusion_status_t
Application-specific serial communications system.
float fCountsPeruT
counts per uT
float fThe
pitch (deg)
bool isEnabled
true if the device is sampling
float flpf
low pass filter coefficient
uint8_t iWhoAmI
sensor whoami
int16_t int16
Definition: sensor_fusion.h:66
float fLPPsi
low pass yaw (deg)
float fLPRho
low pass compass (deg)
float fdeltat
fusion time interval (s)
SV_6DOF_GB_BASIC is the 6DOF basic accelerometer and magnetometer state vector structure.
void() ssSetStatus_t(struct StatusSubsystem *pStatus, fusion_status_t status)
This structure defines the device specific info required by register I/O.
Definition: sensor_drv.h:128
float fLPChi
low pass tilt from vertical (deg)
Operation is Nominal.
setStatus_t * queueStatus
queue status change for next regular interval
This is the 3DOF basic accelerometer state vector structure.
float fLPThe
low pass pitch (deg)
float fLPPsi
low pass yaw (deg)
uint8_t iWhoAmI
sensor whoami
float fPsiPl
yaw (deg)
This structure defines the spi slave command format.
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
int8_t resetflag
flag to request re-initialization on next pass
int8_t int8
Definition: sensor_fusion.h:65
The register_io_spi.h file declares low-level interface functions for reading and writing sensor regi...
uint8_t iFIFOCount
number of measurements read from FIFO
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)
The GyroSensor structure stores raw and processed measurements for a 3-axis gyroscope.
int32_t systick
systick timer;
applyPerturbation_t ApplyPerturbation
ApplyPerturbation is a reverse unit-step test function.
float fLPH
low pass filtered height (m)
int8_t resetflag
flag to request re-initialization on next pass
float fdeltat
sensor fusion interval (s)
void zeroArray(struct StatusSubsystem *pStatus, void *data, uint16_t size, uint16_t numElements, uint8_t check)
float fLPDelta
low pass filtered inclination angle (deg)
void() runFusion_t(struct SensorFusionGlobals *sfg)
Quaternion fq
unfiltered orientation quaternion
The PressureSensor structure stores raw and processed measurements for an altimeter.
float fLPPhi
low pass roll (deg)