Virtual Testbed
Ship dynamics simulator for extreme conditions
core/ship.hh
1 #ifndef VTESTBED_CORE_SHIP_HH
2 #define VTESTBED_CORE_SHIP_HH
3 
4 #include <iosfwd>
5 
6 #include <vtestbed/base/blitz.hh>
7 #include <vtestbed/base/bstream.hh>
8 #include <vtestbed/base/constants.hh>
9 #include <vtestbed/core/compartment.hh>
10 #include <vtestbed/core/grid.hh>
11 #include <vtestbed/core/hull.hh>
12 #include <vtestbed/core/macros.hh>
13 #include <vtestbed/core/mass.hh>
14 #include <vtestbed/core/math.hh>
15 #include <vtestbed/core/propulsor.hh>
16 #include <vtestbed/core/types.hh>
17 #include <vtestbed/geometry/basis.hh>
18 #include <vtestbed/geometry/math.hh>
19 #include <vtestbed/geometry/quaternion.hh>
20 #include <vtestbed/geometry/types.hh>
21 
22 namespace vtb {
23 
24  namespace core {
25 
26  template <class T>
28  angular_velocity_matrix_zyx(const Vector<T,3>& sin, const Vector<T,3>& cos) {
29  static constexpr const int theta=1, psi=2;
30  return {{cos(theta)*cos(psi), -sin(psi), 0,
31  cos(theta)*sin(psi), cos(psi), 0,
32  -sin(theta), 0, 1}};
33  }
34 
41  template <class T>
43  angular_velocity_matrix_zyx(const Vector<T,3>& euler_angles) {
44  return angular_velocity_matrix_zyx<T>(sin(euler_angles), cos(euler_angles));
45  }
46 
47  template <class T>
49  angular_velocity_matrix_xyz(const Vector<T,3>& sin, const Vector<T,3>& cos) {
50  static constexpr const int phi=0, theta=1;
51  return {{1, 0, sin(theta),
52  0, cos(phi), -sin(phi)*cos(theta),
53  0, sin(phi), cos(phi)*cos(theta)}};
54  }
55 
56  template <class T>
58  angular_velocity_matrix_xyz(const Vector<T,3>& euler_angles) {
59  return angular_velocity_matrix_xyz<T>(sin(euler_angles), cos(euler_angles));
60  }
61 
62  template <class T>
63  inline blitz::TinyMatrix<T,3,4>
64  angular_velocity_matrix_quaternion(const vtb::geometry::Quaternion<T>& q) {
65  blitz::TinyMatrix<T,3,4> m;
66  m(0,0) = q(1); m(0,1) = -q(0); m(0,2) = -q(3); m(0,3) = q(2);
67  m(1,0) = q(2); m(1,1) = q(3); m(1,2) = -q(0); m(1,3) = -q(1);
68  m(2,0) = q(3); m(2,1) = -q(2); m(2,2) = q(1); m(2,3) = -q(0);
69  m *= 2;
70  return m;
71  }
72 
73  template <class T>
75  euler_angles_matrix_zyx(
76  const Vector<T,3>& sin,
77  const Vector<T,3>& cos,
78  const T tan_theta
79  ) {
80  static constexpr const int theta=1, psi=2;
81  return {{cos(psi)/cos(theta), sin(psi)/cos(theta), 0,
82  -sin(psi), cos(psi), 0,
83  cos(psi)*tan_theta, sin(psi)*tan_theta, 1}};
84  }
85 
92  template <class T>
94  euler_angles_matrix_zyx(const Vector<T,3>& euler_angles) {
95  return euler_angles_matrix_zyx<T>(
96  sin(euler_angles),
97  cos(euler_angles),
98  sin(1)/cos(1)
99  );
100  }
101 
102  template <class T>
104  euler_angles_matrix_xyz(
105  const Vector<T,3>& sin,
106  const Vector<T,3>& cos,
107  const T tan_theta
108  ) {
109  static constexpr const int phi=0, theta=1;
110  return {{1, sin(phi)*tan_theta, -cos(phi)*tan_theta,
111  0, cos(phi), sin(phi),
112  0, -sin(phi)/cos(theta), cos(phi)/cos(theta)}};
113  }
114 
115  template <class T>
117  euler_angles_matrix_xyz(const Vector<T,3>& euler_angles) {
118  return euler_angles_matrix_zyx<T>(
119  sin(euler_angles),
120  cos(euler_angles),
121  sin(1)/cos(1)
122  );
123  }
124 
125  template <class T>
126  inline Vector<T,3>
127  euler_angles_residual_vector_zyx(
128  const Vector<T,3>& sin,
129  const Vector<T,3>& cos,
130  const T tan_theta,
131  const Vector<T,3>& angvelocity
132  ) {
133  static constexpr const int theta=1, psi=2;
134  // common subexpressions
135  auto d_01 = angvelocity(0)*angvelocity(1);
136  auto d_12 = angvelocity(1)*angvelocity(2);
137  auto d_02 = angvelocity(0)*angvelocity(2);
138  return {
139  -sin(theta)*cos(psi)*d_01 - cos(psi)*d_12 - cos(theta)*sin(psi)*d_02,
140  -sin(theta)*sin(psi)*d_01 - sin(psi)*d_12 + cos(theta)*cos(psi)*d_02,
141  -cos(theta)*d_01
142  };
143  }
144 
145  template <class T>
146  inline Vector<T,3>
147  euler_angles_residual_vector_xyz(
148  const Vector<T,3>& sin,
149  const Vector<T,3>& cos,
150  const T tan_theta,
151  const Vector<T,3>& angvelocity
152  ) {
153  static constexpr const int phi=0, theta=1;
154  // common subexpressions
155  auto d_01 = angvelocity(0)*angvelocity(1);
156  auto d_12 = angvelocity(1)*angvelocity(2);
157  auto d_02 = angvelocity(0)*angvelocity(2);
158  return {
159  cos(theta)*d_12,
160  -sin(phi)*d_01 + sin(phi)*sin(theta)*d_12 - cos(phi)*cos(theta)*d_02,
161  cos(phi)*d_01 - cos(phi)*sin(theta)*d_12 - sin(phi)*cos(theta)*d_02
162  };
163  }
164 
165  template <class T>
166  inline blitz::TinyMatrix<T,4,3>
167  quaternion_matrix(const vtb::geometry::Quaternion<T>& q) {
168  blitz::TinyMatrix<T,4,3> m;
169  m(0,0) = q(1); m(0,1) = q(2); m(0,2) = q(3);
170  m(1,0) = -q(0); m(1,1) = q(3); m(1,2) = -q(2);
171  m(2,0) = -q(3); m(2,1) = -q(0); m(2,2) = q(1);
172  m(3,0) = q(2); m(3,1) = -q(1); m(3,2) = -q(0);
173  m /= 2;
174  return m;
175  }
176 
185  template <class T>
186  class Ship {
187 
188  public:
189  using scalar_type = T;
190  using vec3 = blitz::TinyVector<T,3>;
191  using hull_type = Hull<T>;
192  using room_type = Compartment<T>;
195  using mass_type = Mass<T>;
197  using matrix_type = blitz::TinyMatrix<T,3,3>;
204 
205  public:
207  using variables_type = blitz::TinyVector<T,13>;
208  variables_type variables;
209  struct {
210  vec3 position;
211  vec3 velocity;
212  quaternion_type quaternion;
213  vec3 angmomentum;
214  };
215  state_vector_type(): variables{T{}} {}
216  state_vector_type(const state_vector_type& rhs): variables(rhs.variables) {}
217  state_vector_type(const variables_type& rhs): variables(rhs) {}
218  ~state_vector_type() {}
219  inline const variables_type& vars() const { return this->variables; }
220  inline operator const variables_type&() const { return this->variables; }
221  inline state_vector_type&
222  operator=(const variables_type& rhs) { this->variables = rhs; return *this; }
223  };
224  using variables_type = typename state_vector_type::variables_type;
225 
226  static_assert(sizeof(variables_type) == 3*sizeof(vec3) + sizeof(quaternion_type),
227  "bad state_vector");
228  static_assert(sizeof(variables_type) == sizeof(state_vector_type),
229  "bad state_vector");
230 
231  private:
232  // Position coordinates and their first and second time derivatives
233  // (velocity and acceleration).
234  vec3 _position[3] {T{},T{},T{}};
235  // Angular position and its first and second time derivatives.
236  vec3 _angdisplacement[3] {T{},T{},T{}};
237  // Angular momentum.
238  vec3 _angmomentum{T{}};
239  // Rotation quaternion and its first and second time derivatives.
240  quaternion_type _quaternion{1,0,0,0};
241  // Rotation matrix computed from the current Euler angles.
242  rotation_matrix_type _rotation_matrix;
243  rotation_matrix_type _inertia_matrix;
244  hull_type _hull;
245  room_array _rooms;
246  propulsor_type _propulsor;
247  scalar_type _mass{};
248 
249  public:
250 
253  inline const vec3& position(int i=0) const { return this->_position[i]; }
254 
257  inline void position(int i, const vec3& rhs) { this->_position[i] = rhs; }
258 
260  inline const vec3& velocity() const { return position(1); }
261 
263  inline void velocity(const vec3& rhs) { this->_position[1] = rhs; }
264 
266  inline const vec3& acceleration() const { return position(2); }
267 
271  inline const vec3&
272  angular_displacement(int i=0) const {
273  return this->_angdisplacement[i];
274  }
275 
278  inline vec3 euler_angles() const { return to_euler_angles(this->_quaternion); }
279 
281  inline const quaternion_type& quaternion() const { return this->_quaternion; }
282 
284  void euler_angles(const vec3& rhs);
285 
287  void quaternion(const quaternion_type& q);
288 
291  inline T roll() const { return euler_angles()[0]; }
292 
295  inline T pitch() const { return euler_angles()[1]; }
296 
299  inline T yaw() const { return euler_angles()[2]; }
300 
303  inline T surge(int i=0) const { return this->_position[i][0]; }
304 
307  inline T sway(int i=0) const { return this->_position[i][1]; }
308 
311  inline T heave(int i=0) const { return this->_position[i][2]; }
312 
314  inline const vec3& angular_velocity() const { return angular_displacement(1); }
316  void angular_velocity(const vec3& rhs);
317 
319  inline const vec3& angular_acceleration() const { return angular_displacement(2); }
320 
322  inline const vec3& angular_momentum() const { return this->_angmomentum; }
324  inline void angular_momentum(const vec3& rhs) { this->_angmomentum = rhs; }
325 
332  void state_vector(const state_vector_type& v, const state_vector_type& dv, T dt);
333 
334  inline void
335  state_vector(const variables_type& v, const variables_type& dv, T dt) {
336  this->state_vector(
337  reinterpret_cast<const state_vector_type&>(v),
338  reinterpret_cast<const state_vector_type&>(dv),
339  dt
340  );
341  }
342 
349  state_vector_type state_vector() const;
350  void reset();
351  inline const hull_type& hull() const { return this->_hull; }
352  void hull(hull_type&& rhs);
353  void hull(const hull_type& rhs);
354 
355  inline void compartments(const room_array& rhs) { this->_rooms = rhs; }
356  inline room_array& compartments() { return this->_rooms; }
357  inline const room_array& compartments() const { return this->_rooms; }
358  inline const propulsor_type& propulsor() const { return this->_propulsor; }
359  inline void propulsor(const propulsor_type& rhs) { this->_propulsor = rhs; }
360 
361  inline scalar_type mass() const { return this->_mass; }
362 
364  T flooded_mass() const;
365 
366  inline void
367  mass(scalar_type rhs) {
368  if (rhs < 0) { throw std::invalid_argument("bad mass"); }
369  this->_mass = rhs;
370  }
371 
372  inline void
373  displacement(scalar_type rhs) {
374  this->mass(vtb::base::constants<T>::water_density()*rhs);
375  }
376 
377  inline scalar_type
378  displacement() const {
379  return this->mass() / vtb::base::constants<T>::water_density();
380  }
381 
382  inline void
383  draught(scalar_type rhs) {
384  if (rhs < 0) { throw std::invalid_argument("bad draught"); }
385  auto level = hull().bounds(2).min() + rhs;
386  this->displacement(hull().signed_volume_below(2, level));
387  }
388 
389  inline coordinate_system_type
390  earth_fixed_coordinate_system() const {
391  return make_coordinate_system(rotation_matrix(), position(0));
392  }
393 
394  inline quaternion_coordinate_system_type
395  body_fixed_coordinate_system() const {
396  return make_coordinate_system(conj(quaternion()), position(0));
397  }
398 
399  inline const rotation_matrix_type&
400  rotation_matrix() const {
401  return this->_rotation_matrix;
402  }
403 
417  inline const rotation_matrix_type&
418  inertia_matrix() const {
419  return this->_inertia_matrix;
420  }
421 
422  void dump(std::ostream& out) const;
423 
424  template <class X>
425  friend std::ostream&
426  operator<<(std::ostream& out, const Ship<X>& rhs);
427 
428  template <class X>
429  friend bstream&
430  operator<<(bstream& out, const Ship<X>& rhs);
431 
432  template <class X>
433  friend bstream&
434  operator>>(bstream& in, Ship<X>& rhs);
435 
436  private:
437 
438  inline void
439  angular_displacement(int i, const vec3& rhs) {
440  this->_angdisplacement[i] = rhs;
441  }
442 
443  };
444 
445  template <class T>
446  std::ostream&
447  operator<<(std::ostream& out, const Ship<T>& rhs);
448 
449  template <class T>
450  bstream&
451  operator<<(bstream& out, const Ship<T>& rhs);
452 
453  template <class T>
454  bstream&
455  operator>>(bstream& in, Ship<T>& rhs);
456 
457  }
458 
459 }
460 
461 #endif // vim:filetype=cpp
const vec3 & acceleration() const
Acceleration in Earth-fixed coordinate system.
Definition: core/ship.hh:266
T flooded_mass() const
Total mass of all fluid volumes inside compartments.
Definition: core/ship.cc:30
void angular_momentum(const vec3 &rhs)
Set angular momentum.
Definition: core/ship.hh:324
const vec3 & position(int i=0) const
Get position or its time derivatives in Earth-fixed coordinate system.
Definition: core/ship.hh:253
Rigid ship with a mass and translational and angular velocity.
Definition: core/ship.hh:186
T roll() const
Counterclockwise rotation about -axis in radians.
Definition: core/ship.hh:291
static constexpr const T water_density()
Sea water density.
Definition: constants.hh:27
vec3 euler_angles() const
Get Euler angles or their derivatives.
Definition: core/ship.hh:278
void position(int i, const vec3 &rhs)
Set position or its time derivatives in Earth-fixed coordinate system.
Definition: core/ship.hh:257
T pitch() const
Counterclockwise rotation about -axis in radians.
Definition: core/ship.hh:295
T sway(int i=0) const
coordinate of the position.
Definition: core/ship.hh:307
void velocity(const vec3 &rhs)
Set velocity in Earth-fixed coordinate system.
Definition: core/ship.hh:263
T sin(T... args)
const vec3 & angular_velocity() const
Angular velocity in Earth-fixed coordinate system.
Definition: core/ship.hh:314
const vec3 & angular_displacement(int i=0) const
Get angular position or its time derivatives in Earth-fixed coordinate system.
Definition: core/ship.hh:272
T surge(int i=0) const
coordinate of the position.
Definition: core/ship.hh:303
const vec3 & angular_momentum() const
Angular momentum.
Definition: core/ship.hh:322
T yaw() const
Counterclockwise rotation about -axis in radians.
Definition: core/ship.hh:299
const vec3 & velocity() const
Get velocity in Earth-fixed coordinate system.
Definition: core/ship.hh:260
const quaternion_type & quaternion() const
Get rotation quaternion.
Definition: core/ship.hh:281
const rotation_matrix_type & inertia_matrix() const
Inertia matrix in body-fixed coordinate system.
Definition: core/ship.hh:418
Mass attached to specified point in space.
Definition: mass.hh:15
T cos(T... args)
Main namespace.
Definition: convert.hh:9
const vec3 & angular_acceleration() const
Angular acceleration in Earth-fixed coordinate system.
Definition: core/ship.hh:319
state_vector_type state_vector() const
Get state vector for ship motion equation.
Definition: core/ship.cc:62
T heave(int i=0) const
coordinate of the position.
Definition: core/ship.hh:311