imunano33  0.1.1
quaternion.hpp
Go to the documentation of this file.
1 
7 #ifndef INCLUDE_IMUNANO33_QUATERNION_HPP_
8 #define INCLUDE_IMUNANO33_QUATERNION_HPP_
9 
10 #ifdef IMUNANO33_EMBED
11 #include <math.h>
12 #else
13 #include <cmath>
14 #endif
15 
16 #ifdef IMUNANO33_EMBED
17 #include "imunano33/sv_embed.hpp"
18 #else
20 #endif
21 #include "imunano33/unit.hpp"
22 
23 namespace imunano33 {
24 #ifdef IMUNANO33_EMBED
25 using Vector3D =
27 #else
28 using std::cos;
29 using std::sin;
30 using std::sqrt;
31 using svector::Vector3D;
32 #endif
33 
40 class Quaternion {
41 public:
47  Quaternion() : m_w{1} {}
48 
55  Quaternion(const num_t w, const Vector3D &vec) : m_vec{vec} {
56  // makes sure that quaternion magnitude is nonzero
57  // this is important for rotations
58  if (w == 0 && isZero(vec)) {
59  m_w = 1;
60  } else {
61  m_w = w;
62  }
63  }
64 
73  Quaternion(const Vector3D &vec, const num_t ang) : m_w{cos(ang / 2)} {
74  const Vector3D norm = normalize(vec);
75  m_vec = normalize(vec) * sin(ang / 2);
76  }
77 
83  Quaternion(const Quaternion &other) = default;
84 
88  Quaternion &operator=(const Quaternion &other) = default;
89 
93  ~Quaternion() = default;
94 
98  Quaternion(Quaternion &&) = default;
99 
104 
110  num_t w() const { return m_w; }
111 
117  Vector3D vec() const { return m_vec; }
118 
124  Quaternion conj() const { return Quaternion{m_w, -m_vec}; }
125 
131  Quaternion inv() const {
132  const Quaternion conju = conj();
133  const num_t mag = norm();
134  const num_t newW = conju.w() / (mag * mag);
135  const Vector3D newVec = conju.vec() / (mag * mag);
136 
137  return Quaternion{newW, newVec};
138  }
139 
147  num_t norm() const {
148  return sqrt(m_w * m_w + x(m_vec) * x(m_vec) + y(m_vec) * y(m_vec) +
149  z(m_vec) * z(m_vec));
150  }
151 
161  Quaternion unit() const {
162  const num_t mag = norm();
163  const num_t newW = m_w / mag;
164  const Vector3D newVec = m_vec / mag;
165 
166  return Quaternion{newW, newVec};
167  }
168 
169  // defined later, where operators are defined
170  Quaternion &operator*=(const Quaternion &other);
171  Vector3D rotate(const Vector3D &vec) const;
172  static Vector3D rotate(const Vector3D &vec, const Vector3D &axis, num_t ang);
173 
174 private:
175  num_t m_w;
176  Vector3D m_vec;
177 };
178 
187 inline Quaternion operator*(const Quaternion &lhs, const Quaternion &rhs) {
188 #ifdef IMUNANO33_EMBED
189  using Vector3D =
191 #else
192  using svector::Vector3D;
193 #endif
194 
195  const num_t wl = lhs.w();
196  const num_t wr = rhs.w();
197 
198  const Vector3D vl = lhs.vec();
199  const Vector3D vr = rhs.vec();
200 
201  return Quaternion{wl * wr - dot(vl, vr), vr * wl + vl * wr + cross(vl, vr)};
202 }
203 
212 inline bool operator==(const Quaternion &lhs, const Quaternion &rhs) {
213  return lhs.w() == rhs.w() && lhs.vec() == rhs.vec();
214 }
215 
224 inline bool operator!=(const Quaternion &lhs, const Quaternion &rhs) {
225  return !(lhs == rhs);
226 }
227 
237 inline Vector3D Quaternion::rotate(const Vector3D &vec, const Vector3D &axis,
238  const num_t ang) {
239  const Quaternion rotQ{normalize(axis), ang};
240  const Quaternion vecQ{0, vec};
241  const Quaternion res = rotQ * vecQ * rotQ.conj();
242 
243  return res.vec();
244 }
245 
254  const Quaternion res = (*this) * other;
255  m_w = res.w();
256  m_vec = res.vec();
257 
258  return *this;
259 }
260 
268 inline Vector3D Quaternion::rotate(const Vector3D &vec) const {
269  const Quaternion vecQ = {0, vec};
270  const Quaternion res = (*this) * vecQ * inv();
271 
272  return res.vec();
273 }
274 } // namespace imunano33
275 
276 #endif
bool operator==(const Quaternion &lhs, const Quaternion &rhs)
Equality of two quaternions.
Definition: quaternion.hpp:212
bool operator!=(const Quaternion &lhs, const Quaternion &rhs)
Inequality of two quaternions.
Definition: quaternion.hpp:224
Quaternion operator*(const Quaternion &lhs, const Quaternion &rhs)
Product of two quaternions.
Definition: quaternion.hpp:187
A minimized version of vectors for embedded devices without access to the STL (such as on an Arduino,...
Contains imunano33::TempUnit and imunano33::PressureUnit enums, in addition to number type.
double num_t
Alias to number type depending on embed.
Definition: unit.hpp:34
A simple quaternion class for rotations.
Definition: quaternion.hpp:40
Quaternion unit() const
Gets equivalent unit quaternion.
Definition: quaternion.hpp:161
Quaternion inv() const
Gets quaternion inverse.
Definition: quaternion.hpp:131
Quaternion(const Vector3D &vec, const num_t ang)
Constructor for a rotation quaternion.
Definition: quaternion.hpp:73
Quaternion(const num_t w, const Vector3D &vec)
Constructor for a basic quaternion.
Definition: quaternion.hpp:55
Quaternion conj() const
Gets the quaternion conjugate.
Definition: quaternion.hpp:124
Vector3D rotate(const Vector3D &vec) const
Rotates a vector with current quaternion object.
Definition: quaternion.hpp:268
Quaternion & operator=(const Quaternion &other)=default
Assignment operator.
num_t norm() const
Gets quaternion norm.
Definition: quaternion.hpp:147
Quaternion(const Quaternion &other)=default
Copy constructor.
Quaternion()
Default constructor.
Definition: quaternion.hpp:47
Vector3D vec() const
Gets the vector component of the quaternion.
Definition: quaternion.hpp:117
Quaternion(Quaternion &&)=default
Move constructor.
num_t w() const
Gets the scalar component of the quaternion.
Definition: quaternion.hpp:110
Quaternion & operator*=(const Quaternion &other)
Multiplies a quaternion in place.
Definition: quaternion.hpp:253
Quaternion & operator=(Quaternion &&)=default
Move assignment.
~Quaternion()=default
Destructor.
A simple 3D vector representation.
Definition: simplevectors.hpp:844
A minimal 3D vector representation.
Definition: sv_embed.hpp:168