Corentin Chauvin-Hameau – 2019-2020
Coverage Path Planning for an underwater robot surveying a marine farm
robot_model.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * \brief Declaration of physical underwater robot model
5  * \author Corentin Chauvin-Hameau
6  * \date 2019
7  */
8 
9 #ifndef ROBOT_MODEL_HPP
10 #define ROBOT_MODEL_HPP
11 
12 #include "mf_common/common.hpp"
13 #include <geometry_msgs/Pose.h>
14 #include <tf2_ros/transform_broadcaster.h>
15 #include <eigen3/Eigen/Dense>
16 #include <vector>
17 #include <cmath>
18 
19 
20 namespace mfcpp {
21 
22 
23 /**
24  * \brief Class defining the robot model
25  *
26  * The state is as follow:
27  * - \f$ x_0 = x \f$
28  * - \f$ x_1 = y \f$
29  * - \f$ x_2 = z \f$
30  * - \f$ x_3 = \Phi \f$
31  * - \f$ x_4 = \theta \f$
32  * - \f$ x_5 = \psi \f$
33  * - \f$ x_6 = u \f$
34  * - \f$ x_7 = v \f$
35  * - \f$ x_8 = w \f$
36  * - \f$ x_9 = p \f$
37  * - \f$ x_{10} = q \f$
38  * - \f$ x_{11} = r \f$
39  * - \f$ x_{12} = \Delta m \f$
40  *
41  * The inputs are as follow:
42  * - \f$ u_0 = n \f$
43  * - \f$ u_1 = \delta_r \f$
44  * - \f$ u_2 = \delta_e \f$
45  * - \f$ u_3 = P \f$
46  */
48 {
49  public:
50  /// Data type of the state
51  typedef std::vector<double> state_type;
52 
53  /// Data type of the input
54  typedef std::vector<double> input_type;
55 
56  RobotModel();
57  RobotModel(const std::vector<double> &c);
58  ~RobotModel();
59 
60 
61  /**
62  * \brief Evaluate the ODE
63  *
64  * Public version of the ODE
65  *
66  * \param x Current state
67  * \param u Current input
68  * \param dxdt Current time derivative of the state
69  * \param t Current time
70  */
71  void eval_ode(const state_type &x, const input_type &u, state_type &dxdt, const double t);
72 
73  /**
74  * \brief Integrates the model over a period of time
75  *
76  * It will update the state by integrating the dynamic model of the robot.
77  * It assumes that the inputs are constant during the integration.
78  *
79  * It is based on the error-controlled `runge_kutta54_cash_karp` stepper
80  * (5th order) and uses adaptive step-size.
81  *
82  * \param[in,out] state Initial state to update
83  * \param[in] input Input to the actuators
84  * \param[in] t1 Starting time of the integration
85  * \param[in] t2 Ending time of the integration
86  * \param[in] init_step Initial step size for the integration
87  */
88  void integrate(state_type &state, const input_type &input, double t1,
89  double t2, double init_step);
90 
91  /**
92  * \brief Gets the matrices of the linearised system
93  *
94  * If the system is linearised around \f$ (x_0, u_0) \f$, the system can be
95  * expressed for new variables \f$ (\Delta x, \Delta u) = (x-x_0, u-u_0) \f$.
96  * The ODE then becomes: \f$ \dot{\Delta x} = A \Delta x + B \Delta u \f$.
97  *
98  * `MatrixT` can either be `Eigen::MatrixXd` or `Eigen::MatrixXf`
99  *
100  * \param[in] x_0 Nominal state
101  * \param[in] u_0 Nominal input
102  * \param[out] A A matrix
103  * \param[out] B B matrix
104  */
105  template <class MatrixT>
106  void get_lin_matrices(const state_type &x_0, const input_type &u_0,
107  MatrixT &A, MatrixT &B) const;
108 
109  /**
110  * \brief Gets the matrices of the discretised linearised system
111  *
112  * The system \f$ \dot{\Delta x} = A \Delta x + B \Delta u \f$ is discretised
113  * by \f$ A_d = e^{dt.A} \f$ and \f$ B_d = (\int_{0}^{dt} e^{s.A} ds) B \f$.
114  *
115  * \todo Update how to get B_d
116  *
117  * `MatrixT` can either be `Eigen::MatrixXd` or `Eigen::MatrixXf`
118  *
119  * \param[in] x_0 Nominal state
120  * \param[in] u_0 Nominal input
121  * \param[out] Ad Discretised A matrix
122  * \param[out] Bd Discretised B matrix
123  * \param[in] dt Discretisation interval
124  */
125  template <class MatrixT>
126  void get_lin_discr_matrices(const state_type &x_0, const input_type &u_0,
127  MatrixT &Ad, MatrixT &Bd, float dt) const;
128 
129  /**
130  * \brief Overloads get_lin_discr_matrices for Eigen vectors
131  *
132  * `VectorT` can either be `Eigen::VectorXd` or `Eigen::VectorXf`
133  * `MatrixT` can either be `Eigen::MatrixXd` or `Eigen::MatrixXf`
134  */
135  template <class VectorT, class MatrixT>
136  void get_lin_discr_matrices(const VectorT &x_0, const VectorT &u_0,
137  MatrixT &Ad, MatrixT &Bd, float dt) const;
138 
139  /**
140  * \brief Computes the propeller speed in steady state
141  *
142  * \note This assumes that delta_m = 0
143  * \param speed Desired steady state speed
144  */
145  double inline steady_propeller_speed(double speed) const;
146 
147  /**
148  * \brief Computes the horizontal speed in steady state
149  *
150  * \note This assumes that the propeller speed is constant and the robot is
151  * horizontal
152  * \param n Rotational speed of the propeller
153  */
154  double inline steady_speed(double n) const;
155 
156  /**
157  * \brief Computes the lateral turning radius
158  *
159  * \param u Speed of the robot
160  * \param delta_r Angle of the lateral rudder
161  */
162  double inline lat_turn_radius(double u, double delta_r) const;
163 
164  /**
165  * \brief Computes the elevation turning radius
166  *
167  * \param u Speed of the robot
168  * \param delta_e Angle of the elevation rudder
169  */
170  double inline elev_turn_radius(double u, double delta_e) const;
171 
172  private:
173  /// \brief Model constants
174  /// \warning c[0] is not used to respect notation
175  std::vector<double> c_;
176 
177  /// Gravity acceleration
178  double g_;
179 
180  /// Model inputs
181  input_type u_;
182 
183  /**
184  * \brief ODE used to integrate the model
185  *
186  * \param x Current state
187  * \param dxdt Current time derivative of the state
188  * \param t Current time
189  */
190  void ode(const state_type &x, state_type &dxdt, const double t);
191 
192  /**
193  * \brief Computes the Jacobian of the position
194  *
195  * Transforms linear velocities in the global frame to the intertial
196  * frame.
197  *
198  * \param phi First angle of the robot's orientation
199  * \param theta Second angle of the robot's orientation
200  * \param psi Third angle of the robot's orientation
201  * \return Jacobian of the position
202  */
203  Eigen::Matrix3d jac_pos(double phi, double theta, double psi);
204 
205  /**
206  * \brief Computes the Jacobian of the orientation
207  *
208  * Transforms angular velocities in the global frame to the inertial frame.
209  *
210  * \param phi First angle of the robot's orientation
211  * \param theta Second angle of the robot's orientation
212  * \param psi Third angle of the robot's orientation
213  * \return Jacobian of the orientation
214  */
215  Eigen::Matrix3d jac_orient(double phi, double theta, double psi);
216 
217  /**
218  * \brief Returns the sign of a real number
219  *
220  * \return 1 if x>=0, -1 otherwise
221  */
222  inline double sign(double x) const;
223 
224 };
225 
226 
227 double inline RobotModel::steady_propeller_speed(double speed) const
228 {
229  double a = 1/c_[3] * (-c_[1]*speed - c_[2]*speed*speed);
230  return sign(speed) * sqrt(abs(a));
231 }
232 
233 
234 inline double RobotModel::steady_speed(double propeller_speed) const
235 {
236  double delta = pow(c_[1], 2) - 4*c_[2]*c_[3]*pow(propeller_speed, 2);
237  return -(c_[1] + sqrt(delta)) / (2*c_[2]);
238 }
239 
240 
241 double inline RobotModel::lat_turn_radius(double u, double delta_r) const
242 {
243  double K = -4 * c_[9] * c_[10] * delta_r;
244  double r = (-c_[8] - sqrt(pow(c_[8], 2) + K*pow(u, 2))) / (2*c_[9]);
245  double R_squared = -c_[10]*delta_r / (c_[8]/r + c_[9]);
246 
247  return sqrt(R_squared);
248 }
249 
250 
251 double inline RobotModel::elev_turn_radius(double u, double delta_e) const
252 {
253  double K = -4 * c_[5] * c_[7] * delta_e;
254  double r = (-c_[4] - sqrt(pow(c_[4], 2) + K*pow(u, 2))) / (2*c_[5]);
255  double R_squared = -c_[7]*delta_e / (c_[4]/r + c_[5]);
256 
257  return sqrt(R_squared);
258 }
259 
260 
261 inline double RobotModel::sign(double x) const
262 {
263  return (double) (x >= 0);
264 }
265 
266 /**
267  * \brief Converts a pose into a state message
268  *
269  * The first 6 components will be filled with the pose (x, y, z, roll, pitch,
270  * yaw). The other components of the state will be filled with zeros.
271  *
272  * \param[in] pose Pose to convert
273  * \param[in] state_size Size of the state
274  * \return Converted state
275  */
277  const geometry_msgs::Pose &pose,
278  int state_size)
279 {
280  RobotModel::state_type state(state_size, 0);
281 
282  state[0] = pose.position.x;
283  state[1] = pose.position.y;
284  state[2] = pose.position.z;
285  to_euler(pose.orientation, state[3], state[4], state[5]);
286 
287  return state;
288 }
289 
290 
291 } // namespace mfcpp
292 
293 
294 #endif
Eigen::Matrix3d jac_pos(double phi, double theta, double psi)
Computes the Jacobian of the position.
Definition: common.hpp:23
input_type u_
Model inputs.
void get_lin_discr_matrices(const state_type &x_0, const input_type &u_0, MatrixT &Ad, MatrixT &Bd, float dt) const
Gets the matrices of the discretised linearised system.
Eigen::Matrix3d jac_orient(double phi, double theta, double psi)
Computes the Jacobian of the orientation.
void ode(const state_type &x, state_type &dxdt, const double t)
ODE used to integrate the model.
double sign(double x) const
Returns the sign of a real number.
double elev_turn_radius(double u, double delta_e) const
Computes the elevation turning radius.
std::vector< double > state_type
Data type of the state.
Definition: robot_model.hpp:51
Declaration of common functions.
double g_
Gravity acceleration.
void integrate(state_type &state, const input_type &input, double t1, double t2, double init_step)
Integrates the model over a period of time.
Definition: robot_model.cpp:51
double steady_speed(double n) const
Computes the horizontal speed in steady state.
void eval_ode(const state_type &x, const input_type &u, state_type &dxdt, const double t)
Evaluate the ODE.
double lat_turn_radius(double u, double delta_r) const
Computes the lateral turning radius.
Class defining the robot model.
Definition: robot_model.hpp:47
std::vector< double > input_type
Data type of the input.
Definition: robot_model.hpp:54
double steady_propeller_speed(double speed) const
Computes the propeller speed in steady state.
RobotModel::state_type to_state(const geometry_msgs::Pose &pose, int state_size)
Converts a pose into a state message.
std::vector< double > c_
Model constants.
void to_euler(const tf2::Quaternion &quat, double &roll, double &pitch, double &yaw)
Converts a quaternion to Roll-Pitch-Yaw Euler angles.
Definition: common.hpp:180
void get_lin_matrices(const state_type &x_0, const input_type &u_0, MatrixT &A, MatrixT &B) const
Gets the matrices of the linearised system.
Definition: robot_model.cpp:64