Virtual Testbed
Ship dynamics simulator for extreme conditions
quaternion.hh
1 #ifndef VTESTBED_GEOMETRY_QUATERNION_HH
2 #define VTESTBED_GEOMETRY_QUATERNION_HH
3 
4 #include <iosfwd>
5 
6 #include <vtestbed/base/bstream.hh>
7 #include <vtestbed/geometry/math.hh>
8 #include <vtestbed/geometry/types.hh>
9 
10 namespace vtb {
11 
12  namespace geometry {
13 
14  template <class T>
15  class Quaternion {
16 
17  public:
18  using vec4 = Vertex<T,4>;
19  using vec3 = Vertex<T,3>;
20 
21  private:
22  vec4 _data{1,0,0,0};
23 
24  public:
25  inline Quaternion(): _data{1,0,0,0} {}
26  inline Quaternion(T s, T x, T y, T z): _data{s,x,y,z} {}
27  inline Quaternion(const vec4& q): _data{q(0),q(1),q(2),q(3)} {}
28  inline Quaternion(T re, const vec3& im): _data{re,im(0),im(1),im(2)} {}
29  inline T w() const { return this->_data[0]; }
30  inline T x() const { return this->_data[1]; }
31  inline T y() const { return this->_data[2]; }
32  inline T z() const { return this->_data[3]; }
33  inline void clear() { *this = Quaternion(); }
34  inline T real() const { return w(); }
35  inline vec3 imag() const { return {x(),y(),z()}; }
36  inline T operator()(int i) const { return this->_data[i]; }
37  inline T operator[](int i) const { return this->_data[i]; }
38  inline const vec4& data() const { return this->_data; }
39 
40  static Quaternion exp(const vec3& v);
41 
42  inline friend vtb::base::bstream&
43  operator<<(vtb::base::bstream& out, const Quaternion& rhs) {
44  out << rhs._data;
45  return out;
46  }
47 
48  inline friend vtb::base::bstream&
49  operator>>(vtb::base::bstream& in, Quaternion& rhs) {
50  in >> rhs._data;
51  return in;
52  }
53 
54  };
55 
56  template <class T>
58  operator<<(std::ostream& out, const Quaternion<T>& q);
59 
60  template <class T> inline T real(const Quaternion<T>& q) { return q.real(); }
61  template <class T> inline Vertex<T,3> imag(const Quaternion<T>& q) { return q.imag(); }
62 
64  template <class T>
65  Quaternion<T>
66  operator*(const Quaternion<T>& a, const Quaternion<T>& b);
67 
68  template <class T>
69  Quaternion<T>
70  operator*=(Quaternion<T>& a, const Quaternion<T>& b) {
71  a = a*b;
72  return a;
73  }
74 
75  template <class T>
76  inline Quaternion<T>
77  operator*(const Quaternion<T>& a, T b) {
78  return {a(0)*b, a(1)*b, a(2)*b, a(3)*b};
79  }
80 
81  template <class T>
82  inline Quaternion<T>
83  operator*(T a, const Quaternion<T>& b) {
84  return {a*b(0), a*b(1), a*b(2), a*b(3)};
85  }
86 
87  template <class T>
88  inline Quaternion<T>
89  operator/(const Quaternion<T>& a, T b) {
90  return {a(0)/b, a(1)/b, a(2)/b, a(3)/b};
91  }
92 
93  template <class T>
94  Quaternion<T>
95  operator+(Quaternion<T>& a, const Quaternion<T>& b) {
96  return Quaternion<T>{a(0)+b(0),a(1)+b(1),a(2)+b(2),a(3)+b(3)};
97  }
98 
99  template <class T>
100  Quaternion<T>
101  operator+=(Quaternion<T>& a, const Quaternion<T>& b) {
102  a = a+b;
103  return a;
104  }
105 
106  template <class T>
107  inline Quaternion<T>
108  unit(const Quaternion<T>& q) {
109  return ::vtb::geometry::unit(q.data());
110  }
111 
112  template <class T>
113  inline T
114  length(const Quaternion<T>& q) {
115  return blitz::length(q.data());
116  }
117 
125  template <class T>
126  Vertex<T,3>
127  to_euler_angles(const Quaternion<T>& q);
128 
129  template <class T>
130  Quaternion<T>
131  from_euler_angles(const Vertex<T,3>& angles);
132 
133  template <class T>
134  Rotation_matrix<T,3>
135  rotation_matrix(const Quaternion<T>& q);
136 
137  template <class T>
138  inline Quaternion<T>
139  from_vector(const Quaternion<T>& q) {
140  using blitz::pow2;
141  using std::sqrt;
142  return Quaternion<T>{
143  sqrt(1 - pow2(q(1)) - pow2(q(2)) - pow2(q(3))),
144  q(1),
145  q(2),
146  q(3)
147  };
148  }
149 
150  template <class T>
151  inline Quaternion<T>
152  to_vector(const Quaternion<T>& q) {
153  return Quaternion<T>{0, q(1), q(2), q(3)};
154  }
155 
156  template <class T>
157  inline Quaternion<T>
158  conj(const Quaternion<T>& q) {
159  return Quaternion<T>{q(0), -q(1), -q(2), -q(3)};
160  }
161 
162  template <class T>
163  inline Vertex<T,3>
164  rotate(const Vertex<T,3>& v, const Quaternion<T>& q) {
165  return (q*Quaternion<T>(T{},v)*conj(q)).imag();
166  }
167 
168  template <class T>
170  public:
171  using scalar_type = T;
172  using vertex_type = Vertex<T,3>;
174 
175  private:
176  quaternion_type _quaternion, _quaternion_conj;
177  vertex_type _origin{T{}};
178 
179  public:
180 
181  Quaternion_coordinate_system() = default;
182 
183  inline
185  const quaternion_type& q_conj,
186  const vertex_type& origin):
187  _quaternion(q), _quaternion_conj(q_conj), _origin(origin) {}
188 
189  inline
190  Quaternion_coordinate_system(const quaternion_type& q, const vertex_type& origin):
191  Quaternion_coordinate_system(q, conj(q), origin) {}
192 
193  inline const quaternion_type& quaternion() const { return this->_quaternion; }
194  inline const quaternion_type& quaternion_conj() const { return this->_quaternion_conj; }
195 
196  inline void
197  quaternion(const quaternion_type& rhs) {
198  this->_quaternion = rhs, this->_quaternion_conj = conj(rhs);
199  }
200 
201  inline const vertex_type& origin() const { return this->_origin; }
202  inline void origin(const vertex_type& rhs) { this->_origin = rhs; }
203 
204  inline void clear() {
205  this->_quaternion.clear(), this->_quaternion_conj.clear(),
206  this->_origin = T{};
207  }
208 
209  };
210 
211  template <class T>
213  make_coordinate_system(const Quaternion<T>& q, const Vertex<T,3>& origin) {
214  return Quaternion_coordinate_system<T>(q, origin);
215  }
216 
217  template <class T>
218  inline Quaternion_coordinate_system<T>
219  make_coordinate_system(const Quaternion<T>& q,
220  const Quaternion<T>& q_conj,
221  const Vertex<T,3>& origin) {
222  return Quaternion_coordinate_system<T>(q, q_conj, origin);
223  }
224 
225  template <class T>
226  inline Vertex<T,3>
227  to(const Quaternion_coordinate_system<T>& cs, const Vertex<T,3>& v) {
228  Vertex<T,3> x = v-cs.origin();
229  return rotate(x, cs.quaternion());
230  }
231 
232  template <class T>
233  inline Vertex<T,3>
234  from(const Quaternion_coordinate_system<T>& cs, const Vertex<T,3>& v) {
235  return rotate(v, cs.quaternion_conj()) + cs.origin();
236  }
237 
238  template <class T>
239  inline Vertex<T,3>
240  vector_to(const Quaternion_coordinate_system<T>& cs, const Vertex<T,3>& v) {
241  return rotate(v, cs.quaternion());
242  }
243 
244  template <class T>
245  inline Vertex<T,3>
246  vector_from(const Quaternion_coordinate_system<T>& cs, const Vertex<T,3>& v) {
247  return rotate(v, cs.quaternion_conj());
248  }
249 
250  }
251 
252 }
253 
254 #endif // vim:filetype=cpp
T length(const blitz::TinyVector< T, N > &x)
Computes vector length without overflow.
Definition: blitz.hh:471
Vertex< T, 3 > to_euler_angles(const Quaternion< T > &q)
Convert quaternion to Euler angles.
Main namespace.
Definition: convert.hh:9
T rotate(T... args)
T sqrt(T... args)