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