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