pinocchio  UNKNOWN
quaternion.hpp
1 //
2 // Copyright (c) 2016,2018 CNRS
3 //
4 // This file is part of Pinocchio
5 // Pinocchio is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // Pinocchio is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // Pinocchio If not, see
16 // <http://www.gnu.org/licenses/>.
17 
18 #ifndef __math_quaternion_hpp__
19 #define __math_quaternion_hpp__
20 
21 #include "pinocchio/math/fwd.hpp"
22 
23 namespace se3
24 {
33  template<typename D1, typename D2>
34  typename D1::Scalar
35  angleBetweenQuaternions(const Eigen::QuaternionBase<D1> & q1,
36  const Eigen::QuaternionBase<D2> & q2)
37  {
38  typedef typename D1::Scalar Scalar;
39  const Scalar innerprod = q1.dot(q2);
40  Scalar theta = acos(innerprod);
41  const Scalar PI_value = PI<Scalar>();
42 
43  if(innerprod < 0)
44  return PI_value - theta;
45 
46  return theta;
47  }
48 
58  template<typename D1, typename D2>
59  bool defineSameRotation(const Eigen::QuaternionBase<D1> & q1,
60  const Eigen::QuaternionBase<D2> & q2,
61  const typename D1::RealScalar & prec = Eigen::NumTraits<typename D1::Scalar>::dummy_precision())
62  {
63  return (q1.coeffs().isApprox(q2.coeffs(), prec) || q1.coeffs().isApprox(-q2.coeffs(), prec) );
64  }
65 
87  template<typename D>
88  void firstOrderNormalize(const Eigen::QuaternionBase<D> & q)
89  {
90  typedef typename D::Scalar Scalar;
91  const Scalar N2 = q.squaredNorm();
92 #ifndef NDEBUG
93  const Scalar epsilon = sqrt(sqrt(Eigen::NumTraits<Scalar>::epsilon()));
94  assert(std::fabs(N2-1.) <= epsilon);
95 #endif
96  const Scalar alpha = ((Scalar)3 - N2) / Scalar(2);
97  const_cast <Eigen::QuaternionBase<D> &> (q).coeffs() *= alpha;
98 #ifndef NDEBUG
99  const Scalar M = Scalar(3) * std::pow(Scalar(1)-epsilon, ((Scalar)-Scalar(5))/Scalar(2)) / Scalar(4);
100  assert(std::fabs(q.norm() - Scalar(1)) <=
101  std::max(M * sqrt(N2) * (N2 - Scalar(1))*(N2 - Scalar(1)) / Scalar(2), Eigen::NumTraits<Scalar>::dummy_precision()));
102 #endif
103  }
104 
106  template<typename D>
107  void uniformRandom(const Eigen::QuaternionBase<D> & q)
108  {
109  typedef typename D::Scalar Scalar;
110  typedef Eigen::QuaternionBase<D> Base;
111 
112  // Rotational part
113  const Scalar u1 = (Scalar)rand() / RAND_MAX;
114  const Scalar u2 = (Scalar)rand() / RAND_MAX;
115  const Scalar u3 = (Scalar)rand() / RAND_MAX;
116 
117  const Scalar mult1 = sqrt(Scalar(1)-u1);
118  const Scalar mult2 = sqrt(u1);
119 
120  const Scalar PI_value = PI<Scalar>();
121  Scalar s2,c2; SINCOS(Scalar(2)*PI_value*u2,&s2,&c2);
122  Scalar s3,c3; SINCOS(Scalar(2)*PI_value*u3,&s3,&c3);
123 
124  const_cast <Base &> (q).w() = mult1 * s2;
125  const_cast <Base &> (q).x() = mult1 * c2;
126  const_cast <Base &> (q).y() = mult2 * s3;
127  const_cast <Base &> (q).z() = mult2 * c3;
128  }
129 }
130 #endif //#ifndef __math_quaternion_hpp__
D1::Scalar angleBetweenQuaternions(const Eigen::QuaternionBase< D1 > &q1, const Eigen::QuaternionBase< D2 > &q2)
Compute the minimal angle between q1 and q2.
Definition: quaternion.hpp:35
void uniformRandom(const Eigen::QuaternionBase< D > &q)
Uniformly random quaternion sphere.
Definition: quaternion.hpp:107
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)
Definition: quaternion.hpp:88
bool defineSameRotation(const Eigen::QuaternionBase< D1 > &q1, const Eigen::QuaternionBase< D2 > &q2, const typename D1::RealScalar &prec=Eigen::NumTraits< typename D1::Scalar >::dummy_precision())
Check if two quaternions define the same rotations.
Definition: quaternion.hpp:59