ISSDK  1.8
IoT Sensing Software Development Kit
debug.c
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 /*! \file debug.c
10  \brief ApplyPerturbation function used to analyze dynamic performance
11 
12  The ApplyPerturbation function applies a user-specified step function to
13  prior fusion results which is then "released" in the next fusion cycle.
14  When used in conjustion with the NXP Sensor Fusion Toolbox, this provides
15  a visual indication of the dynamic behavior of the library.
16 
17  Also included is some code for white-box testing within the IAR debug
18  environment. It can be used to evaluate propagation delays for tilt and
19  eCompass algorithms. It makes no sense with regard to "Rotation", because
20  that algorithm is simple gyro integration, and will never return to the
21  starting point. It will also overestimate delays for the kalman filters,
22  as there is no actual gyro data corresponding to the simulated step function.
23  So those filters are not operating as they would in the normal world.
24 */
25 
26 #include "sensor_fusion.h"
27 #include "control.h"
28 #include "stdlib.h"
29 #include "build.h"
30 
31 /// The ApplyPerturbation function applies a user-specified step function to
32 /// prior fusion results which is then "released" in the next fusion cycle.
33 /// When used in conjustion with the NXP Sensor Fusion Toolbox, this provides
34 /// a visual indication of the dynamic behavior of the library.
35 /// This function is normally involved via the "sfg." global pointer.
37 {
38 #ifdef INCLUDE_DEBUG_FUNCTIONS
39  // volatile keyword used to force compiler not to optimize out these
40  // variables. this does unfortunately result in a couple of warnings (which
41  // can be ignored) farther down in this code.
42  volatile static uint16_t iTestProgress; ///< Perturbation test status
43  volatile static uint16_t iTestDelay = 0; ///< Measured delay
44  //volatile static uint16_t iTestAngle = 0; ///< Integer Residual angle associated with measured delay
45  volatile float angle=0.0f; ///< Float Residual angle associated with measured delay
46  volatile static float threshold=0;
47  static Quaternion StartingQ = {
48  .q0 = 1.0,
49  .q1 = 0.0,
50  .q2 = 0.0,
51  .q3 = 0.0
52  };
53  Quaternion CurrentQ = {
54  .q0 = 1.0,
55  .q1 = 0.0,
56  .q2 = 0.0,
57  .q3 = 0.0
58  };
59  // cache local copies of control flags so we don't have to keep dereferencing pointers below
60  quaternion_type quaternionPacketType;
61  quaternionPacketType = sfg->pControlSubsystem->QuaternionPacketType;
62 
63  Quaternion ftmpq; // scratch quaternion
64 
65  // calculate the test perturbation
66  switch (sfg->iPerturbation)
67  {
68  case 1: // 180 degrees about X
69  ftmpq.q0 = 0.0F;
70  ftmpq.q1 = 1.0F;
71  ftmpq.q2 = 0.0F;
72  ftmpq.q3 = 0.0F;
73  threshold = 90.0;
74  break;
75 
76  case 2: // 180 degrees about Y
77  ftmpq.q0 = 0.0F;
78  ftmpq.q1 = 0.0F;
79  ftmpq.q2 = 1.0F;
80  ftmpq.q3 = 0.0F;
81  threshold = 90.0;
82  break;
83 
84  case 3: // 180 degrees about Z
85  ftmpq.q0 = 0.0F;
86  ftmpq.q1 = 0.0F;
87  ftmpq.q2 = 0.0F;
88  ftmpq.q3 = 1.0F;
89  threshold = 90.0;
90  break;
91 
92  case 4: // -90 degrees about X
93  ftmpq.q0 = ONEOVERSQRT2;
94  ftmpq.q1 = -ONEOVERSQRT2;
95  ftmpq.q2 = 0.0F;
96  ftmpq.q3 = 0.0F;
97  threshold = 45.0;
98  break;
99 
100  case 5: // +90 degrees about X
101  ftmpq.q0 = ONEOVERSQRT2;
102  ftmpq.q1 = ONEOVERSQRT2;
103  ftmpq.q2 = 0.0F;
104  ftmpq.q3 = 0.0F;
105  threshold = 45.0;
106  break;
107 
108  case 6: // -90 degrees about Y
109  ftmpq.q0 = ONEOVERSQRT2;
110  ftmpq.q1 = 0.0F;
111  ftmpq.q2 = -ONEOVERSQRT2;
112  ftmpq.q3 = 0.0F;
113  threshold = 45.0;
114  break;
115 
116  case 7: // +90 degrees about Y
117  ftmpq.q0 = ONEOVERSQRT2;
118  ftmpq.q1 = 0.0F;
119  ftmpq.q2 = ONEOVERSQRT2;
120  ftmpq.q3 = 0.0F;
121  threshold = 45.0;
122  break;
123 
124  case 8: // -90 degrees about Z
125  ftmpq.q0 = ONEOVERSQRT2;
126  ftmpq.q1 = 0.0F;
127  ftmpq.q2 = 0.0F;
128  ftmpq.q3 = -ONEOVERSQRT2;
129  threshold = 45.0;
130  break;
131 
132  case 9: // +90 degrees about Z
133  ftmpq.q0 = ONEOVERSQRT2;
134  ftmpq.q1 = 0.0F;
135  ftmpq.q2 = 0.0F;
136  ftmpq.q3 = ONEOVERSQRT2;
137  threshold = 45.0;
138  break;
139 
140  default: // No rotation
141  ftmpq.q0 = 1.0F;
142  ftmpq.q1 = 0.0F;
143  ftmpq.q2 = 0.0F;
144  ftmpq.q3 = 0.0F;
145  break;
146  }
147 
148  switch (quaternionPacketType) {
149 #if F_3DOF_G_BASIC
150  case (Q3):
151  CurrentQ = sfg->SV_3DOF_G_BASIC.fLPq;
152  qAeqAxB(&(sfg->SV_3DOF_G_BASIC.fLPq), &ftmpq);
153  break;
154 #endif
155 #if F_3DOF_B_BASIC
156  case (Q3M):
157  CurrentQ = sfg->SV_3DOF_B_BASIC.fLPq;
158  qAeqAxB(&(sfg->SV_3DOF_B_BASIC.fLPq), &ftmpq);
159  break;
160 #endif
161 #if F_3DOF_Y_BASIC
162  case (Q3G):
163  CurrentQ = sfg->SV_3DOF_Y_BASIC.fq;
164  qAeqAxB(&(sfg->SV_3DOF_Y_BASIC.fq), &ftmpq);
165  break;
166 #endif
167 #if F_6DOF_GB_BASIC
168  case (Q6MA):
169  CurrentQ = sfg->SV_6DOF_GB_BASIC.fLPq;
170  qAeqAxB(&(sfg->SV_6DOF_GB_BASIC.fLPq), &ftmpq);
171  break;
172 #endif
173 #if F_6DOF_GY_KALMAN
174  case (Q6AG):
175  CurrentQ = sfg->SV_6DOF_GY_KALMAN.fqPl;
176  qAeqAxB(&(sfg->SV_6DOF_GY_KALMAN.fqPl), &ftmpq);
177  break;
178 #endif
179 #if F_9DOF_GBY_KALMAN
180  case (Q9):
181  CurrentQ = sfg->SV_9DOF_GBY_KALMAN.fqPl;
182  qAeqAxB(&(sfg->SV_9DOF_GBY_KALMAN.fqPl), &ftmpq);
183  break;
184 #endif
185  default:
186  CurrentQ.q0 = 1.0;
187  CurrentQ.q1 = 0.0;
188  CurrentQ.q2 = 0.0;
189  CurrentQ.q3 = 0.0;
190  break;
191  }
192 
193  // Begin of code for white-box testing - requires IAR debugger
194  switch (iTestProgress) {
195  case 0: // no test in progress, check to see if we should start one
196  if (sfg->iPerturbation>0) {
197  // Start Test
198  iTestProgress = 1;
199  sfg->iPerturbation = 0;
200  iTestDelay = 0;
201  //iTestAngle = 0;
202  // We'll need the complex conjugate of the starting quaternion
203  StartingQ.q0 = CurrentQ.q0;
204  StartingQ.q1 = -1 * CurrentQ.q1;
205  StartingQ.q2 = -1 * CurrentQ.q2;
206  StartingQ.q3 = -1 * CurrentQ.q3;
207  }
208  break;
209  default: // Test in progress, check to see if trigger reached
210  iTestDelay += 1;
211  qAeqAxB(&CurrentQ, &StartingQ);
212  angle = 2 * F180OVERPI * acos(CurrentQ.q0);
213  angle = fmod(fabs(angle), 180.0);
214  //iTestAngle = (uint16_t) (10 * angle);
215  // In IAR, you can use a Log breakpoint to monitor "return to stationary pose".
216  // Use the following expression in the Message field and check the
217  // checkbox for C-Spy macro. Then Click any of the "Test" buttons
218  // in the Sensor Fusion Toolbox and monitor the results in the Messages window.
219  //"Delay=", iTestDelay:%d, " Angle=",iTestAngle:%d
220  if (angle<threshold) iTestProgress=2; // triggered
221  if (angle < (0.2 * threshold)) iTestProgress=0; // test is done
222  if (iTestDelay>100) iTestProgress=0; // abort test
223  break;
224  }
225  // End of code for white-box testing
226 #endif
227 }
float q2
y vector component
Definition: orientation.h:24
volatile uint8_t iPerturbation
test perturbation to be applied
enum quaternion quaternion_type
the quaternion type to be transmitted
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:52
Defines control sub-system.
The top level fusion structure.
#define F180OVERPI
radians to degrees conversion = 180 / pi
Definition: sensor_fusion.h:84
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:49
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:50
quaternion structure definition
Definition: orientation.h:20
#define ONEOVERSQRT2
1/sqrt(2)
Definition: sensor_fusion.h:93
float q3
z vector component
Definition: orientation.h:25
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:44
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:54
The sensor_fusion.h file implements the top level programming interface.
SensorFusionGlobals sfg
struct ControlSubsystem * pControlSubsystem
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:51
float q1
x vector component
Definition: orientation.h:23
void ApplyPerturbation(SensorFusionGlobals *sfg)
Definition: debug.c:36
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:53
float q0
scalar component
Definition: orientation.h:22
void qAeqAxB(Quaternion *pqA, const Quaternion *pqB)
function compute the quaternion product qA = qA * qB
Definition: orientation.c:953