emlabcpp
modern opinionated embedded C++ library
quaternion.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "./point.h"
27 
28 namespace emlabcpp
29 {
30 
33 {
34  using container = std::array< float, 4 >;
35  container fields_ = { 0, 0, 0, 1 };
36 
37 public:
38  using value_type = float;
39  using const_iterator = typename container::const_iterator;
40  using iterator = typename container::iterator;
41 
42  constexpr quaternion() noexcept = default;
43 
44  constexpr quaternion( float x, float y, float z, float w ) noexcept
45  : fields_{ x, y, z, w }
46  {
47  }
48 
49  constexpr quaternion( vector< 3 > const& ax, float const& a ) noexcept
50  {
51  float const s = std::sin( a * 0.5f ) / length_of( ax );
52  fields_[0] = ax[0] * s;
53  fields_[1] = ax[1] * s;
54  fields_[2] = ax[2] * s;
55  fields_[3] = std::cos( a * 0.5f );
56  }
57 
58  [[nodiscard]] constexpr float operator[]( std::size_t i ) const noexcept
59  {
60  return fields_[i];
61  }
62 
63  [[nodiscard]] constexpr const_iterator begin() const
64  {
65  return fields_.begin();
66  }
67 
68  [[nodiscard]] constexpr const_iterator end() const
69  {
70  return fields_.end();
71  }
72 
73  [[nodiscard]] constexpr iterator begin()
74  {
75  return fields_.begin();
76  }
77 
78  [[nodiscard]] constexpr iterator end()
79  {
80  return fields_.end();
81  }
82 
83  [[nodiscard]] constexpr std::size_t size() const
84  {
85  return fields_.size();
86  }
87 };
88 
89 constexpr quaternion neutral_quat{ 0.f, 0.f, 0.f, 1.f };
90 
91 constexpr quaternion inverse( quaternion const& q )
92 {
93  return { -q[0], -q[1], -q[2], q[3] };
94 }
95 
96 constexpr quaternion operator-( quaternion const& q )
97 {
98  return { -q[0], -q[1], -q[2], -q[3] };
99 }
100 
101 constexpr float dot( quaternion const& q, quaternion const& s )
102 {
103  return q[0] * s[0] + q[1] * s[1] + q[2] * s[2] + q[3] * s[3];
104 }
105 
106 constexpr float norm2_of( quaternion const& q )
107 {
108  return dot( q, q );
109 }
110 
111 constexpr float angle_shortest_path( quaternion const& m, quaternion const& n )
112 {
113  float const s = std::sqrt( norm2_of( m ) * norm2_of( n ) );
114  float d = dot( m, n );
115  if ( d < 0 )
116  d = dot( m, -n );
117  return float{ std::acos( d / s ) * 2.0f };
118 }
119 
120 constexpr quaternion slerp( quaternion const& q, quaternion const& s, float f )
121 {
122  // NOTE: inspired by tf::Quaternion::slerp
123  float const theta = angle_shortest_path( q, s ) / 2.0f;
124  if ( theta == 0.0f )
125  return q;
126 
127  float const d = 1.0f / std::sin( theta );
128  float const s0 = std::sin( ( 1.0f - f ) * theta );
129  float const s1 = std::sin( f * theta );
130  float m = 1.0f;
131  if ( dot( q, s ) < 0 )
132  m = -1.0f;
133  return {
134  ( q[0] * s0 + m * s[0] * s1 ) * d,
135  ( q[1] * s0 + m * s[1] * s1 ) * d,
136  ( q[2] * s0 + m * s[2] * s1 ) * d,
137  ( q[3] * s0 + m * s[3] * s1 ) * d,
138  };
139 }
140 
141 constexpr bool operator==( quaternion const& q, quaternion const& s )
142 {
143  return q[0] == s[0] && q[1] == s[1] && q[2] == s[2] && q[3] == s[3];
144 }
145 
146 constexpr bool operator!=( quaternion const& q, quaternion const& s )
147 {
148  return !( q == s );
149 }
150 
151 constexpr bool operator<( quaternion const& q, quaternion const& s )
152 {
153  auto iter = find_if( range( 4u ), [&]( std::size_t i ) {
154  return q[i] != s[i];
155  } );
156 
157  auto i = static_cast< std::size_t >( *iter );
158 
159  if ( i == 4 )
160  return false;
161  return q[i] < s[i];
162 }
163 
164 constexpr quaternion operator*( quaternion const& q, quaternion const& s )
165 {
166  return {
167  q[3] * s[0] + q[0] * s[3] + q[1] * s[2] - q[2] * s[1],
168  q[3] * s[1] + q[1] * s[3] + q[2] * s[0] - q[0] * s[2],
169  q[3] * s[2] + q[2] * s[3] + q[0] * s[1] - q[1] * s[0],
170  q[3] * s[3] - q[0] * s[0] - q[1] * s[1] - q[2] * s[2],
171  };
172 }
173 
174 constexpr quaternion operator*( quaternion const& q, point< 3 > const& x )
175 {
176  return q * quaternion{ x[0], x[1], x[2], 0.f };
177 }
178 
179 constexpr quaternion operator*( point< 3 > const& x, quaternion const& q )
180 {
181  return quaternion{ x[0], x[1], x[2], 0.f } * q;
182 }
183 
184 constexpr quaternion operator+( quaternion const& lh, quaternion const& rh )
185 {
186  return { lh[0] + rh[0], lh[1] + rh[1], lh[2] + rh[2], lh[3] + rh[3] };
187 }
188 
189 constexpr bool almost_equal( quaternion const& q, quaternion const& s, float eps = default_epsilon )
190 {
191  return all_of( range< std::size_t >( 4 ), [&]( std::size_t i ) {
192  return almost_equal( q[i], s[i], eps );
193  } );
194 }
195 
197 {
198  // TODO: this needs _testing_
199  x = normalized( x );
200  y = normalized( y );
201 
203  auto d = float( dot( x, y ) );
204 
205  if ( d < -1.0f + default_epsilon )
206  return { c[0], c[1], c[2], 0.0f };
207 
208  float const s = std::sqrt( ( 1.0f + d ) * 2.0f );
209  float const rs = 1.0f / s;
210 
211  return { c[0] * rs, c[1] * rs, c[2] * rs, s * 0.f };
212 }
213 
214 constexpr point< 3 > rotate( point< 3 > const& x, quaternion const& q )
215 {
216  quaternion const r = q * x * inverse( q );
217  return point< 3 >{ r[0], r[1], r[2] };
218 }
219 
220 constexpr quaternion rotate( quaternion const& x, quaternion const& q )
221 {
222  return q * x * inverse( q );
223 }
224 
225 constexpr vector< 3 > rotate( vector< 3 > const& v, quaternion const& q )
226 {
227  return vector_cast( rotate( point_cast( v ), q ) );
228 }
229 
230 } // namespace emlabcpp
API and behavior of this is inspired by tf::Quaternion.
Definition: quaternion.h:33
constexpr const_iterator end() const
Definition: quaternion.h:68
constexpr iterator end()
Definition: quaternion.h:78
constexpr float operator[](std::size_t i) const noexcept
Definition: quaternion.h:58
typename container::const_iterator const_iterator
Definition: quaternion.h:39
constexpr std::size_t size() const
Definition: quaternion.h:83
constexpr iterator begin()
Definition: quaternion.h:73
typename container::iterator iterator
Definition: quaternion.h:40
constexpr quaternion() noexcept=default
constexpr quaternion(vector< 3 > const &ax, float const &a) noexcept
Definition: quaternion.h:49
constexpr const_iterator begin() const
Definition: quaternion.h:63
float value_type
Definition: quaternion.h:38
Definition: vector.h:33
MIT License.
Definition: impl.h:31
constexpr point< N > point_cast(vector< N > const &v)
Definition: point.h:61
constexpr float angle_shortest_path(quaternion const &m, quaternion const &n)
Definition: quaternion.h:111
constexpr float dot(quaternion const &q, quaternion const &s)
Definition: quaternion.h:101
constexpr float default_epsilon
Definition: algorithm.h:40
constexpr point< N > operator+(point< N > a, vector< N > const &b)
Returns a result of addition a to b, viz += operator.
Definition: point.h:93
constexpr bool all_of(Container &&cont, PredicateCallable &&f=std::identity())
Returns true if call to predicate 'f(x)' returns true for all items in 'cont'.
Definition: algorithm.h:342
constexpr auto sin(quantity< Derived, ValueType > const u)
Returns sinus of the quantity as scalar.
Definition: quantity.h:234
constexpr auto sqrt(physical_quantity< Len, Mass, Time, Current, Temp, Mol, Li, Angle, Byte > val)
Square root of physical quantity is square root of it's value and the exponents are divided in half.
Definition: physical_quantity.h:215
constexpr point< N > operator*(point< N > a, point< N > const &b)
Multiplication of points multiplies each coordinate of A by coordinate of B on same dimension.
Definition: point.h:74
constexpr quaternion neutral_quat
Definition: quaternion.h:89
constexpr float length_of(vec_point_base< Derived, N > const &a)
Returns distance of A from [0,0,0], this is a length of vector represented by A.
Definition: vec_point_base.h:203
constexpr vector< 3 > cross_product(vector< 3 > const &a, vector< 3 > const &b)
Calculates cross product between points A and B.
Definition: vector.h:66
constexpr Derived normalized(vec_point_base< Derived, N > const &a)
Calculates normalized version of A, this means that length(A) equals to 1.
Definition: vec_point_base.h:211
constexpr quaternion slerp(quaternion const &q, quaternion const &s, float f)
Definition: quaternion.h:120
constexpr auto cos(quantity< Derived, ValueType > const u)
Returns cosinus of the quantity as scalar.
Definition: quantity.h:227
constexpr pose inverse(pose const &x)
Definition: pose.h:164
constexpr bool operator<(pose const &x, pose const &y)
Definition: pose.h:85
constexpr vector< N > vector_cast(point< N > const &p)
Definition: point.h:67
constexpr vector< N > operator-(point< N > a, point< N > const &b)
Returns a result of subtraction of A from B, viz -= operator.
Definition: point.h:84
constexpr pose rotate(pose const &x, quaternion const &quat)
Pose X is rotated based on quaternion 'quad'.
Definition: pose.h:176
constexpr view< iterators::numeric_iterator< Numeric > > range(Numeric from, Numeric to)
Builds numeric view over interval [from, to)
Definition: range.h:34
constexpr float norm2_of(quaternion const &q)
Definition: quaternion.h:106
constexpr auto find_if(Container &&cont, PredicateCallable &&f=std::identity())
Returns iterator for first item, for which call to predicate f(*iter) holds true.
Definition: algorithm.h:112
constexpr bool operator!=(pose const &x, pose const &y)
negation of operator== between poses
Definition: pose.h:99
constexpr bool almost_equal(T const &lh, T const &rh, float const eps=default_epsilon)
Two items 'lh' and 'rh' are almost equal if their difference is smaller than value 'eps'.
Definition: algorithm.h:87
UnaryCallable && f
Definition: algorithm.h:161
constexpr quaternion shortest_arc_quat(point< 3 > x, point< 3 > y)
Definition: quaternion.h:196
constexpr bool operator==(pose const &x, pose const &y)
compares poses on their position and orientation
Definition: pose.h:93