1 /*********************************************************************
2 Copyright 2013 Karl Jones
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 For Further Information Please Contact me at
27 http://p.sf.net/kdis/UserGuide
28 *********************************************************************/
30 #include "./DeadReckoningCalculator.h"
35 #define KDIS_PI 3.14159265358979323846
39 #define KDIS_PI_2 1.57079632679489661923
42 //////////////////////////////////////////////////////////////////////////
46 using namespace DATA_TYPE
;
47 using namespace ENUMS
;
48 using namespace UTILS
;
50 #define MAGIC_EPSILON 0.00001
51 const float PI_TIMES_TWO
= 2.0f
* KDIS_PI
;
53 //////////////////////////////////////////////////////////////////////////
56 inline KBOOL
equivalent( const T lhs
, const T rhs
, T epsilon
= std::numeric_limits
<T
>::epsilon() )
59 return ( delta
< 0 ) ? delta
> -epsilon
: delta
< epsilon
;
62 /////////////////////////////////////////////////////////////////////////
64 inline KFLOAT32
checkAngleHR( const KFLOAT32 a
)
66 if (a
< -KDIS_PI
) return (a
+ PI_TIMES_TWO
);
67 else if (a
> KDIS_PI
) return (a
- PI_TIMES_TWO
);
71 //////////////////////////////////////////////////////////////////////////
73 inline KFLOAT32
checkAngleP( const KFLOAT32 a
)
75 if (a
< -KDIS_PI_2
) return (-KDIS_PI
-a
);
76 else if (a
> KDIS_PI_2
) return (KDIS_PI
-a
);
80 /////////////////////////////////////////////////////////////////////////
83 inline const T
clampVal( const T val
, T CutOff
)
85 if( CutOff
< 0 )CutOff
= -CutOff
;
87 if( val
> CutOff
)return CutOff
;
88 else if( val
< -CutOff
)return -CutOff
;
93 //////////////////////////////////////////////////////////////////////////
95 void matrixToHPR_new( const TMATRIX
& rotation
, EulerAngles
& hpr
)
97 static const float PRECISION
= MAGIC_EPSILON
;
98 KFLOAT64 sin_pitch
= clampVal( -rotation
.Data
[0][2], 1.0f
); // -mat(0,2)
99 KFLOAT64 pitch
= asin( sin_pitch
);
100 hpr
.SetThetaInRadians( pitch
);
102 KFLOAT64 cp
= cos( pitch
);
103 if (equivalent
<double>(cp
, 0, PRECISION
))
105 KFLOAT64 cr
= clampVal(rotation
.Data
[1][1],1.0f
);
106 KFLOAT64 sr
= clampVal(-rotation
.Data
[2][1],1.0f
);
107 hpr
.SetPsiInRadians( 0.0f
);
108 hpr
.SetPhiInRadians( atan2( sr
,cr
) );
110 KFLOAT64 sr
= clampVal(rotation
.Data
[1][2],1.0f
);
111 KFLOAT64 cr
= clampVal(rotation
.Data
[2][2],1.0f
);
112 float sgnr
= (sr
< 0) ? -1.0f
: 1.0f
;
114 KFLOAT64 sh
= clampVal(rotation
.Data
[0][1],1.0f
);
115 KFLOAT64 ch
= clampVal(rotation
.Data
[0][0],1.0f
);
116 float sgnh
= (sh
< 0) ? -1.0f
: 1.0f
;
118 //hpr.SetPsiInRadians( acos ( ch / cp )*sgnh );
119 //hpr.SetPhiInRadians( acos( cr / cp)*sgnr);
120 hpr
.SetPsiInRadians( atan2 (sh
,ch
) );
121 hpr
.SetPhiInRadians( atan2 (sr
,cr
) );
125 //////////////////////////////////////////////////////////////////////////
127 //////////////////////////////////////////////////////////////////////////
129 void DeadReckoningCalculator::positionReset( const WorldCoordinates
& Position
)
131 m_initPosition
= Position
;
134 //////////////////////////////////////////////////////////////////////////
136 void DeadReckoningCalculator::orientationReset( const EulerAngles
& Orientation
)
138 m_initOrientation
= Orientation
;
140 const KFLOAT32 f32Psi
= Orientation
.GetPsiInRadians();
141 const KFLOAT32 f32Theta
= Orientation
.GetThetaInRadians();
142 const KFLOAT32 f32Phi
= Orientation
.GetPhiInRadians();
144 const KFLOAT64 f32CosPsi
= cos( f32Psi
);
145 const KFLOAT64 f32CosTheta
= cos( f32Theta
);
146 const KFLOAT64 f32CosPhi
= cos( f32Phi
);
147 const KFLOAT64 f32SinPsi
= sin( f32Psi
);
148 const KFLOAT64 f32SinTheta
= sin( f32Theta
);
149 const KFLOAT64 f32SinPhi
= sin( f32Phi
);
151 // Create the orientation matrix
153 // RI - could use osg mathematics for Euler to rotation matrix computation
154 const KFLOAT64 sinTheta_cosPsi
= f32SinTheta
* f32CosPsi
;
155 const KFLOAT64 sinTheta_sinPsi
= f32SinTheta
* f32SinPsi
;
157 m_initOrientationMatrix
.Data
[0][0] = f32CosTheta
* f32CosPsi
;
158 m_initOrientationMatrix
.Data
[0][1] = f32CosTheta
* f32SinPsi
;
159 m_initOrientationMatrix
.Data
[0][2] = -f32SinTheta
;
161 m_initOrientationMatrix
.Data
[1][0] = ( f32SinPhi
* sinTheta_cosPsi
) - ( f32CosPhi
* f32SinPsi
);
162 m_initOrientationMatrix
.Data
[1][1] = ( f32SinPhi
* sinTheta_sinPsi
) + ( f32CosPhi
* f32CosPsi
);
163 m_initOrientationMatrix
.Data
[1][2] = f32SinPhi
* f32CosTheta
;
165 m_initOrientationMatrix
.Data
[2][0] = ( f32CosPhi
* sinTheta_cosPsi
) + ( f32SinPhi
* f32SinPsi
);
166 m_initOrientationMatrix
.Data
[2][1] = ( f32CosPhi
* sinTheta_sinPsi
) - ( f32SinPhi
* f32CosPsi
);
167 m_initOrientationMatrix
.Data
[2][2] = f32CosPhi
* f32CosTheta
;
169 m_initOrientationMatrixTranspose
= m_initOrientationMatrix
;
170 m_initOrientationMatrixTranspose
.inPlanceTranspose();
172 computeRotationAxis(m_initOrientationMatrix
);
175 //////////////////////////////////////////////////////////////////////////
177 void DeadReckoningCalculator::angularVelocityReset( const Vector
& AngularVelocity
)
179 m_initAngularVelocity
= AngularVelocity
;
181 m_initEulerAngularVelocity
= toEulerAngularVelocity(AngularVelocity
, m_initOrientation
);
183 // Create the ww matrix
184 m_wwMatrix
.Data
[0][0] = m_initAngularVelocity
[0] * m_initAngularVelocity
[0];
185 m_wwMatrix
.Data
[0][1] = m_initAngularVelocity
[0] * m_initAngularVelocity
[1];
186 m_wwMatrix
.Data
[0][2] = m_initAngularVelocity
[0] * m_initAngularVelocity
[2];
188 m_wwMatrix
.Data
[1][0] = m_initAngularVelocity
[1] * m_initAngularVelocity
[0];
189 m_wwMatrix
.Data
[1][1] = m_initAngularVelocity
[1] * m_initAngularVelocity
[1];
190 m_wwMatrix
.Data
[1][2] = m_initAngularVelocity
[1] * m_initAngularVelocity
[2];
192 m_wwMatrix
.Data
[2][0] = m_initAngularVelocity
[2] * m_initAngularVelocity
[0];
193 m_wwMatrix
.Data
[2][1] = m_initAngularVelocity
[2] * m_initAngularVelocity
[1];
194 m_wwMatrix
.Data
[2][2] = m_initAngularVelocity
[2] * m_initAngularVelocity
[2];
196 m_SkewOmegaMatrix
.Data
[0][0] = 0;
197 m_SkewOmegaMatrix
.Data
[0][1] = - m_initAngularVelocity
[2];
198 m_SkewOmegaMatrix
.Data
[0][2] = m_initAngularVelocity
[1];
200 m_SkewOmegaMatrix
.Data
[1][0] = m_initAngularVelocity
[2];
201 m_SkewOmegaMatrix
.Data
[1][1] = 0;
202 m_SkewOmegaMatrix
.Data
[1][2] = - m_initAngularVelocity
[0];
204 m_SkewOmegaMatrix
.Data
[2][0] = - m_initAngularVelocity
[1];
205 m_SkewOmegaMatrix
.Data
[2][1] = m_initAngularVelocity
[0];
206 m_SkewOmegaMatrix
.Data
[2][2] = 0;
208 m_f64Magnitude
= sqrt( m_initAngularVelocity
[0] * m_initAngularVelocity
[0] +
209 m_initAngularVelocity
[1] * m_initAngularVelocity
[1] +
210 m_initAngularVelocity
[2] * m_initAngularVelocity
[2] );
213 //////////////////////////////////////////////////////////////////////////
215 void DeadReckoningCalculator::velocityReset( const Vector
& LinearVelocity
)
217 m_initLinearVelocity
= LinearVelocity
;
220 //////////////////////////////////////////////////////////////////////////
222 void DeadReckoningCalculator::accelerationReset( const Vector
& LinearAcceleration
)
224 m_initLinearAcceleration
= LinearAcceleration
;
227 //////////////////////////////////////////////////////////////////////////
229 EulerAngles
DeadReckoningCalculator::toEulerAngularVelocity( const Vector
& angVel
, const EulerAngles
& Orientation
)
231 KFLOAT32 dpsi
, dtheta
, dphi
;
233 const KFLOAT32 phi
= Orientation
.GetPhiInRadians();
234 const KFLOAT32 theta
= Orientation
.GetThetaInRadians();
235 const KFLOAT32 psi
= Orientation
.GetPsiInRadians();
237 KFLOAT32 cos_phi
= cos( phi
);
238 KFLOAT32 sin_phi
= sin( phi
);
240 dtheta
= angVel
[1] * cos_phi
- angVel
[2] * sin_phi
;
241 dpsi
= ( angVel
[1] * sin_phi
+ angVel
[2] * cos_phi
) / cos( theta
); //could be unstable when cos(theta) is close to 0
242 dphi
= angVel
[0] + dpsi
* sin( theta
);
244 return EulerAngles( ( const KFLOAT32
)dpsi
, ( const KFLOAT32
)dtheta
, ( const KFLOAT32
)dphi
);
248 void DeadReckoningCalculator::calcOrientation_simplified( EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
251 // A simpler way from the IEEE method:
253 m_curOrientation += ( toEulerAngularVelocity( m_initAngularVelocity, m_curOrientation ) * DeltaTime );
255 OrientationOut
= m_initOrientation
+ m_initEulerAngularVelocity
* totalTimeSinceReset
;
256 // make sure the Pitch is between -90 and +90 degrees
257 // also handle the discontinuity when Pitch is very close to +-90
258 if( equivalent
<KFLOAT32
>( OrientationOut
[1], KDIS_PI_2
, MAGIC_EPSILON
* 100 ) ) {
259 OrientationOut
[0] = KDIS_PI
- OrientationOut
[0]; //reflecting the heading angle, to avoid discontinuity
260 if (OrientationOut
[1] < 0)
261 OrientationOut
[1] = (-KDIS_PI_2
-OrientationOut
[1]);
262 else if (OrientationOut
[1] > 0)
263 OrientationOut
[1] = (KDIS_PI_2
-OrientationOut
[1]);
266 // Make sure the value is within -180 and +180 degrees for Heading and Roll.
267 OrientationOut
[0] = checkAngleHR( OrientationOut
[0]);
268 OrientationOut
[2] = checkAngleHR( OrientationOut
[2]);
271 /////////////////////////////////////////////////////////////////////////
273 void DeadReckoningCalculator::computeRotationAxis( const TMATRIX
& curOrientationMatrix
)
278 x
= curOrientationMatrix
.Data
[1][2] - curOrientationMatrix
.Data
[2][1];
279 y
= curOrientationMatrix
.Data
[2][0] - curOrientationMatrix
.Data
[0][2];
280 z
= curOrientationMatrix
.Data
[0][1] - curOrientationMatrix
.Data
[1][0];
283 KFLOAT32 len
= sqrt(x
* x
+ y
* y
+ z
* z
);
296 m_bQuaxAxisSet
= true;
300 void DeadReckoningCalculator::calcOrientation( EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
302 // compute the DR matrix
305 computeDRMatrix_asQuat( DR
, totalTimeSinceReset
);
307 computeDRMatrix( DR
, totalTimeSinceReset
);
309 TMATRIX curOrientationMatrix
= DR
* m_initOrientationMatrix
;
310 //TMATRIX curOrientationMatrix = m_initOrientationMatrix;
312 matrixToHPR_new( curOrientationMatrix
, OrientationOut
);
313 //matrixToHPR( curOrientationMatrix, m_curOrientation );
314 OrientationOut
[0] = checkAngleHR( OrientationOut
[0]);
315 OrientationOut
[1] = checkAngleP(OrientationOut
[1]);
316 OrientationOut
[2] = checkAngleHR( OrientationOut
[2]);
318 computeRotationAxis(curOrientationMatrix
);
321 //////////////////////////////////////////////////////////////////////////
323 void DeadReckoningCalculator::computeDRMatrix( TMATRIX
& res
, const KFLOAT32 totalTimeSinceReset
)
326 const KFLOAT64 f64DeltaMag
= totalTimeSinceReset
* m_f64Magnitude
;
327 if( f64DeltaMag
> MAGIC_EPSILON
)
329 const KFLOAT32 f64CosMagDelta
= cos( f64DeltaMag
);
330 const KFLOAT64 fwwScalar
= ( 1 - f64CosMagDelta
) / ( m_f64Magnitude
* m_f64Magnitude
);
334 const KFLOAT64 f64SkewScalar
= sin( f64DeltaMag
) / m_f64Magnitude
;
336 res
-= ( m_SkewOmegaMatrix
* f64SkewScalar
);
340 res
= I
; // Identity matrix
344 void DeadReckoningCalculator::computeDRMatrix_asQuat( TMATRIX
& res
, const KFLOAT32 totalTimeSinceReset
)
347 // assume that m_quatAxis is set
350 const KFLOAT64 beta
= totalTimeSinceReset
* m_f64Magnitude
;
352 KFLOAT32 sin_beta_2
= sin(beta
/2.0f
);
353 qx
= sin_beta_2
* m_quatAxis
.GetX();
354 qy
= sin_beta_2
* m_quatAxis
.GetY();
355 qz
= sin_beta_2
* m_quatAxis
.GetZ();
358 res
.Data
[0][0] = q0
*q0
+ qx
*qx
- 0.5f
;
359 res
.Data
[0][1] = qx
*qy
- q0
*qz
;
360 res
.Data
[0][2] = qx
*qz
+ q0
*qy
;
362 res
.Data
[1][0] = qx
*qy
+ q0
*qz
;
363 res
.Data
[1][1] = q0
*q0
+ qy
*qy
- 0.5f
;
364 res
.Data
[1][2] = qy
*qz
- q0
*qx
;
366 res
.Data
[2][0] = qx
*qz
- q0
*qy
;
367 res
.Data
[2][1] = qy
*qz
+ q0
*qx
;
368 res
.Data
[2][2] = q0
*q0
+ qz
*qz
- 0.5f
;
371 //////////////////////////////////////////////////////////////////////////
372 // Dead Reckoning Algorithm Implementations
373 //////////////////////////////////////////////////////////////////////////
375 void DeadReckoningCalculator::calcDeadReckoningFPW( WorldCoordinates
& PositionOut
, const KFLOAT32 totalTimeSinceReset
)
378 PositionOut
= ( m_initPosition
+ ( m_initLinearVelocity
* totalTimeSinceReset
) );
381 //////////////////////////////////////////////////////////////////////////
383 void DeadReckoningCalculator::calcDeadReckoningRPW( WorldCoordinates
& PositionOut
, EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
386 PositionOut
= ( m_initPosition
+ ( m_initLinearVelocity
* totalTimeSinceReset
) );
387 if (m_f64Magnitude
< MAGIC_EPSILON
)
389 OrientationOut
= m_initOrientation
;
392 //calcOrientation(OrientationOut);
393 calcOrientation_simplified( OrientationOut
, totalTimeSinceReset
);
396 //////////////////////////////////////////////////////////////////////////
398 void DeadReckoningCalculator::calcDeadReckoningRVW( WorldCoordinates
& PositionOut
, EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
401 PositionOut
= ( m_initPosition
+ ( m_initLinearVelocity
* totalTimeSinceReset
) +
402 ( m_initLinearAcceleration
* ( 0.5 * totalTimeSinceReset
* totalTimeSinceReset
) ) );
403 if (m_f64Magnitude
< MAGIC_EPSILON
)
405 OrientationOut
= m_initOrientation
;
408 //calcOrientation(OrientationOut);
409 calcOrientation_simplified( OrientationOut
, totalTimeSinceReset
);
412 //////////////////////////////////////////////////////////////////////////
414 void DeadReckoningCalculator::calcDeadReckoningFVW( WorldCoordinates
& PositionOut
, const KFLOAT32 totalTimeSinceReset
)
417 PositionOut
= ( m_initPosition
+ ( m_initLinearVelocity
* totalTimeSinceReset
) +
418 ( m_initLinearAcceleration
* ( 0.5 * totalTimeSinceReset
* totalTimeSinceReset
) ) );
421 //////////////////////////////////////////////////////////////////////////
423 void DeadReckoningCalculator::calcDeadReckoningFPB( WorldCoordinates
& PositionOut
, const KFLOAT32 totalTimeSinceReset
)
425 // See page 124 of IEEE 1278.1 - 1995 for more details on this and other dead reckoning equations.
427 // Calculate Magnitude, scalars etc
428 const KFLOAT64 f64DeltaMag
= totalTimeSinceReset
* m_f64Magnitude
;
429 if( f64DeltaMag
> MAGIC_EPSILON
)
431 KFLOAT32 m_f32MagPow2
= m_f64Magnitude
* m_f64Magnitude
;
432 KFLOAT32 m_f32MagPow3
= m_f32MagPow2
* m_f64Magnitude
;
434 const KFLOAT64 f64Scalar
= ( ( f64DeltaMag
) - sin( f64DeltaMag
) ) / m_f32MagPow3
;
435 const KFLOAT64 f64IScalar
= sin( f64DeltaMag
) / m_f64Magnitude
;
436 const KFLOAT64 f64SkewScale
= ( 1 - cos( f64DeltaMag
) ) / m_f32MagPow2
;
437 TMATRIX
R1( m_wwMatrix
), IMatrix
;
439 IMatrix
*= f64IScalar
;
441 R1
+= ( m_SkewOmegaMatrix
* f64SkewScale
); // RI - should be + instead of - IEEE 1278.1-1995.pdf page 128
443 PositionOut
= ( m_initPosition
+ ( m_initOrientationMatrixTranspose
* ( R1
* m_initLinearVelocity
) ) );
447 PositionOut
= ( m_initPosition
+ ( m_initOrientationMatrixTranspose
* m_initLinearVelocity
* totalTimeSinceReset
) );
451 //////////////////////////////////////////////////////////////////////////
453 void DeadReckoningCalculator::calcDeadReckoningRPB( WorldCoordinates
& PositionOut
, EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
456 // Position is calculated the same as FPB
457 calcDeadReckoningFPB( PositionOut
, totalTimeSinceReset
);
458 //calcOrientation(OrientationOut);
459 calcOrientation_simplified( OrientationOut
, totalTimeSinceReset
);
463 //////////////////////////////////////////////////////////////////////////
465 void DeadReckoningCalculator::calcDeadReckoningRVB( WorldCoordinates
& PositionOut
, EulerAngles
& OrientationOut
, const KFLOAT32 totalTimeSinceReset
)
468 calcDeadReckoningFVB( PositionOut
, totalTimeSinceReset
);
469 //calcOrientation(OrientationOut);
470 calcOrientation_simplified( OrientationOut
, totalTimeSinceReset
);
473 //////////////////////////////////////////////////////////////////////////
475 void DeadReckoningCalculator::calcDeadReckoningFVB( WorldCoordinates
& PositionOut
, const KFLOAT32 totalTimeSinceReset
)
477 // the first part of the equation
478 calcDeadReckoningFPB( PositionOut
, totalTimeSinceReset
);
480 // now adding to the position R0t_w->b * R2 * Ab
481 // Calculate Magnitude, scalars etc
482 const KFLOAT64 f64DeltaMag
= totalTimeSinceReset
* m_f64Magnitude
;
484 if( f64DeltaMag
> MAGIC_EPSILON
)
487 KFLOAT32 m_f32MagPow2
= m_f64Magnitude
* m_f64Magnitude
;
488 KFLOAT32 m_f32MagPow3
= m_f32MagPow2
* m_f64Magnitude
;
489 KFLOAT32 m_f32MagPow4
= m_f32MagPow3
* m_f64Magnitude
;
490 KFLOAT32 m_f32DeltaPow2
= f64DeltaMag
* f64DeltaMag
;
492 KFLOAT64 f64R2Scale
= (0.5 * m_f32DeltaPow2
- cos( f64DeltaMag
)- f64DeltaMag
* sin( f64DeltaMag
) + 1)/m_f32MagPow4
;
494 KFLOAT64 f64R2IScalar
= ( cos( f64DeltaMag
) + f64DeltaMag
* sin( f64DeltaMag
) - 1.0 ) / m_f32MagPow2
;
496 KFLOAT64 f64R2SkewScale
= ( sin( f64DeltaMag
) - f64DeltaMag
* cos( f64DeltaMag
) ) / m_f32MagPow3
;
498 // Create the ww matrix
499 TMATRIX
R2Matrix( m_wwMatrix
), IR2Matrix
;
500 R2Matrix
*= f64R2Scale
;
501 IR2Matrix
*= f64R2IScalar
;
502 R2Matrix
+= ( IR2Matrix
+ ( m_SkewOmegaMatrix
* f64R2SkewScale
) );
504 PositionOut
= PositionOut
+ ( m_initOrientationMatrixTranspose
* ( R2Matrix
* m_Ab
) );
506 PositionOut
= PositionOut
+ ( m_initOrientationMatrixTranspose
* m_Ab
) * totalTimeSinceReset
;
509 /////////////////////////////////////////////////////////////////////////
511 void DeadReckoningCalculator::RunAlgorithm( const KFLOAT32 totalTimeSinceReset
, WorldCoordinates
& PositionOut
, EulerAngles
& OrientationOut
)
516 calcDeadReckoningFPW( PositionOut
, totalTimeSinceReset
);
520 calcDeadReckoningRPW( PositionOut
, OrientationOut
, totalTimeSinceReset
);
524 calcDeadReckoningRVW( PositionOut
, OrientationOut
, totalTimeSinceReset
);
528 calcDeadReckoningFVW( PositionOut
, totalTimeSinceReset
);
532 calcDeadReckoningFPB( PositionOut
, totalTimeSinceReset
);
536 calcDeadReckoningRPB( PositionOut
, OrientationOut
, totalTimeSinceReset
);
540 calcDeadReckoningRVB( PositionOut
, OrientationOut
, totalTimeSinceReset
);
544 calcDeadReckoningFVB( PositionOut
, totalTimeSinceReset
);
549 //////////////////////////////////////////////////////////////////////////
551 //////////////////////////////////////////////////////////////////////////
553 DeadReckoningCalculator::DeadReckoningCalculator() :
554 m_bQuaxAxisSet( false ),
560 //////////////////////////////////////////////////////////////////////////
562 DeadReckoningCalculator::~DeadReckoningCalculator()
566 //////////////////////////////////////////////////////////////////////////
568 void DeadReckoningCalculator::Reset( const Vector
& LinearVelocity
, const Vector
& LinearAcceleration
, const Vector
& AngularVelocity
,
569 const WorldCoordinates
& Position
, const EulerAngles
& Orientation
, const Vector
& QuatAxis
, DeadReckoningAlgorithm DRA
)
573 positionReset( Position
);
574 if ((QuatAxis
.GetX() + QuatAxis
.GetY() + QuatAxis
.GetZ()) > 0.0f
) // must set m_bQuaxAxisSet before orientationReset
575 quatAxisReset(QuatAxis
);
577 m_bQuaxAxisSet
= false;
578 orientationReset( Orientation
);
579 angularVelocityReset( AngularVelocity
);
580 velocityReset( LinearVelocity
);
581 accelerationReset( LinearAcceleration
);
583 m_Ab
= ( m_initLinearAcceleration
+ ( m_SkewOmegaMatrix
* m_initLinearVelocity
) );
586 //////////////////////////////////////////////////////////////////////////
588 vector
<WorldCoordinates
> DeadReckoningCalculator::GenerateSmoothingPoints( const WorldCoordinates
& StartPosition
, const WorldCoordinates
& EndPosition
,
589 KUINT32 NumberOfPoints
)
591 vector
<WorldCoordinates
> Points
;
592 Points
.reserve( NumberOfPoints
);
594 GenerateSmoothingPoints( StartPosition
, EndPosition
, NumberOfPoints
, Points
);
599 //////////////////////////////////////////////////////////////////////////
601 void DeadReckoningCalculator::GenerateSmoothingPoints( const WorldCoordinates
& StartPosition
, const WorldCoordinates
& EndPosition
,
602 KUINT32 NumberOfPoints
, vector
<WorldCoordinates
> & v
)
604 v
.reserve( NumberOfPoints
);
605 WorldCoordinates delta_loc
= EndPosition
- StartPosition
;
607 for( KINT32 i
= 1; i
<= NumberOfPoints
; ++i
)
609 v
.push_back( StartPosition
+ ( delta_loc
* ( KFLOAT32( i
) / KFLOAT32( NumberOfPoints
) ) ) );
613 //////////////////////////////////////////////////////////////////////////
615 void DeadReckoningCalculator::quatAxisReset( const Vector
& QuatAxis
)
617 m_quatAxis
= QuatAxis
;
618 m_bQuaxAxisSet
= true;
621 //////////////////////////////////////////////////////////////////////////