Corentin Chauvin-Hameau – 2019-2020
Coverage Path Planning for an underwater robot surveying a marine farm
mpc_node.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * \brief Declaration of a node for Model Predictive Control of an underwater
5  * robot
6  * \author Corentin Chauvin-Hameau
7  * \date 2020
8  */
9 
10 #ifndef MPC_NODE_HPP
11 #define MPC_NODE_HPP
12 
14 #include "mf_common/Float32Array.h"
15 #include <nav_msgs/Path.h>
16 #include <geometry_msgs/TransformStamped.h>
17 #include <geometry_msgs/PoseArray.h>
18 #include <geometry_msgs/Pose.h>
19 #include <tf2_ros/transform_listener.h>
20 #include <ros/ros.h>
21 #include <eigen3/Eigen/Dense>
22 #include <string>
23 #include <vector>
24 
25 namespace mfcpp {
26 
27 /**
28  * \brief Node for Model Predictive Control of a robot
29  *
30  * `MatrixT` template can either be `Eigen::MatrixXf` or `Eigen::MatrixXd`.
31  * `VectorT` template can either be `Eigen::VectorXf` or `Eigen::VectorXd`.
32  */
33 class MPCNode {
34  public:
35  MPCNode();
36  ~MPCNode();
37 
38  /**
39  * \brief Runs the node
40  */
41  void run_node();
42 
43  private:
44  /**
45  * \brief MPC tuning parameters
46  */
48  {
49  Eigen::MatrixXf P; ///< Penalty on the last state error
50  Eigen::MatrixXf Q_x; ///< Penalty on the intermediary states errors
51  Eigen::MatrixXf R_u; ///< Penalty on the control input error
52  Eigen::MatrixXf R_delta; ///< Penalty on the control change rate
53  };
54 
55  /**
56  * \brief Bounds on the MPC problem
57  */
58  struct MPCBounds
59  {
60  double delta_m; // bound on delta_m
61  std::vector<double> input; // bounds on the control input
62  };
63 
64  // Private members
65  ros::NodeHandle nh_; ///< Node handler (for topics and services)
66  ros::Subscriber path_sub_; ///< Subscriber for the desired path
67  ros::Subscriber state_sub_; ///< Subscriber for the current robot state
68  ros::Publisher command_pub_; ///< Publisher for the computed command
69  ros::Publisher expected_traj_pub_; ///< Publisher for the expected controlled trajectory
70  tf2_ros::Buffer tf_buffer_; ///< Buffer for tf2
71  tf2_ros::TransformListener tf_listener_; ///< Transform listener for tf2
72 
73  nav_msgs::Path path_; ///< Path to follow
74  bool path_received_; ///< Whether a new path has been received
75  bool state_received_; ///< Whether the robot state has ever been received
76  RobotModel robot_model_; ///< Robot model
77  std::vector<float> state_; ///< Current robot state
78  std::vector<float> last_control_; ///< Last control applied to the robot
79  MPCTuningParameters tuning_params_; ///< MPC tuning parameters
80  MPCBounds bounds_; ///< Bounds for the MPC
81 
82  Eigen::VectorXf qp_last_primal_; ///< Last primal solution of the Quadratic Problem
83  Eigen::VectorXf qp_last_dual_; ///< Last dual solution of the Quadratic Problem
84  bool qp_warm_start_; ///< Whether the QP can start warm
85 
86  /// \name ROS parameters
87  ///@{
88  float main_freq_; ///< Frequency of the main loop
89  std::string fixed_frame_; ///< Fixed frame
90 
91  float desired_speed_; ///< Desired speed (m/s) of the robot
92  float last_desired_speed_; ///< Last desired speed (m/s) of the robot
93  float time_horizon_; ///< Time horizon (s) for the MPC prediction
94  int nbr_steps_; ///< Number of steps for the MPC prediction
95  bool disable_vbs_; ///< Whether to disable Variable Buoyancy System (VBS)
96  bool ltv_mpc_; ///< Whether to use the Linear Time Varying (LTV) version of MPC
97  ///@}
98 
99  /**
100  * \brief Initialises the node and its parameters
101  */
102  void init_node();
103 
104  /**
105  * \brief Generates a path of the right size for MPC prediction
106  *
107  * The path will have as many poses as steps for MPC, with a desired spatial
108  * resolution. The desired speed and size of the path are maintained, so if
109  * the desired spatial resolution leads to a too long path, the resolution
110  * is decreased to fit. If so, the time resolution is also shrinked (ie
111  * the path duration is smaller) and the desired speed is decreased.
112  *
113  * \param[in] orig_path Path provided by the path planner
114  * \param[in] current_position Current position of the robot
115  * \param[in] nbr_steps Number of MPC prediction steps
116  * \param[in,out] spatial_resolution Distance between two MPC steps
117  * \param[in,out] time_resolution Time between two MPC steps
118  * \param[in,out] desired_speed Desired speed
119  * \return Path of size nbr_steps+1
120  */
121  std::vector<geometry_msgs::Pose> adapt_path(
122  const std::vector<geometry_msgs::Pose> &orig_path,
123  const geometry_msgs::Point &current_position,
124  int nbr_steps,
125  float &spatial_resolution,
126  float &time_resolution,
127  float &desired_speed
128  );
129 
130  /**
131  * \brief Fills reference points for MPC optimisation
132  *
133  * \param[in] N Number of steps for the MPC prediction
134  * \param[in] n Dimension of the state vector
135  * \param[in] m Dimension of the control vector
136  * \param[in] path Reference path to follow (of size N+1)
137  * \param[in] desired_speed Desired speed (m/s) of the robot
138  * \param[in] last_desired_speed Last desired speed (m/s) of the robot
139  * \param[in] robot_model Robot model
140  * \param[out] X_ref Reference state to fill (x0_ref, ..., xN_ref)
141  * \param[out] U_ref Reference output to fill (u0_ref, ..., uN_ref)
142  * \return Whether the points could be filled
143  */
144  template <class VectorT>
145  bool fill_ref_pts(
146  int N, int n, int m,
147  const std::vector<geometry_msgs::Pose> &path,
148  float desired_speed,
149  float last_desired_speed,
150  const RobotModel &robot_model,
151  VectorT &X_ref,
152  VectorT &U_ref
153  );
154 
155  /**
156  * \brief Changes reference state orientation to prevent modulo discontinuity
157  *
158  * Adds multiple of 2pi to each orientation so that error in orientation is
159  * continuous over the reference points.
160  *
161  * \param[in,out] X_ref Reference state
162  * \param[in] x0 Current robot state
163  * \param[in] n Dimension of the state
164  */
165  template <class VectorT>
166  void modulo_ref_state(VectorT &X_ref, const VectorT &x0, int n);
167 
168  /**
169  * \brief Fills the G and H matrices used to express X with respect to U and X0
170  *
171  * Linear Time Varying MPC version.
172  *
173  * \param[in] X_ref State reference
174  * \param[in] U_ref Control reference
175  * \param[in] N Number of steps for the MPC prediction
176  * \param[in] dt Sampling time
177  * \param[in] ds Spatial resolution of reference path
178  * \param[out] G G matrix
179  * \param[out] H H matrix
180  * \param[out] D D vector
181  */
182  template <class VectorT, class MatrixT>
183  void fill_ltv_G_H_D(const VectorT &X_ref, const VectorT &U_ref,
184  int N, float dt, float ds,
185  MatrixT &G, MatrixT &H, VectorT &D);
186 
187  /**
188  * \brief Fills the G matrix used to express X with respect to U and X0
189  *
190  * Linear Time Invariant MPC version.
191  *
192  * \param[in] Ad Discretised model matrix
193  * \param[in] Bd Discretised model matrix
194  * \param[in] N Number of steps for the MPC prediction
195  * \param[out] G G matrix
196  */
197  template <class MatrixT>
198  void fill_lti_G(const MatrixT &Ad, const MatrixT &Bd, int N, MatrixT &G);
199 
200  /**
201  * \brief Fills the H matrix used to express X with respect to U and X0
202  *
203  * Linear Time Invariant MPC version
204  *
205  * \param[in] Ad Discretised model matrix
206  * \param[in] N Number of steps for the MPC prediction
207  * \param[out] H H matrix
208  */
209  template <class MatrixT>
210  void fill_lti_H(const MatrixT &Ad, int N, MatrixT &H);
211 
212  /**
213  * \brief Fills the L matrix used for quadratic cost wrt state error
214  *
215  * \param[in] P Penalty on the last state error
216  * \param[in] Q_x Penalty on the intermediary states errors
217  * \param[in] N Number of steps for the MPC prediction
218  * \param[out] L L matrix
219  */
220  template <class MatrixT>
221  void fill_L(const MatrixT &P, const MatrixT &Q_x, int N, MatrixT &L);
222 
223  /**
224  * \brief Fills the M matrix used for quadratic cost wrt control input error
225  *
226  * \param[in] R_u Penalty on the control input error
227  * \param[in] R_delta Penalty on the control change rate
228  * \param[in] N Number of steps for the MPC prediction
229  * \param[out] M M matrix
230  */
231  template <class MatrixT>
232  void fill_M(const MatrixT &R_u, const MatrixT &R_delta, int N, MatrixT &M);
233 
234  /**
235  * \brief Fills the V matrix used for the linear cost wrt control input error
236  *
237  * \param[in] control_ref Reference control
238  * \param[in] last_control Last control applied to the robot
239  * \param[in] R_delta Penalty on the control change rate
240  * \param[in] N Number of steps for the MPC prediction
241  * \param[out] V V matrix
242  */
243  template <class VectorT, class MatrixT>
244  void fill_V(VectorT control_ref, VectorT last_control,
245  const MatrixT &R_delta, int N, VectorT &V);
246 
247  /**
248  * \brief Fills the product of L and G matrices
249  *
250  * Optimisation in the Linear Time Invariant MPC case
251  *
252  * \param[in] G G matrix
253  * \param[in] P Penalty on the last state error
254  * \param[in] Q_x Penalty on the intermediary states errors
255  * \param[in] n Size of the state
256  * \param[in] m Size of the input
257  * \param[in] N Number of steps for the MPC prediction
258  * \param[out] LG LG matrix
259  */
260  template <class MatrixT>
261  void fill_lti_LG(const MatrixT &G, const MatrixT &P, const MatrixT &Q_x, int n,
262  int m, int N, MatrixT &LG);
263 
264  /**
265  * \brief Fills the different bounds objects
266  *
267  * \param[in] bounds Bounds of the MPC problem
268  * \param[in] n Size of the state
269  * \param[in] N Number of steps for the MPC prediction
270  * \param[in] X0 Initial offset
271  * \param[in] X_ref Reference state (x_0_ref, ..., x_N_ref)
272  * \param[in] U_ref Reference input (u_0_ref, ..., u_N_ref)
273  * \param[in] G Used to express X with respect to U and X0
274  * \param[in] H Used to express X with respect to U and X0
275  * \param[in] D Used to express X with respect to U and X0
276  * \param[out] lb Lower bound on Ab*U
277  * \param[out] ub Upper bound on Ab*U
278  * \param[out] Ab Multiplicative factor in front of U in the bound inequalities
279  */
280  template <class VectorT, class MatrixT>
281  void fill_bounds_objs(
282  const MPCBounds &bounds,
283  int n, int N,
284  const VectorT &X0, const VectorT &X_ref, const VectorT &U_ref,
285  const MatrixT &G, const MatrixT &H, const VectorT &D,
286  VectorT &lb, VectorT &ub, MatrixT &Ab
287  );
288 
289  /**
290  * \brief Solves a Quadratic Program
291  *
292  *
293  */
294  template <class VectorT, class T>
295  bool solve_qp(
296  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &P,
297  const VectorT &q,
298  const VectorT &lb,
299  const VectorT &ub,
300  const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &Ab,
301  VectorT &solution
302  );
303 
304  /**
305  * \brief Computes the control signal to send to the robot
306  *
307  * The desired speed might be changed if the robot is close to the end of
308  * the path.
309  *
310  * \param[in,out] desired_speed Desired speed (m/s) of the robot
311  * \param[in] last_desired_speed Last desired speed
312  * \param[out] command Computed control input to apply
313  * \param[out] expected_traj Expected controlled trajectory
314  *
315  * \return Whether the control could be computed
316  */
317  bool compute_control(
318  float &desired_speed,
319  float last_desired_speed,
320  std::vector<float> &command,
321  geometry_msgs::PoseArray &expected_traj
322  );
323 
324  /**
325  * \brief Callback for the desired path
326  */
327  void path_cb(const nav_msgs::Path msg);
328 
329  /**
330  * \brief Callback for the current robot state
331  */
332  void state_cb(const mf_common::Float32Array msg);
333 
334 };
335 
336 } // namespace mfcpp
337 
338 #endif
void fill_lti_G(const MatrixT &Ad, const MatrixT &Bd, int N, MatrixT &G)
Fills the G matrix used to express X with respect to U and X0.
Definition: mpc.cpp:254
Definition: common.hpp:23
Declaration of physical underwater robot model.
bool disable_vbs_
Whether to disable Variable Buoyancy System (VBS)
Definition: mpc_node.hpp:95
bool fill_ref_pts(int N, int n, int m, const std::vector< geometry_msgs::Pose > &path, float desired_speed, float last_desired_speed, const RobotModel &robot_model, VectorT &X_ref, VectorT &U_ref)
Fills reference points for MPC optimisation.
Definition: mpc.cpp:105
ros::Publisher expected_traj_pub_
Publisher for the expected controlled trajectory.
Definition: mpc_node.hpp:69
float time_horizon_
Time horizon (s) for the MPC prediction.
Definition: mpc_node.hpp:93
MPCBounds bounds_
Bounds for the MPC.
Definition: mpc_node.hpp:80
Node for Model Predictive Control of a robot.
Definition: mpc_node.hpp:33
Eigen::MatrixXf Q_x
Penalty on the intermediary states errors.
Definition: mpc_node.hpp:50
ros::Subscriber path_sub_
Subscriber for the desired path.
Definition: mpc_node.hpp:66
nav_msgs::Path path_
Path to follow.
Definition: mpc_node.hpp:73
std::vector< float > last_control_
Last control applied to the robot.
Definition: mpc_node.hpp:78
tf2_ros::Buffer tf_buffer_
Buffer for tf2.
Definition: mpc_node.hpp:70
MPC tuning parameters.
Definition: mpc_node.hpp:47
Eigen::MatrixXf R_delta
Penalty on the control change rate.
Definition: mpc_node.hpp:52
void fill_V(VectorT control_ref, VectorT last_control, const MatrixT &R_delta, int N, VectorT &V)
Fills the V matrix used for the linear cost wrt control input error.
Definition: mpc.cpp:326
Eigen::MatrixXf R_u
Penalty on the control input error.
Definition: mpc_node.hpp:51
float main_freq_
Frequency of the main loop.
Definition: mpc_node.hpp:88
bool compute_control(float &desired_speed, float last_desired_speed, std::vector< float > &command, geometry_msgs::PoseArray &expected_traj)
Computes the control signal to send to the robot.
Definition: mpc.cpp:531
void fill_L(const MatrixT &P, const MatrixT &Q_x, int N, MatrixT &L)
Fills the L matrix used for quadratic cost wrt state error.
Definition: mpc.cpp:287
ros::NodeHandle nh_
Node handler (for topics and services)
Definition: mpc_node.hpp:65
std::vector< float > state_
Current robot state.
Definition: mpc_node.hpp:77
Eigen::MatrixXf P
Penalty on the last state error.
Definition: mpc_node.hpp:49
bool qp_warm_start_
Whether the QP can start warm.
Definition: mpc_node.hpp:84
std::vector< double > input
Definition: mpc_node.hpp:61
void state_cb(const mf_common::Float32Array msg)
Callback for the current robot state.
Definition: mpc_node.cpp:145
RobotModel robot_model_
Robot model.
Definition: mpc_node.hpp:76
void path_cb(const nav_msgs::Path msg)
Callback for the desired path.
Definition: mpc_node.cpp:138
Bounds on the MPC problem.
Definition: mpc_node.hpp:58
void fill_ltv_G_H_D(const VectorT &X_ref, const VectorT &U_ref, int N, float dt, float ds, MatrixT &G, MatrixT &H, VectorT &D)
Fills the G and H matrices used to express X with respect to U and X0.
Definition: mpc.cpp:176
void fill_lti_LG(const MatrixT &G, const MatrixT &P, const MatrixT &Q_x, int n, int m, int N, MatrixT &LG)
Fills the product of L and G matrices.
Definition: mpc.cpp:336
void fill_lti_H(const MatrixT &Ad, int N, MatrixT &H)
Fills the H matrix used to express X with respect to U and X0.
Definition: mpc.cpp:273
Class defining the robot model.
Definition: robot_model.hpp:47
void fill_bounds_objs(const MPCBounds &bounds, int n, int N, const VectorT &X0, const VectorT &X_ref, const VectorT &U_ref, const MatrixT &G, const MatrixT &H, const VectorT &D, VectorT &lb, VectorT &ub, MatrixT &Ab)
Fills the different bounds objects.
Definition: mpc.cpp:355
float desired_speed_
Desired speed (m/s) of the robot.
Definition: mpc_node.hpp:91
void modulo_ref_state(VectorT &X_ref, const VectorT &x0, int n)
Changes reference state orientation to prevent modulo discontinuity.
Definition: mpc.cpp:148
void fill_M(const MatrixT &R_u, const MatrixT &R_delta, int N, MatrixT &M)
Fills the M matrix used for quadratic cost wrt control input error.
Definition: mpc.cpp:300
std::string fixed_frame_
Fixed frame.
Definition: mpc_node.hpp:89
int nbr_steps_
Number of steps for the MPC prediction.
Definition: mpc_node.hpp:94
ros::Publisher command_pub_
Publisher for the computed command.
Definition: mpc_node.hpp:68
MPCTuningParameters tuning_params_
MPC tuning parameters.
Definition: mpc_node.hpp:79
void init_node()
Initialises the node and its parameters.
Definition: mpc_node.cpp:42
ros::Subscriber state_sub_
Subscriber for the current robot state.
Definition: mpc_node.hpp:67
tf2_ros::TransformListener tf_listener_
Transform listener for tf2.
Definition: mpc_node.hpp:71
std::vector< geometry_msgs::Pose > adapt_path(const std::vector< geometry_msgs::Pose > &orig_path, const geometry_msgs::Point &current_position, int nbr_steps, float &spatial_resolution, float &time_resolution, float &desired_speed)
Generates a path of the right size for MPC prediction.
Definition: mpc.cpp:31
Eigen::VectorXf qp_last_dual_
Last dual solution of the Quadratic Problem.
Definition: mpc_node.hpp:83
void run_node()
Runs the node.
Definition: mpc_node.cpp:92
bool state_received_
Whether the robot state has ever been received.
Definition: mpc_node.hpp:75
bool path_received_
Whether a new path has been received.
Definition: mpc_node.hpp:74
bool solve_qp(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &P, const VectorT &q, const VectorT &lb, const VectorT &ub, const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &Ab, VectorT &solution)
Solves a Quadratic Program.
Definition: mpc.cpp:413
float last_desired_speed_
Last desired speed (m/s) of the robot.
Definition: mpc_node.hpp:92
Eigen::VectorXf qp_last_primal_
Last primal solution of the Quadratic Problem.
Definition: mpc_node.hpp:82