Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
DualQuaternion.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 #include "DualQuaternion.hh"
27 #include <Base/Math/Matrix4x4.hh>
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 
33 template <class QUAT_TYPE>
36  Vector3<QUAT_TYPE> &translation) const
37 {
38  // @todo check unit norm constraint of this dual quaternion!!
39 
40  rotation = real;
42  dual.Mult(real.Inverse(), qt);
43  translation.Set(QUAT_TYPE(2.0)*qt[0], QUAT_TYPE(2.0)*qt[1], QUAT_TYPE(2.0)*qt[2]);
44 }
45 
46 
47 template <class QUAT_TYPE>
50  const Vector3<QUAT_TYPE> &translation)
51 {
52  real = rotation;
53  Vector3<QUAT_TYPE> r(real[0], real[1], real[2]);
54  Vector3<QUAT_TYPE> d = QUAT_TYPE(0.5) * (real[3]*translation +
55  translation.CrossProduct(r));
56  dual[0] = d[0]; dual[1] = d[1]; dual[2] = d[2];
57  dual[3] = QUAT_TYPE(-0.5) * translation.ScalarProduct(r);
58 
59  // @todo check unit norm constraint of this dual quaternion!!
60 }
61 
62 
63 template <class QUAT_TYPE>
66 {
67  PoseParametrization params;
68  Quaternion<QUAT_TYPE> rotation;
69  Vector3<QUAT_TYPE> translation;
70  GetRigidMotion(rotation, translation);
71  params.Set(Vector3<PP_TYPE>((PP_TYPE)translation[0],
72  (PP_TYPE)translation[1],
73  (PP_TYPE)translation[2]),
74  Quaternion<PP_TYPE>((PP_TYPE)rotation[0],
75  (PP_TYPE)rotation[1],
76  (PP_TYPE)rotation[2],
77  (PP_TYPE)rotation[3]));
78  return params;
79 }
80 
81 
82 template <class QUAT_TYPE>
85 {
86  Quaternion<PP_TYPE> rotation = params.GetOrientation();
87  Vector3<PP_TYPE> translation = params.GetPosition();
88  SetFromRigidMotion(Quaternion<QUAT_TYPE>((QUAT_TYPE)rotation[0],
89  (QUAT_TYPE)rotation[1],
90  (QUAT_TYPE)rotation[2],
91  (QUAT_TYPE)rotation[3]),
92  Vector3<QUAT_TYPE>((QUAT_TYPE)translation[0],
93  (QUAT_TYPE)translation[1],
94  (QUAT_TYPE)translation[2]));
95 }
96 
97 
98 template<class QUAT_TYPE>
100 {
101  Matrix<QUAT_TYPE> res(8, 8, MatrixZero);
102  Matrix4x4<QUAT_TYPE> Lq = real.GetQuaternionMultMatrixLeft();
103  Matrix4x4<QUAT_TYPE> Lp = dual.GetQuaternionMultMatrixLeft();
104  for (register int i = 0; i < 4; i++) {
105  for (register int j = 0; j < 4; j++) {
106  res[i][j] = res[i+4][j+4] = Lq[i][j];
107  res[i+4][j] = Lp[i][j];
108  }
109  }
110  return res;
111 }
112 
113 
114 template<class QUAT_TYPE>
116 {
117  Matrix<QUAT_TYPE> res(8, 8, MatrixZero);
118  Matrix4x4<QUAT_TYPE> Rq = real.GetQuaternionMultMatrixRight();
119  Matrix4x4<QUAT_TYPE> Rp = dual.GetQuaternionMultMatrixRight();
120  for (register int i = 0; i < 4; i++) {
121  for (register int j = 0; j < 4; j++) {
122  res[i][j] = res[i+4][j+4] = Rq[i][j];
123  res[i+4][j] = Rp[i][j];
124  }
125  }
126  return res;
127 }
128 
129 
130 template<class QUAT_TYPE>
133  const QUAT_TYPE &t) const
134 {
135  BIASASSERT(t >= QUAT_TYPE(0.0) && t <= QUAT_TYPE(1.0));
136 
137  // @todo check unit norm constraint of input!!
138 
139  DualQuaternion res;
140  res.real = real.InterpolateLinear(to.real, t);
141  res.dual = dual.InterpolateLinear(to.dual, t);
142 
143  res.Normalize();
144 
145  // @todo check unit norm constraint!!
146 
147  return res;
148 }
149 
150 
151 template<class QUAT_TYPE>
154  const QUAT_TYPE &t) const
155 {
156  BIASASSERT(t >= QUAT_TYPE(0.0) && t <= QUAT_TYPE(1.0));
157 
158  // @todo check unit norm constraint of input!!
159 
160  DualQuaternion res;
161  res.real = real.Interpolate(to.real, t);
162 
163  // @todo complete spherical interpolation of dual part!!
164 
165  // @todo check unit norm constraint!!
166 
167  return res;
168 }
169 
170 
171 template<class QUAT_TYPE> void
174  bool useOtherAngle, bool useOtherPitch)
175 {
176  // @todo check unit norm constraint of this and other dual quaternion!!
177 
178  // make this and other dual quaternion unique
179  MakeUnique();
180  other.MakeUnique();
181 
182  // get aliases for real and dual parts of both quaternions
183  Quaternion<QUAT_TYPE> &q0 = real, &p0 = dual, &q1 = other.real, &p1 = other.dual;
184 
185  // interpolate equal angle and pitch
186  if (useOtherAngle)
187  q0[3] = q1[3];
188  else
189  q0[3] = q1[3] = QUAT_TYPE(0.5) * (q0[3] + q1[3]);
190  if (useOtherPitch)
191  p0[3] = p1[3];
192  else
193  p0[3] = p1[3] = QUAT_TYPE(0.5) * (p0[3] + p1[3]);
194 
195  // re-enforce unit length constraint for q0 and q1
196  QUAT_TYPE q0norm = q0[0]*q0[0] + q0[1]*q0[1] + q0[2]*q0[2];
197  QUAT_TYPE q1norm = q1[0]*q1[0] + q1[1]*q1[1] + q1[2]*q1[2];
198  if (q0norm > QUAT_TYPE(1e-8) && q1norm > QUAT_TYPE(1e-8)) {
199  QUAT_TYPE qscale0 = (QUAT_TYPE)sqrt(double((1-q0[3]*q0[3])/q0norm));
200  QUAT_TYPE qscale1 = (QUAT_TYPE)sqrt(double((1-q1[3]*q1[3])/q1norm));
201  for (register int l = 0; l < 3; l++) {
202  q0[l] *= qscale0;
203  q1[l] *= qscale1;
204  }
205  }
206  // re-enforce orthogonality constraint for q0,p0 and q1,p1
207  QUAT_TYPE q0p0 = q0[0]*p0[0]+q0[1]*p0[1]+q0[2]*p0[2];
208  QUAT_TYPE q1p1 = q1[0]*p1[0]+q1[1]*p1[1]+q1[2]*p1[2];
209  if ((q0p0 > 0 ? q0p0 > QUAT_TYPE(1e-8) : q0p0 < -QUAT_TYPE(1e-8)) &&
210  (q1p1 > 0 ? q1p1 > QUAT_TYPE(1e-8) : q1p1 < -QUAT_TYPE(1e-8))) {
211  QUAT_TYPE pscale0 = -q0[3]*p0[3]/q0p0;
212  QUAT_TYPE pscale1 = -q1[3]*p1[3]/q1p1;
213  for (register int l = 0; l < 3; l++) {
214  p0[l] *= pscale0;
215  p1[l] *= pscale1;
216  }
217  }
218 
219  // @todo check unit norm constraint of resulting dual quaternions!!
220 }
221 
222 
223 template<class QUAT_TYPE> void
226  bool useFirstAngle, bool useFirstPitch)
227 {
228  // @todo check unit norm constraint of all dual quaternions!!
229  if (quats.empty()) return;
230 
231  // make all dual quaternions unique
232  const int n = quats.size();
233  for (int i = 0; i < n; i++)
234  quats[i].MakeUnique();
235 
236  // interpolate equal angle and pitch
237  QUAT_TYPE a = quats[0].real[3], p = quats[0].dual[3];
238  if (!useFirstAngle) {
239  for (int i = 1; i < n; i++)
240  a += quats[i].real[3];
241  a /= QUAT_TYPE(n);
242  }
243  if (!useFirstPitch) {
244  for (int i = 1; i < n; i++)
245  p += quats[i].dual[3];
246  p /= QUAT_TYPE(n);
247  }
248  for (int i = 0; i < n; i++) {
249  quats[i].real[3] = a;
250  quats[i].dual[3] = p;
251  }
252 
253  // re-enforce unit length constraint for all dual quaternions
254  for (int i = 0; i < n; i++) {
255  Quaternion<QUAT_TYPE> &q = quats[i].real;
256  QUAT_TYPE qnorm = q[0]*q[0] + q[1]*q[1] + q[2]*q[2];
257  if (qnorm > QUAT_TYPE(1e-8)) {
258  QUAT_TYPE qscale = (QUAT_TYPE)sqrt(double((1-q[3]*q[3])/qnorm));
259  for (register int l = 0; l < 3; l++)
260  q[l] *= qscale;
261  }
262  }
263 
264  // re-enforce orthogonality constraint for all dual quaternions
265  for (int i = 0; i < n; i++) {
266  Quaternion<QUAT_TYPE> &q = quats[i].real;
267  Quaternion<QUAT_TYPE> &p = quats[i].dual;
268  QUAT_TYPE qp = q[0]*p[0]+q[1]*p[1]+q[2]*p[2];
269  if (qp > 0 ? (qp > QUAT_TYPE(1e-8)) : (qp < -QUAT_TYPE(1e-8))) {
270  QUAT_TYPE pscale = -q[3]*p[3]/qp;
271  for (register int l = 0; l < 3; l++)
272  p[l] *= pscale;
273  }
274  }
275 
276  // @todo check unit norm constraint of resulting dual quaternions!!
277 }
278 
279 
280 // instances for dual quaternions
281 template class BIASGeometryBase_EXPORT BIAS::DualQuaternion<float>;
282 template class BIASGeometryBase_EXPORT BIAS::DualQuaternion<double>;
void Normalize()
Scales dual quaternion to unit length, i.e.
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
void SetFromPoseParametrization(const PoseParametrization &params)
void ScalarProduct(const Vector3< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
Definition: Vector3.hh:603
Quaternion< QUAT_TYPE > InterpolateLinear(const Quaternion< QUAT_TYPE > &to, const QUAT_TYPE &t) const
Linear interpolation between this and given quaternion.
PoseParametrization GetPoseParametrization() const
DualQuaternion< QUAT_TYPE > InterpolateLinear(const DualQuaternion< QUAT_TYPE > &to, const QUAT_TYPE &t) const
void EnforceRigidCouplingConstraint(DualQuaternion< QUAT_TYPE > &other, bool useOtherAngle=false, bool useOtherPitch=false)
Enforce rigid coupling constraint for this and the other given dual quaternion (equal rotation angle ...
class representing rigid motion by dual quaternions
Slim class bundeling pose parametrization and associated covariance matrix.
DualQuaternion< QUAT_TYPE > Interpolate(const DualQuaternion< QUAT_TYPE > &to, const QUAT_TYPE &t) const
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
Definition: Vector3.hh:594
Matrix< QUAT_TYPE > GetLeftMultMatrix() const
Quaternion< QUAT_TYPE > Interpolate(const Quaternion< QUAT_TYPE > &to, const QUAT_TYPE &t) const
Spherical interpolation between this and given quaternion.
void GetRigidMotion(Quaternion< QUAT_TYPE > &rotation, Vector3< QUAT_TYPE > &translation) const
void Mult(const Quaternion< QUAT_TYPE > &quat)
quaternion multiplication: this= this * quat
Definition: Quaternion.hh:73
class Vector3 contains a Vector of fixed dim.
Definition: Matrix.hh:53
Vector3< PP_TYPE > GetPosition() const
returns the position (first 3 entries) part of the pose parametrization vector
void Set(const Vector3< PP_TYPE > &position, const Quaternion< PP_TYPE > &orientation, const Matrix< PP_TYPE > &covariance=Matrix< double >(7, 7, MatrixZero))
Set this from position, orientation and covariance.
matrix class with arbitrary size, indexing is row major.
void MakeUnique()
Make dual quaternion representation unique with respect to the rigid motion it represents.
Matrix< QUAT_TYPE > GetRightMultMatrix() const
void SetFromRigidMotion(const Quaternion< QUAT_TYPE > &rotation, const Vector3< QUAT_TYPE > &translation)
is a &#39;fixed size&#39; quadratic matrix of dim.
Definition: Matrix4x4.hh:54
Quaternion< PP_TYPE > GetOrientation() const
returns the quaternion (last 4 entries) part of the pose parametrization vector