Corentin Chauvin-Hameau – 2019-2020
Coverage Path Planning for an underwater robot surveying a marine farm
robot_model.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * \brief Definition of physical underwater robot model
5  * \author Corentin Chauvin-Hameau
6  * \date 2019
7  */
8 
9 #include "robot_model.hpp"
10 #include <eigen3/unsupported/Eigen/MatrixFunctions>
11 #include <boost/numeric/odeint.hpp>
12 #include <eigen3/Eigen/Dense>
13 #include <cmath>
14 
15 #include <iostream>
16 
17 using Eigen::Vector3d;
18 using Eigen::Matrix3d;
19 using Eigen::VectorXd;
20 using Eigen::VectorXf;
21 using Eigen::MatrixXd;
22 using Eigen::MatrixXf;
23 
24 
25 using namespace std;
26 namespace pl = std::placeholders;
27 
28 
29 namespace mfcpp {
30 
31 
32 RobotModel::RobotModel()
33 {
34  g_ = 9.81;
35 }
36 
37 
38 RobotModel::RobotModel(const vector<double> &c)
39 {
40  c_ = c;
41  g_ = 9.81;
42 }
43 
44 
45 RobotModel::~RobotModel()
46 {
47 
48 }
49 
50 
51 void RobotModel::integrate(state_type &state, const input_type &input, double t1,
52  double t2, double init_step)
53 {
54  u_ = input;
55 
56  size_t steps = boost::numeric::odeint::integrate(
57  std::bind(&RobotModel::ode, this, pl::_1, pl::_2, pl::_3),
58  state, t1, t2, init_step
59  );
60 }
61 
62 
63 template <class MatrixT>
64 void RobotModel::get_lin_matrices(const state_type &x_0, const input_type &u_0,
65  MatrixT &A, MatrixT &B) const
66 {
67  const state_type &x = x_0; // for convenience
68  const input_type &u = u_0;
69  A = MatrixT::Zero(x.size(), x.size());
70  B = MatrixT::Zero(x.size(), u.size());
71 
72  double c3 = cos(x[3]); double s3 = sin(x[3]);
73  double c4 = cos(x[4]); double s4 = sin(x[4]); double t4 = tan(x[4]);
74  double c5 = cos(x[5]); double s5 = sin(x[5]);
75 
76  // A matrix
77  A(0, 3) = (s5*s3 + c5*s4*c3)*x[7] + (s5*c3 - c5*s3*s4)*x[8];
78  A(0, 4) = -c5*s4*x[6] + c5*c4*s3*x[7] + c5*c3*c4*x[8];
79  A(0, 5) = -s5*c4*x[6] - (c5*c3 + s5*s4*s3)*x[7] + (c5*s3 - s5*c3*s4)*x[8];
80  A(0, 6) = c5*c4;
81  A(0, 7) = -s5*c3 + c5*s4*s3;
82  A(0, 8) = s5*s3 + c5*c3*s4;
83 
84  A(1, 3) = (-c5*s3 + s5*s4*c3)*x[7] - (c5*c3 + s5*s3*s4)*x[8];
85  A(1, 4) = -s5*s4*x[6] + s5*c4*s3*x[7] + s5*c3*c4*x[8];
86  A(1, 5) = c5*c4*x[6] + (-s5*c3 + c5*s4*s3)*x[7] + (s5*s3 + c5*c3*s4)*x[8];
87  A(1, 6) = s5*c4;
88  A(1, 7) = c5*c3 + s5*s4*s3;
89  A(1, 8) = -c5*s3 + s5*s4*c3;
90 
91  A(2, 3) = c4*c3*x[7] - c4*s3*x[8];
92  A(2, 4) = -c4*x[6] - s4*s3*x[7] -s4*c3*x[8];
93  A(2, 6) = -s4;
94  A(2, 7) = c4*s3;
95  A(2, 8) = c4*c3;
96 
97  A(3, 3) = c3*t4*x[10] - s3*t4*x[11];
98  A(3, 4) = (s3*x[10] + c3*x[11]) * (1 + t4*t4);
99  A(3, 9) = 1;
100  A(3, 10) = s3*t4;
101  A(3, 11) = c3*t4;
102 
103  A(4, 3) = -s3*x[10] - c3*x[11];
104  A(4, 10) = c3;
105  A(4, 11) = -s3;
106 
107  A(5, 3) = (c3*x[10] - s3*x[11]) / c4;
108  A(5, 4) = s4 / (c4*c4) * (s3*x[10] + c3*x[11]);
109  A(5, 10) = s3/c4;
110  A(5, 11) = c3/c4;
111 
112  A(6, 4) = -g_*x[12]*c4;
113  A(6, 6) = c_[1] + 2*c_[2]*abs(x[6]);
114  A(6, 12) = -g_*s4;
115 
116  A(7, 3) = g_*x[12]*c4*c3;
117  A(7, 4) = -g_*x[12]*s4*s3;
118  A(7, 7) = c_[11];
119  A(7, 12) = g_*c4*s3;
120 
121  A(8, 3) = -g_*x[12]*c4*s3;
122  A(8, 4) = -g_*x[12]*s4*c3;
123  A(8, 8) = c_[11];
124  A(8, 12) = g_*c4*c3;
125 
126  A(9, 3) = -c_[14]*c4*c3;
127  A(9, 4) = c_[14]*s4*s3;
128  A(9, 9) = -c_[13];
129 
130  A(10, 4) = c_[6]*c4;
131  A(10, 6) = 2*c_[7]*x[6]*u[2];
132  A(10, 10) = c_[4] + 2*c_[5]*abs(x[10]);
133 
134  A(10, 6) = 2*c_[10]*x[6]*u[1];
135  A(11, 11) = c_[8] + 2*c_[9]*abs(x[11]);
136 
137  A(12, 12) = -1/c_[12];
138 
139  // B matrix
140  B(6, 0) = 2*c_[3]*abs(u[0]);
141  B(10, 2) = c_[7]*x[6]*x[6];
142  B(11, 1) = c_[10]*x[6]*x[6];
143  B(12, 3) = 1;
144 }
145 
146 
147 template <class MatrixT>
148 void RobotModel::get_lin_discr_matrices(const state_type &x_0, const input_type &u_0,
149  MatrixT &Ad, MatrixT &Bd, float dt) const
150 {
151  MatrixT A, B;
152  get_lin_matrices(x_0, u_0, A, B);
153 
154  int n = A.cols();
155  int m = B.cols();
156  MatrixT M = MatrixT::Zero(n + m, n + m);
157  M.block(0, 0, n, n) = dt*A;
158  M.block(0, n, n, m) = dt*B;
159  MatrixT E = M.exp();
160  Ad = E.block(0, 0, n, n);
161  Bd = E.block(0, n, n, m);
162 }
163 
164 
165 template <class VectorT, class MatrixT>
166 void RobotModel::get_lin_discr_matrices(const VectorT &x_0, const VectorT &u_0,
167  MatrixT &Ad, MatrixT &Bd, float dt) const
168 {
169  state_type _x_0(x_0.rows());
170  input_type _u_0(u_0.rows());
171 
172  for (int k = 0; k < _x_0.size(); k++) _x_0[k] = x_0(k);
173  for (int k = 0; k < _u_0.size(); k++) _u_0[k] = u_0(k);
174 
175  get_lin_discr_matrices(_x_0, _u_0, Ad, Bd, dt);
176 }
177 
178 
179 void RobotModel::ode(const state_type &x, state_type &dxdt, const double t)
180 {
181  Vector3d pos_dt = jac_pos(x[3], x[4], x[5]) * Vector3d(x[6], x[7], x[8]);
182  dxdt[0] = pos_dt[0];
183  dxdt[1] = pos_dt[1];
184  dxdt[2] = pos_dt[2];
185 
186  Vector3d orient_dt = jac_orient(x[3], x[4], x[5]) * Vector3d(x[9], x[10], x[11]);
187  dxdt[3] = orient_dt[0];
188  dxdt[4] = orient_dt[1];
189  dxdt[5] = orient_dt[2];
190 
191  double phi = x[3];
192  double theta = x[4];
193 
194  dxdt[6] = c_[1]*x[6] + c_[2]*abs(x[6])*x[6] + c_[3]*abs(u_[0])*u_[0] - x[12]*g_*sin(theta);
195  dxdt[7] = x[12]*g_*cos(theta)*sin(phi) + c_[11]*x[7];
196  dxdt[8] = x[12]*g_*cos(theta)*cos(phi) + c_[11]*x[8];
197  dxdt[9] = -c_[13]*x[9] - c_[14]*cos(theta)*sin(phi);
198  dxdt[10] = c_[4]*x[10] + c_[5]*abs(x[10])*x[10] + c_[6]*sin(theta) + c_[7]*x[6]*x[6]*u_[2];
199  dxdt[11] = c_[8]*x[11] + c_[9]*abs(x[11])*x[11] + c_[10]*x[6]*x[6]*u_[1];
200  dxdt[12] = -1/c_[12]*x[12] + u_[3];
201 }
202 
203 
204 void RobotModel::eval_ode(const state_type &x, const input_type &u, state_type &dxdt, const double t)
205 {
206  Vector3d pos_dt = jac_pos(x[3], x[4], x[5]) * Vector3d(x[6], x[7], x[8]);
207  dxdt[0] = pos_dt[0];
208  dxdt[1] = pos_dt[1];
209  dxdt[2] = pos_dt[2];
210 
211  Vector3d orient_dt = jac_orient(x[3], x[4], x[5]) * Vector3d(x[9], x[10], x[11]);
212  dxdt[3] = orient_dt[0];
213  dxdt[4] = orient_dt[1];
214  dxdt[5] = orient_dt[2];
215 
216  double phi = x[3];
217  double theta = x[4];
218 
219  dxdt[6] = c_[1]*x[6] + c_[2]*abs(x[6])*x[6] + c_[3]*abs(u[0])*u[0] - x[12]*g_*sin(theta);
220  dxdt[7] = x[12]*g_*cos(theta)*sin(phi) + c_[11]*x[7];
221  dxdt[8] = x[12]*g_*cos(theta)*cos(phi) + c_[11]*x[8];
222  dxdt[9] = -c_[13]*x[9] - c_[14]*cos(theta)*sin(phi);
223  dxdt[10] = c_[4]*x[10] + c_[5]*abs(x[10])*x[10] + c_[6]*sin(theta) + c_[7]*x[6]*x[6]*u[2];
224  dxdt[11] = c_[8]*x[11] + c_[9]*abs(x[11])*x[11] + c_[10]*x[6]*x[6]*u[1];
225  dxdt[12] = -1/c_[12]*x[12] + u[3];
226 }
227 
228 
229 Matrix3d RobotModel::jac_pos(double phi, double theta, double psi)
230 {
231  Matrix3d J;
232 
233  double c_ph = cos(phi);
234  double s_ph = sin(phi);
235  double c_th = cos(theta);
236  double s_th = sin(theta);
237  double c_ps = cos(psi);
238  double s_ps = sin(psi);
239 
240  J << c_ps*c_th, -s_ps*c_ph + c_ps*s_th*s_ph, s_ps*s_ph + c_ps*c_ph*s_th,
241  s_ps*c_th, c_ps*c_ph + s_ph*s_th*s_ps, -c_ps*s_ph + s_th*s_ps*c_ph,
242  -s_th, c_th*s_ph, c_th*c_ph;
243 
244  return J;
245 }
246 
247 
248 Matrix3d RobotModel::jac_orient(double phi, double theta, double psi)
249 {
250  Matrix3d J;
251 
252  double c_ph = cos(phi);
253  double s_ph = sin(phi);
254  double c_th = cos(theta);
255  double t_th = tan(theta);
256 
257  J << 1, s_ph*t_th, c_ph*t_th,
258  0, c_ph, -s_ph,
259  0, s_ph/c_th, c_ph/c_th;
260 
261  return J;
262 }
263 
264 
265 /*
266  * Instanciate templated functions
267  */
268 template void RobotModel::get_lin_matrices(const state_type &x_0, const input_type &u_0, MatrixXf &A, MatrixXf &B) const;
269 template void RobotModel::get_lin_matrices(const state_type &x_0, const input_type &u_0, MatrixXd &A, MatrixXd &B) const;
270 template void RobotModel::get_lin_discr_matrices(const state_type &x_0, const input_type &u_0, MatrixXf &Ad, MatrixXf &Bd, float dt) const;
271 template void RobotModel::get_lin_discr_matrices(const state_type &x_0, const input_type &u_0, MatrixXd &Ad, MatrixXd &Bd, float dt) const;
272 template void RobotModel::get_lin_discr_matrices(const VectorXf &x_0, const VectorXf &u_0, MatrixXf &Ad, MatrixXf &Bd, float dt) const;
273 template void RobotModel::get_lin_discr_matrices(const VectorXd &x_0, const VectorXd &u_0, MatrixXd &Ad, MatrixXd &Bd, float dt) const;
274 
275 
276 } // namespace mfcpp
Definition: common.hpp:23
Declaration of physical underwater robot model.
std::vector< double > state_type
Data type of the state.
Definition: robot_model.hpp:51
std::vector< double > input_type
Data type of the input.
Definition: robot_model.hpp:54