Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TestQuaternion.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 /**
26  @file TestQuaternion.cpp
27  @relates Quaternion
28  @brief Test quaternion usage and consistency with rotation matrix
29  @ingroup g_tests
30  @author MIP
31 */
32 
33 #include <Base/Common/CompareFloatingPoint.hh>
34 #include <Base/Geometry/Quaternion.hh>
35 #include <Base/Math/Random.hh>
36 
37 using namespace std;
38 using namespace BIAS;
39 
40 
41 Quaternion<double> GenerateRandomQuaternion(Random &randomizer, double angle)
42 {
44  Q[3] = cos(0.5*angle);
45  Q[0] = Q[1] = Q[2] = sin(0.5*angle);
46  Vector3<double> axis;
47  do {
48  axis.Set(randomizer.GetUniformDistributed(-1.0, 1.0),
49  randomizer.GetUniformDistributed(-1.0, 1.0),
50  randomizer.GetUniformDistributed(-1.0, 1.0));
51  } while (Equal(axis.NormL2(), 0.0));
52  axis.Normalize();
53  for (int j = 0; j < 3; j++) Q[j] *= axis[j];
54  Q.Normalize();
55  return Q;
56 }
57 
58 Quaternion<double> GenerateRandomQuaternion(Random &randomizer)
59 {
60  double angle = randomizer.GetUniformDistributed(-2.0*M_PI, 2.0*M_PI);
61  return GenerateRandomQuaternion(randomizer, angle);
62 }
63 
64 Vector3<double> GenerateRandomVector(Random &randomizer)
65 {
66  Vector3<double> vec;
67  do {
68  vec.Set(randomizer.GetUniformDistributed(-100.0, 100.0),
69  randomizer.GetUniformDistributed(-100.0, 100.0),
70  randomizer.GetUniformDistributed(-100.0, 100.0));
71  } while (Equal(vec.NormL2(), 0.0));
72  return vec;
73 }
74 
75 double TestQuatQuatMult(Quaternion<double> &q, Quaternion<double> &p,
76  const double epsilon = 1e-12,
77  const bool verbose = false)
78 {
79  Quaternion<double> qp = q*p;
81  Matrix4x4<double> R = p.GetQuaternionMultMatrixRight();
82  Quaternion<double> Lp = L*p;
83  Quaternion<double> Rq = R*q;
84 
85  // compare quaternion multiplication results
86  double diffL = (Lp-qp).NormL2();
87  double diffR = (Rq-qp).NormL2();
88  double maxDiffLR = (diffL > diffR ? diffL : diffR);
89  if (verbose) {
90  cout << "q = " << q << ", p = " << p << ", q*p = " << qp << endl
91  << "L(q)*p = " << Lp << ", |L(q)*p - q*p| = " << diffL << endl
92  << "R(p)*q = " << Rq << ", |R(p)*q - q*p| = " << diffR << endl;
93  }
94  BIASASSERT(Equal(diffL, 0.0, epsilon));
95  BIASASSERT(Equal(diffR, 0.0, epsilon));
96 
97  // compare result with rotation matrix
98  RMatrixBase Mq, Mp;
99  Mq.SetFromQuaternion(q);
100  Mp.SetFromQuaternion(p);
101  RMatrixBase MqMp = Mq*Mp;
103 #ifdef BIAS_DEBUG
104  BIASASSERT(MqMp.GetQuaternion(r) == 0);
105 #else
106  MqMp.GetQuaternion(r);
107 #endif
108 
109  double diffQuatR = fabs(r.ScalarProduct(qp))-1.0;
110  if (verbose) {
111  cout << "|<quat(M(q)*M(p)), q*p>| = " << diffQuatR+1.0 << endl << flush;
112  }
113  BIASASSERT(Equal(diffQuatR, 0.0, epsilon));
114 
115  return (fabs(diffQuatR) > maxDiffLR ? fabs(diffQuatR) : maxDiffLR);
116 }
117 
118 double TestQuatVecMult(Quaternion<double> &q, Vector3<double> &v,
119  const double epsilon = 1e-12,
120  const bool verbose = false)
121 {
122  // compare quaternion - vector multiplication with
123  // rotation matrix - vector multiplication
124  Vector3<double> qvq;
125  q.MultVec(v, qvq);
126  RMatrixBase R;
127  R.SetFromQuaternion(q);
128  Vector3<double> Rv = R*v;
129  double diffV = (Rv-qvq).NormL2();
130  if (verbose) {
131  cout << "v = " << v << ", q*v*q' = " << qvq
132  << ", |R*v - q*v*q'| = " << diffV << endl << flush;
133  }
134  BIASASSERT(Equal(diffV, 0.0, epsilon));
135  return diffV;
136 }
137 
138 int main()
139 {
140  const int num = 10000;
141  const double epsilon = 1e-12;
142  const bool verbose = false;
143  Random randomizer;
144 
145  cout << "\ntest quaternions for " << num << " random rotations"
146  << "\n---------------------------------------------------\n";
147 
148  double error, maxError = 0.0;
149  Quaternion<double> q, p;
150  Vector3<double> v;
151  for (int n = 0; n < num; n++)
152  {
153  q = GenerateRandomQuaternion(randomizer);
154  p = GenerateRandomQuaternion(randomizer);
155  v = GenerateRandomVector(randomizer);
156  error = TestQuatQuatMult(q, p, epsilon, verbose);
157  if (error > maxError) maxError = error;
158  error = TestQuatVecMult(q, v, epsilon, verbose);
159  if (error > maxError) maxError = error;
160  error = TestQuatVecMult(p, v, epsilon, verbose);
161  if (error > maxError) maxError = error;
162  }
163  cout << "max. error = " << setprecision(30) << maxError << endl << endl;
164 
165  return 0;
166 }
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
int SetFromQuaternion(const Quaternion< ROTATION_MATRIX_TYPE > &q)
Set rotation matrix from a quaternion.
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
Matrix4x4< QUAT_TYPE > GetQuaternionMultMatrixLeft() const
Returns matrix which expresses (left) quaternion multiplication.
int MultVec(const Vector3< QUAT_TYPE > &vec, Vector3< QUAT_TYPE > &res) const
rotates the given Vector qith the quaternion ( q v q* ) the resulting vector is given in res ...
Definition: Quaternion.hh:136
int GetQuaternion(Quaternion< ROTATION_MATRIX_TYPE > &quat) const
Calculates quaternion representation for this rotation matrix.
void Normalize()
Scales quaternion to unit length, i.e.
Definition: Quaternion.hh:236
void ScalarProduct(const Vector4< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
Definition: Vector4.hh:475
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
Implements a 3D rotation matrix.
Definition: RMatrixBase.hh:44
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
class for producing random numbers from different distributions
Definition: Random.hh:51
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633