cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vctRodriguezRotation3Base.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5 
6  Author(s): Anton Deguet
7  Created on: 2005-08-25
8 
9  (C) Copyright 2005-2012 Johns Hopkins University (JHU), All Rights
10  Reserved.
11 
12 --- begin cisst license - do not edit ---
13 
14 This software is provided "as is" under an open source license, with
15 no warranty. The complete license can be found in license.txt and
16 http://www.cisst.org/cisst/license.txt.
17 
18 --- end cisst license ---
19 */
20 
21 #pragma once
22 #ifndef _vctRodriguezRotation3Base_h
23 #define _vctRodriguezRotation3Base_h
24 
31 
34 
35 #include <cisstVector/vctExport.h>
36 
37 #ifndef DOXYGEN
38 #ifndef SWIG
39 
40 // helper functions for subtemplated methods of a templated class
41 template <class _rodriguezType, class _matrixType>
42 void
44  const vctMatrixRotation3Base<_matrixType> & matrixRotation);
45 
46 template <class _rodriguezType, class _matrixType>
47 void
49  const vctQuaternionRotation3Base<_matrixType> & quaternionRotation);
50 
51 #endif // SWIG
52 #endif // DOXYGEN
53 
54 
68 template <class _containerType>
69 class vctRodriguezRotation3Base: public _containerType
70 {
71 public:
72  enum {DIMENSION = 3};
73  typedef _containerType BaseType;
74  typedef _containerType ContainerType;
76 
77  /* no need to document, inherit doxygen documentation from vctFixedSizeVectorBase */
78  VCT_CONTAINER_TRAITS_TYPEDEFS(typename ContainerType::value_type);
80 
81 
82 protected:
84  inline void ThrowUnlessIsNormalized(void) const throw(std::runtime_error) {
85  if (! IsNormalized()) {
86  cmnThrow(std::runtime_error("vctRodriguezRotation3Base: This rotation is not normalized"));
87  }
88  }
89 
94  template <class _inputType>
95  inline void ThrowUnlessIsNormalized(const _inputType & input) const throw(std::runtime_error) {
96  if (! input.IsNormalized()) {
97  cmnThrow(std::runtime_error("vctRodriguezRotation3Base: Input is not normalized"));
98  }
99  }
100 
101 public:
102 
105  BaseType(Identity())
106  {}
107 
111  template <stride_type __stride, class __dataPtrType>
113  BaseType(axis)
114  {}
115 
117  inline vctRodriguezRotation3Base(value_type x, value_type y, value_type z) {
118  this->Assign(x, y, z);
119  }
120 
123  static CISST_EXPORT const ThisType & Identity();
124 
125  template <stride_type __stride, class __dataPtrType>
127  throw(std::runtime_error)
128  {
129  FromRaw(vector);
130  // Always true - ThrowUnlessIsNormalized();
131  return (*this);
132  }
133 
134  inline ThisType & From(value_type x, value_type y, value_type z)
135  throw(std::runtime_error)
136  {
137  FromRaw(x, y, z);
138  // Always true - ThrowUnlessIsNormalized();
139  return (*this);
140  }
141 
142 
143  template <class __vectorOwnerType>
145  throw(std::runtime_error)
146  {
147  FromRaw(vector);
148  // Always true - ThrowUnlessIsNormalized();
149  return (*this);
150  }
151 
152 
153  template <class __containerType>
154  inline ThisType & From(const vctQuaternionRotation3Base<__containerType> & quaternionRotation)
155  throw(std::runtime_error)
156  {
157  ThrowUnlessIsNormalized(quaternionRotation);
158  return FromRaw(quaternionRotation);
159  }
160 
161 
162  template <class __containerType>
163  inline ThisType & From(const vctMatrixRotation3Base<__containerType> & matrixRotation) {
164  ThrowUnlessIsNormalized(matrixRotation);
165  return FromRaw(matrixRotation);
166  }
167 
168 
169  inline ThisType & From(const vctAxisAngleRotation3<value_type> & axisAngleRotation) {
170  ThrowUnlessIsNormalized(axisAngleRotation);
171  return FromRaw(axisAngleRotation);
172  }
173 
174 
175 
176  template <stride_type __stride, class __dataPtrType>
178  {
179  FromRaw(vector);
180  return NormalizedSelf();
181  }
182 
183 
184  inline ThisType & FromNormalized(value_type x, value_type y, value_type z)
185  {
186  FromRaw(x, y, z);
187  return NormalizedSelf();
188  }
189 
190 
191  // might throw because of size
192  template <class __vectorOwnerType>
194  throw(std::runtime_error)
195  {
196  FromRaw(vector);
197  return NormalizedSelf();
198  }
199 
200 
201  template <class __containerType>
203  {
204  return FromRaw(quaternionRotation.Normalized());
205  }
206 
207 
208  template <class __containerType>
210  return FromRaw(matrixRotation.Normalized());
211  }
212 
213 
214  inline ThisType & FromNormalized(const vctAxisAngleRotation3<value_type> & axisAngleRotation) {
215  return FromRaw(axisAngleRotation.Normalized());
216  }
217 
218 
219 
220 
221 
222  template <stride_type __stride, class __dataPtrType>
224  {
225  this->Assign(vector);
226  return *this;
227  }
228 
229 
230  inline ThisType & FromRaw(value_type x, value_type y, value_type z)
231  {
232  this->Assign(static_cast<value_type>(x), static_cast<value_type>(y), static_cast<value_type>(z));
233  return *this;
234  }
235 
236 
237  template <class __vectorOwnerType>
239  {
240  if (vector.size() != 3) {
241  cmnThrow(std::runtime_error("vctRodriguezRotation3Base: From requires a vector of size 3"));
242  }
243  this-Assign(vector);
244  return *this;
245  }
246 
247 
248  template <class __containerType>
249  inline ThisType & FromRaw(const vctQuaternionRotation3Base<__containerType> & quaternionRotation) {
250  vctRodriguezRotation3BaseFromRaw(*this, quaternionRotation);
251  return *this;
252  }
253 
254 
255  template <class __containerType>
256  inline ThisType & FromRaw(const vctMatrixRotation3Base<__containerType> & matrixRotation) {
257  vctRodriguezRotation3BaseFromRaw(*this, matrixRotation);
258  return *this;
259  }
260 
261 
262  inline ThisType & FromRaw(const vctAxisAngleRotation3<value_type> & axisAngleRotation) {
263  this->Assign(axisAngleRotation.Axis());
264  this->Multiply(value_type(axisAngleRotation.Angle()));
265  return *this;
266  }
267 
268 
269  inline ThisType & InverseSelf(void) {
270  this->NegationSelf();
271  return *this;
272  }
273 
274  inline ThisType & InverseOf(const ThisType & otherRotation) {
275  this->NegationOf(otherRotation);
276  return *this;
277  }
278 
279  inline ThisType Inverse(void) const {
280  ThisType result;
281  result.NegationOf(*this);
282  return result;
283  }
284 
286  inline ThisType & NormalizedSelf(void) {
287  const NormType norm = this->Norm();
288  if (norm > (2.0 * cmnPI)) {
289  const NormType remainder = fmod(norm, (2.0 * cmnPI));
290  // const NormType quotient = (norm - remainder) / (2.0 * cmnPI);
291  this->Multiply(value_type(remainder / norm));
292  }
293  return *this;
294  }
295 
297  inline ThisType & NormalizedOf(const ThisType & otherRotation) {
298  this->Assign(otherRotation);
299  NormalizedSelf();
300  return *this;
301  }
302 
304  inline ThisType Normalized(void) const {
305  ThisType result(*this);
306  result.NormalizedSelf();
307  return result;
308  }
309 
319  inline bool IsNormalized(value_type CMN_UNUSED(tolerance) = TypeTraits::Tolerance()) const {
320  return true;
321  }
322 
323 
332  inline bool AlmostEquivalent(const ThisType & other,
333  value_type tolerance = TypeTraits::Tolerance()) const {
334  const AngleType angleThis = this->Norm();
335  const AngleType angleOther = other.Norm();
336  const AngleType dotProduct = AngleType(this->DotProduct(other));
337  // two quasi null rotations
338  if ((angleThis <= tolerance) && (angleOther <= tolerance)) {
339  return true;
340  }
341  // one rotation is almost null
342  if ((angleThis <= tolerance) || (angleOther <= tolerance)) {
343  return false;
344  }
345  // both rotations are non null
346  const AngleType cosAngle = dotProduct / (angleThis * angleOther);
347  const AngleType absCosAngle = cosAngle > value_type(0.0) ? cosAngle : -cosAngle;
348  // axis don't seem aligned
349  if ((absCosAngle <= (AngleType(1.0) - tolerance))
350  || (absCosAngle >= (AngleType(1.0) + tolerance))) {
351  return false;
352  }
353  // axis are aligned
354  const AngleType angleDifference = angleThis - cosAngle * angleOther;
355  AngleType angleRemain = fmod(angleDifference, 2.0 * cmnPI);
356  if (angleRemain > cmnPI) {
357  angleRemain -= (2.0 * cmnPI);
358  } else if (angleRemain < -cmnPI) {
359  angleRemain += (2.0 *cmnPI);
360  }
361  if ((angleRemain > -tolerance) && (angleRemain < tolerance)) {
362  return true;
363  }
364  return false;
365  }
366 
367 };
368 
369 
370 
371 template <class _rodriguezType, class _quaternionType>
372 void
374  const vctQuaternionRotation3Base<_quaternionType> & quaternionRotation)
375 {
376  typedef typename _rodriguezType::value_type value_type;
377  typedef typename _rodriguezType::AngleType AngleType;
378  typedef typename _rodriguezType::NormType NormType;
379  typedef typename _rodriguezType::TypeTraits TypeTraits;
380 
381  const NormType r = quaternionRotation.R();
382  const AngleType angle = acos(r) * 2;
383  AngleType oneMinusR2 = 1.0 - r * r;
384  if (oneMinusR2 < TypeTraits::Tolerance())
385  oneMinusR2 = 0.0;
386  AngleType sinAngle = sqrt(oneMinusR2);
387  if (vctUnaryOperations<AngleType>::AbsValue::Operate(sinAngle) > TypeTraits::Tolerance()) {
388  rodriguezRotation.X() = (value_type)(quaternionRotation.X() / sinAngle);
389  rodriguezRotation.Y() = (value_type)(quaternionRotation.Y() / sinAngle);
390  rodriguezRotation.Z() = (value_type)(quaternionRotation.Z() / sinAngle);
391  } else {
392  rodriguezRotation.X() = quaternionRotation.X();
393  rodriguezRotation.Y() = quaternionRotation.Y();
394  rodriguezRotation.Z() = quaternionRotation.Z();
395  }
396  rodriguezRotation.Multiply((value_type) angle);
397 }
398 
399 
400 template <class _rodriguezType, class _matrixType>
401 void
403  const vctMatrixRotation3Base<_matrixType> & matrixRotation)
404 {
405  typedef typename _rodriguezType::value_type value_type;
406  typedef typename _rodriguezType::AngleType AngleType;
407  typedef typename _rodriguezType::NormType NormType;
408  typedef typename _rodriguezType::TypeTraits TypeTraits;
409 
410  const NormType normTolerance = TypeTraits::Tolerance();
411  const NormType trace = matrixRotation.Element(0, 0) + matrixRotation.Element(1, 1) + matrixRotation.Element(2, 2); // 2 * cos(angle) + 1
412  const NormType xSin = matrixRotation.Element(2, 1) - matrixRotation.Element(1, 2); // 2 * x * sin(angle)
413  const NormType ySin = matrixRotation.Element(0, 2) - matrixRotation.Element(2, 0); // 2 * y * sin(angle)
414  const NormType zSin = matrixRotation.Element(1, 0) - matrixRotation.Element(0, 1); // 2 * z * sin(angle)
415  const NormType normSquare = xSin * xSin + ySin * ySin + zSin * zSin;
416  NormType norm;
417  if (normSquare < normTolerance) {
418  norm = 0.0;
419  } else {
420  norm = sqrt(normSquare); // 2 * |sin(angle)|
421  }
422 
423  // either 0 or PI
424  if (norm == 0.0) {
425  const NormType traceMinus3 = trace - NormType(3);
426  // if the angle is 0, then cos(angle) = 1, and trace = 2*cos(angle) + 1 = 3
427  if ( (traceMinus3 > -normTolerance) && (traceMinus3 < normTolerance) ) {
428  rodriguezRotation.SetAll(value_type(0));
429  return;
430  }
431  // since norm is already 0, we are in the other case, i.e., angle-PI, but we just want
432  // to assert that trace = -1
433  assert( (trace > (NormType(-1) - normTolerance)) && (trace < (NormType(-1) + normTolerance)) );
434  // the diagonal is [k_x*k_x*v + c , k_y*k_y*v + c, k_z*k_z*v + c]
435  // c = -1 ; v = (1 - c) = 2
436  NormType xSquare = (matrixRotation.Element(0, 0) + 1) / 2;
437  NormType ySquare = (matrixRotation.Element(1, 1) + 1) / 2;
438  NormType zSquare = (matrixRotation.Element(2, 2) + 1) / 2;
439  if (xSquare < normTolerance)
440  xSquare = 0;
441  if (ySquare < normTolerance)
442  ySquare = 0;
443  if (zSquare < normTolerance)
444  zSquare = 0;
445  NormType x = sqrt(xSquare);
446  NormType y = sqrt(ySquare);
447  NormType z = sqrt(zSquare);
448  // we arbitrarily decide the k_x is positive, if it's zero then k_y is positive, and if both are zero, then k_z is positive
449  if (x > 0) {
450  if (matrixRotation.Element(1, 0) < 0) // Element(1,0) = k_x*k_y*v , where v=2, so we just need to check its sign
451  y = -y;
452  if (matrixRotation.Element(2, 0) < 0) // Element(2,0) = k_x*k_z*v
453  z = -z;
454  } else if (y > 0) {
455  if (matrixRotation.Element(2, 1) < 0) // Element(2,1) = k_y*k_z*v
456  z = -z;
457  }
458  else {
459  z = 1.0; // x and y are zero, Z has to be one
460  }
461  rodriguezRotation.Assign(value_type(x), value_type(y), value_type(z));
462  rodriguezRotation.Multiply(value_type(cmnPI));
463  return;
464  }
465 
466  AngleType angle = atan2(norm / 2, (trace - 1) / 2);
467  rodriguezRotation.Assign(value_type(xSin), value_type(ySin), value_type(zSin));
468  rodriguezRotation.Multiply(value_type(angle / norm));
469 }
470 
471 #endif // _vctRodriguezRotation3Base_h
#define CISST_EXPORT
Definition: cmnExportMacros.h:50
bool AlmostEquivalent(const ThisType &other, value_type tolerance=TypeTraits::Tolerance()) const
Definition: vctRodriguezRotation3Base.h:332
ThisType & FromRaw(const vctDynamicConstVectorBase< __vectorOwnerType, value_type > &vector)
Definition: vctRodriguezRotation3Base.h:238
const AxisType & Axis(void) const
Definition: vctAxisAngleRotation3.h:314
NormType Norm(void) const
Definition: vctFixedSizeConstVectorBase.h:453
ThisType & From(const vctQuaternionRotation3Base< __containerType > &quaternionRotation)
Definition: vctRodriguezRotation3Base.h:154
RotationValueType Normalized(void) const
Definition: vctMatrixRotation3.h:389
ThisType & FromRaw(const vctFixedSizeConstVectorBase< 3, __stride, value_type, __dataPtrType > &vector)
Definition: vctRodriguezRotation3Base.h:223
ThisType & FromNormalized(value_type x, value_type y, value_type z)
Definition: vctRodriguezRotation3Base.h:184
#define CMN_UNUSED(argument)
Definition: cmnPortability.h:479
_containerType ContainerType
Definition: vctRodriguezRotation3Base.h:74
static Type Tolerance(void)
Definition: cmnTypeTraits.h:170
ThisType & FromNormalized(const vctQuaternionRotation3Base< __containerType > &quaternionRotation)
Definition: vctRodriguezRotation3Base.h:202
Forward declarations and #define for cisstVector.
ThisType & From(const vctMatrixRotation3Base< __containerType > &matrixRotation)
Definition: vctRodriguezRotation3Base.h:163
ThisType & NormalizedOf(const ThisType &otherRotation)
Definition: vctRodriguezRotation3Base.h:297
ThisType & FromNormalized(const vctMatrixRotation3Base< __containerType > &matrixRotation)
Definition: vctRodriguezRotation3Base.h:209
static CISST_EXPORT const ThisType & Identity()
vctRodriguezRotation3Base(const vctFixedSizeConstVectorBase< DIMENSION, __stride, value_type, __dataPtrType > &axis)
Definition: vctRodriguezRotation3Base.h:112
Definition: vctRodriguezRotation3Base.h:72
void ThrowUnlessIsNormalized(const _inputType &input) const
Definition: vctRodriguezRotation3Base.h:95
ThisType & InverseSelf(void)
Definition: vctRodriguezRotation3Base.h:269
vctRodriguezRotation3Base()
Definition: vctRodriguezRotation3Base.h:104
Declaration of various constants.
ThisType & NormalizedSelf(void)
Definition: vctRodriguezRotation3Base.h:286
ThisType Normalized(void) const
Definition: vctQuaternionRotation3Base.h:529
Define a rotation based on an axis and an angle for a space of dimension 3.
Definition: vctAxisAngleRotation3.h:94
ThisType & From(const vctFixedSizeConstVectorBase< 3, __stride, value_type, __dataPtrType > &vector)
Definition: vctRodriguezRotation3Base.h:126
Define unary operations on an object as classes.
Definition: vctUnaryOperations.h:55
ThisType & FromRaw(value_type x, value_type y, value_type z)
Definition: vctRodriguezRotation3Base.h:230
size_type size(void) const
Definition: vctDynamicConstVectorBase.h:164
ThisType & InverseOf(const ThisType &otherRotation)
Definition: vctRodriguezRotation3Base.h:274
ThisType & From(value_type x, value_type y, value_type z)
Definition: vctRodriguezRotation3Base.h:134
Define a rotation matrix for a space of dimension 3.
Definition: vctForwardDeclarations.h:199
ThisType & FromNormalized(const vctAxisAngleRotation3< value_type > &axisAngleRotation)
Definition: vctRodriguezRotation3Base.h:214
ThisType Normalized(void) const
Definition: vctAxisAngleRotation3.h:542
Declaration of vctFixedSizeVector.
void ThrowUnlessIsNormalized(void) const
Definition: vctRodriguezRotation3Base.h:84
void Assign(const OtherT &other)
Definition: cisstVectorEigenAddons.h:3
ThisType Normalized(void) const
Definition: vctRodriguezRotation3Base.h:304
ThisType & FromRaw(const vctQuaternionRotation3Base< __containerType > &quaternionRotation)
Definition: vctRodriguezRotation3Base.h:249
void vctRodriguezRotation3BaseFromRaw(vctRodriguezRotation3Base< _rodriguezType > &rodriguezRotation, const vctMatrixRotation3Base< _matrixType > &matrixRotation)
Definition: vctRodriguezRotation3Base.h:402
#define cmnThrow(a)
Definition: MinimalCmn.h:4
const AngleType & Angle(void) const
Definition: vctAxisAngleRotation3.h:324
const_reference R(void) const
Definition: vctQuaternionBase.h:101
ThisType & From(const vctDynamicConstVectorBase< __vectorOwnerType, value_type > &vector)
Definition: vctRodriguezRotation3Base.h:144
A template for a fixed length vector with fixed spacing in memory.
Definition: vctFixedSizeVectorBase.h:76
VCT_CONTAINER_TRAITS_TYPEDEFS(typename ContainerType::value_type)
ThisType & FromNormalized(const vctDynamicConstVectorBase< __vectorOwnerType, value_type > &vector)
Definition: vctRodriguezRotation3Base.h:193
ThisType & From(const vctAxisAngleRotation3< value_type > &axisAngleRotation)
Definition: vctRodriguezRotation3Base.h:169
bool IsNormalized(value_type CMN_UNUSED(tolerance)=TypeTraits::Tolerance()) const
Definition: vctRodriguezRotation3Base.h:319
Definition: vctDynamicConstVectorBase.h:77
A template for a fixed length vector with fixed spacing in memory.
Definition: vctFixedSizeConstVectorBase.h:107
ThisType & FromRaw(const vctAxisAngleRotation3< value_type > &axisAngleRotation)
Definition: vctRodriguezRotation3Base.h:262
_containerType BaseType
Definition: vctRodriguezRotation3Base.h:73
Define a rotation quaternion for a space of dimension 3.
Definition: vctForwardDeclarations.h:208
Macros to export the symbols of cisstVector (in a Dll).
A collection of useful information about the C++ basic types, represented in a generic programming wa...
Definition: cmnTypeTraits.h:155
vctRodriguezRotation3Base(value_type x, value_type y, value_type z)
Definition: vctRodriguezRotation3Base.h:117
ThisType & FromNormalized(const vctFixedSizeConstVectorBase< 3, __stride, value_type, __dataPtrType > &vector)
Definition: vctRodriguezRotation3Base.h:177
ThisType & FromRaw(const vctMatrixRotation3Base< __containerType > &matrixRotation)
Definition: vctRodriguezRotation3Base.h:256
const double cmnPI
Definition: cmnConstants.h:38
vctRodriguezRotation3Base< ContainerType > ThisType
Definition: vctRodriguezRotation3Base.h:75
Define a rotation based on the rodriguez representation for a space of dimension 3.
Definition: vctForwardDeclarations.h:214
ThisType Inverse(void) const
Definition: vctRodriguezRotation3Base.h:279
cmnTypeTraits< value_type > TypeTraits
Definition: vctRodriguezRotation3Base.h:79