BALL  1.4.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
quaternion.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 2; -*-
2 // vi: set ts=2:
3 
4 #ifndef BALL_MATHS_QUATERNION_H
5 #define BALL_MATHS_QUATERNION_H
6 
7 #ifndef BALL_MATHS_MATRIX44_H
8 # include <BALL/MATHS/matrix44.h>
9 #endif
10 
11 #ifndef BALL_MATHS_VECTOR3_H
12 # include <BALL/MATHS/vector3.h>
13 #endif
14 
15 #include <boost/math/quaternion.hpp>
16 #include <iostream>
17 
18 namespace BALL
19 {
24 
29  template <typename T>
31  : public boost::math::quaternion<T> //{/*...*/};
32  {
33  public:
34 
36 
37 
40 
45  TQuaternion();
46 
51  TQuaternion(const TQuaternion& q);
52 
57  TQuaternion(const boost::math::quaternion<T>& q);
58 
66  TQuaternion(const T& w, const T& i, const T& j, const T& k);
67 
73  TQuaternion(const TVector3<T>& axis, const T& angle);
74 
79  ~TQuaternion();
80 
84  void clear();
85 
87 
90 
92  void set(const TQuaternion& q);
93 
95  void set(const boost::math::quaternion<T>& q);
96 
103  void set(const TVector3<T>& axis, const T& angle);
104 
111  void set(const T& w, const T& i, const T& j, const T& k);
112 
117 
121  TQuaternion& operator = (const boost::math::quaternion<T>& q);
122 
127  void setIdentity();
128 
134 
138  void swap(TQuaternion& q);
139 
144  void fromAxisAngle(const TVector3<T>& axis, const T& angle);
145 
153  void fromEulerAngles(const T& yaw, const T& pitch, const T& roll);
154 
160  void toAxisAngle(TVector3<T>& axis, T& angle);
161 
169  void toEulerAngles(T& yaw, T& pitch, T& roll);
170  //void toEA(T& yaw, T& pitch, T& roll);
171 
176  void get(TQuaternion& q) const;
177 
181  T getAngle() const;
182 
187 
193 
197  TQuaternion getInverse() const;
198 
203  TQuaternion getConjugate() const;
205 
208 
212  T& w();
213 
217  const T& w() const;
218 
222  T& i();
223 
227  const T& i() const;
228 
232  T& j();
233 
237  const T& j() const;
238 
242  T& k();
243 
247  const T& k() const;
248 
249 
251 
254 
261  void dump(std::ostream& s = std::cout, Size depth = 0) const;
263 
264  };
266 
267  template <typename T>
269  : boost::math::quaternion<T>()
270  {
271  this->setIdentity();
272  }
273 
274  template <typename T>
276  : boost::math::quaternion<T>(q)
277  {
278  }
279 
280  template <typename T>
281  TQuaternion<T>::TQuaternion(const boost::math::quaternion<T>& q)
282  : boost::math::quaternion<T>(q)
283  {
284  }
285 
286  template <typename T>
287  TQuaternion<T>::TQuaternion(const T& w, const T& i, const T& j, const T& k)
288  : boost::math::quaternion<T>(w, i, j, k)
289  {
290  }
291 
292  template <typename T>
293  TQuaternion<T>::TQuaternion(const TVector3<T>& axis, const T& angle)
294  : boost::math::quaternion<T>()
295  {
296  fromAxisAngle(axis, angle);
297  }
298 
299  template <typename T>
301  {
302  }
303 
304  template <typename T>
306  {
307  this->setIdentity();
308  }
309 
310  template <typename T>
312  {
313  boost::math::quaternion<T>::operator= (q);
314  }
315 
316  template <typename T>
317  void TQuaternion<T>::set(const boost::math::quaternion<T>& q)
318  {
319  boost::math::quaternion<T>::operator= (q);
320  }
321 
322  template <typename T>
324  void TQuaternion<T>::set(const TVector3<T>& axis, const T& angle)
325  {
326  fromAxisAngle(axis, angle);
327  }
328 
329  template <typename T>
331  void TQuaternion<T>::set(const T& w, const T& i, const T& j, const T& k)
332  {
333  this->a = w;
334  this->b = i;
335  this->c = j;
336  this->d = k;
337 
338  }
339 
340  template <typename T>
342  TQuaternion<T>& TQuaternion<T>::operator = (const boost::math::quaternion<T>& q)
343  {
344  set(q);
345  return *this;
346  }
347 
348  template <typename T>
351  {
352  set(q);
353  return *this;
354  }
355 
356  template <typename T>
359  {
360  this->a = (T)1;
361  this->b = this->c = this->d = (T)0;
362  }
363 
364  template <typename T>
367  {
368  T length = boost::math::norm(*this);
369 
370  if (!(Maths::isEqual(length, (T)0)))
371  {
372  this->a /= length;
373  this->b /= length;
374  this->c /= length;
375  this->d /= length;
376  }
377  return *this;
378  }
379 
380  template <typename T>
382  {
383  T tmp = q.a;
384  q.a = this->a;
385  this->a = tmp;
386 
387  tmp = q.b;
388  q.b = this->b;
389  this->b = tmp;
390 
391  tmp = q.c;
392  q.c = this->c;
393  this->c = tmp;
394 
395  tmp = q.d;
396  q.d = this->d;
397  this->d = tmp;
398  }
399 
400  template <typename T>
401  void TQuaternion<T>::fromAxisAngle(const TVector3<T>& axis, const T& angle)
402  {
403  T length = axis.getLength();
404 
405  if (Maths::isEqual(length, (T)0))
406  {
407  this->b = this->c = this->d = (T)0;
408  this->a = (T)1;
409  }
410  else
411  {
412  T omega = (T) (angle * 0.5);
413  T sin_omega = (T)::sin(omega);
414 
415  this->a = (T)::cos(omega);
416  this->b = axis.x * sin_omega / length;
417  this->c = axis.y * sin_omega / length;
418  this->d = axis.z * sin_omega / length;
419  }
420  }
421 
422  template <typename T>
423  void TQuaternion<T>::fromEulerAngles(const T& yaw, const T& pitch, const T& roll)
424  {
425  T half_yaw = yaw / 2.0;
426  T half_pitch = pitch / 2.0;
427  T half_roll = roll / 2.0;
428 
429  T cosYaw = cos(half_yaw);
430  T sinYaw = sin(half_yaw);
431 
432  T cosPitch = cos(half_pitch);
433  T sinPitch = sin(half_pitch);
434 
435  T cosRoll = cos(half_roll);
436  T sinRoll = sin(half_roll);
437 
438 
439  this->a = cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw;
440  this->b = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
441  this->c = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
442  this->d = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
443 
444  }
445 
446  template <typename T>
448  {
449  T length = sqrt(this->b*this->b + this->c*this->c + this->d*this->d);
450 
451  if (Maths::isEqual(length, (T)0))
452  {
453  axis.x = axis.y = angle= (T)0;
454  axis.y = (T)1;
455  }
456  else
457  {
458  angle = 2 * (T)::acos(this->a);
459  axis.x = this->b / length;
460  axis.y = this->c / length;
461  axis.z = this->d / length;
462  }
463  }
464 
465 
466  template <typename T>
467  void TQuaternion<T>::toEulerAngles(T& yaw, T& pitch, T& roll)
468  {
469  TMatrix4x4<T> matrix;
470  getRotationMatrix(matrix);
471  T sinYaw, cosYaw, sinPitch, cosPitch, sinRoll, cosRoll;
472 
473  sinPitch = -matrix(2,0);
474  cosPitch = sqrt(1 - sinPitch*sinPitch);
475 
476  if ( fabs(cosPitch) > Constants::EPSILON)
477  {
478  sinRoll = matrix(2,1) / cosPitch;
479  cosRoll = matrix(2,2) / cosPitch;
480  sinYaw = matrix(1,0) / cosPitch;
481  cosYaw = matrix(0,0) / cosPitch;
482  }
483  else
484  {
485  sinRoll = -matrix(1,2);
486  cosRoll = matrix(1,1);
487  sinYaw = 0;
488  cosYaw = 1;
489  }
490 
491  /* yaw */
492  yaw = atan2(sinYaw, cosYaw);
493 
494  /* pitch */
495  pitch = atan2(sinPitch, cosPitch);
496 
497  /* roll */
498  roll = atan2(sinRoll, cosRoll);
499 
500  }
501 
502  template <typename T>
505  {
506  q.set(*this);
507  }
508 
509  template <typename T>
511  {
512  T length = sqrt(this->b*this->b + this->c*this->c + this->d*this->d);
513  if (Maths::isEqual(length, (T)0))
514  {
515  return (T)(0);
516  }
517  else
518  {
519  return (T)(2 * (T)::acos(this->a));
520  }
521  }
522 
523  template <typename T>
525  {
526  T length = sqrt(this->b*this->b + this->c*this->c + this->d*this->d);
527  if (Maths::isEqual(length, (T)0))
528  {
529  return TVector3<T>((T)0,(T)0,(T)1);
530  }
531  else
532  {
533  return TVector3<T>(this->b/length, this->c/length, this->d/length);
534  }
535  }
536 
537  template <typename T>
539  {
540  T s = 2.0 / boost::math::norm(*this);
541  m.set
542  (
543  (T)(1.0 - s * (this->c * this->c + this->d * this->d)),
544  (T)(s * (this->b * this->c - this->d * this->a)),
545  (T)(s * (this->d * this->b + this->c * this->a)),
546  (T)0,
547 
548  (T)(s * (this->b * this->c + this->d * this->a)),
549  (T)(1.0 - s * (this->d * this->d + this->b * this->b)),
550  (T)(s * (this->c * this->d - this->b * this->a)),
551  (T)0,
552 
553  (T)(s * (this->d * this->b - this->c * this->a)),
554  (T)(s * (this->c * this->d + this->b * this->a)),
555  (T)(1.0 - s * (this->c * this->c + this->b * this->b)),
556  (T)0,
557 
558  (T)0,
559  (T)0,
560  (T)0,
561  (T)1
562  );
563 
564  return m;
565  }
566 
567  template <typename T>
570  {
571 
572  return conj(*this) / boost::math::norm(*this);
573  }
574 
575  template <typename T>
578  {
579  return conj(*this);
580  }
581 
582  template <typename T>
583  const T& TQuaternion<T>::w() const
584  {
585  return this->a;
586  }
587 
588  template <typename T>
590  {
591  return this->a;
592  }
593 
594  template <typename T>
595  const T& TQuaternion<T>::i() const
596  {
597  return this->b;
598  }
599 
600  template <typename T>
602  {
603  return this->b;
604  }
605 
606  template <typename T>
607  const T& TQuaternion<T>::j() const
608  {
609  return this->c;
610  }
611 
612  template <typename T>
614  {
615  return this->c;
616  }
617 
618  template <typename T>
619  const T& TQuaternion<T>::k() const
620  {
621  return this->d;
622  }
623 
624  template <typename T>
626  {
627  return this->d;
628  }
629 
630  template <typename T>
631  std::istream& operator >>(std::istream& s, TQuaternion<T>& q)
632 
633  {
634  char c;
635  s >> c >> q.w() >> c >> q.i() >> c >> q.j() >> c >>q.k() >> c;
636  return s;
637  }
638 
639  template <typename T>
640  std::ostream& operator << (std::ostream& s, const TQuaternion<T>& q)
641 
642  {
643  s << '(' << q.w() << ',' << q.i() << ','
644  << q.j() << ',' << q.k() << ')';
645 
646  return s;
647  }
648 
649  template <typename T>
650  void TQuaternion<T>::dump(std::ostream& s, Size depth) const
651  {
653 
654  BALL_DUMP_HEADER(s, this, this);
655 
656  BALL_DUMP_DEPTH(s, depth);
657  s << " w: " << this->w() << std::endl;
658 
659  BALL_DUMP_DEPTH(s, depth);
660  s << " i: " << this->i() << std::endl;
661 
662  BALL_DUMP_DEPTH(s, depth);
663  s << " j: " << this->j() << std::endl;
664 
665  BALL_DUMP_DEPTH(s, depth);
666  s << " k: " << this->k() << std::endl;
667 
669  }
670 
671 
672 
674 
675 } // namespace BALL
676 
677 #endif // BALL_MATHS_QUATERNION_H