Corentin Chauvin-Hameau – 2019-2020
Coverage Path Planning for an underwater robot surveying a marine farm
cart_control_nodelet.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * \brief Definition of a nodelet for cheated cartesian control of a robot
5  * \author Corentin Chauvin-Hameau
6  * \date 2020
7  */
8 
10 #include <nav_msgs/Path.h>
11 #include <geometry_msgs/Pose.h>
12 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
13 #include <pluginlib/class_list_macros.h>
14 #include <ros/ros.h>
15 #include <iostream>
16 
17 using namespace std;
18 
19 PLUGINLIB_EXPORT_CLASS(mfcpp::CartControlNodelet, nodelet::Nodelet)
20 
21 
22 namespace mfcpp {
23 
24 /*
25  * Definition of static variables
26  */
27 sig_atomic_t volatile CartControlNodelet::b_sigint_ = 0;
28 ros::Timer CartControlNodelet::main_timer_ = ros::Timer();
29 
30 /*
31  * Definition of member functions
32  */
33 CartControlNodelet::CartControlNodelet() {}
34 CartControlNodelet::~CartControlNodelet() {}
35 
36 
37 void CartControlNodelet::onInit()
38 {
39  nh_ = getNodeHandle();
40  private_nh_ = getPrivateNodeHandle();
41 
42  // Catch SIGINT (Ctrl+C) stop signal
43  struct sigaction sigIntHandler;
44  sigIntHandler.sa_handler = CartControlNodelet::sigint_handler;
45  sigemptyset(&sigIntHandler.sa_mask);
46  sigIntHandler.sa_flags = 0;
47  sigaction(SIGINT, &sigIntHandler, NULL);
48 
49  // ROS parameters
50  private_nh_.param<float>("main_freq", main_freq_, 10.0);
51  private_nh_.param<float>("speed", robot_speed_, 1.0);
52 
53  // Other variables
54  path_received_ = false;
55  path_processed_ = false;
56  path_executed_ = true;
57 
58  // ROS subscribers
59  path_sub_ = nh_.subscribe<nav_msgs::PathConstPtr>("path", 1, &CartControlNodelet::path_cb, this);
60 
61  // ROS publishers
62  pose_pub_ = nh_.advertise<geometry_msgs::Pose>("pose_output", 0);
63 
64 
65  // Main loop
66  main_timer_ = private_nh_.createTimer(
67  ros::Duration(1/main_freq_), &CartControlNodelet::main_cb, this
68  );
69 }
70 
71 
72 void CartControlNodelet::main_cb(const ros::TimerEvent &timer_event)
73 {
74  if (!ros::ok() || ros::isShuttingDown() || b_sigint_)
75  return;
76 
77  if (path_received_) {
78  compute_waypoints(path_, robot_speed_, 1/main_freq_, waypoints_);
79  idx_waypoints_ = 0;
80  path_received_ = false;
81  }
82 
83  if (idx_waypoints_ < waypoints_.size()) {
84  pose_pub_.publish(waypoints_[idx_waypoints_]);
85  idx_waypoints_++;
86  }
87 }
88 
89 
90 void CartControlNodelet::sigint_handler(int s) {
91  b_sigint_ = 1;
92  main_timer_.stop();
93 
94  raise(SIGTERM);
95 }
96 
97 
98 void CartControlNodelet::path_cb(const nav_msgs::PathConstPtr msg)
99 {
100  path_ = *msg;
101  path_received_ = true;
102 }
103 
104 
105 void CartControlNodelet::compute_waypoints(const nav_msgs::Path &path, float speed, float dt,
106  vector<geometry_msgs::Pose> &waypoints) const
107 {
108  float resolution = speed * dt; // desired spatial resolution of the waypoints
109  int path_size = path.poses.size();
110  float s = 0; // current curvilinear abscissa
111  int idx_path = 0; // current index in the input path
112  int idx_wp = 0; // current index in the output waypoints
113  waypoints.resize(1);
114  waypoints[0] = path.poses[0].pose;
115 
116  while (idx_path < path_size) {
117 
118  // Find the next pose in the path
119  int prev_idx_path = idx_path;
120  float prev_s = s;
121 
122  while (idx_path < path_size && s-prev_s < resolution) {
123  idx_path++;
124 
125  tf2::Vector3 p1, p2;
126  tf2::convert(path.poses[idx_path-1].pose.position, p1);
127  tf2::convert(path.poses[idx_path].pose.position, p2);
128  s += tf2::tf2Distance(p1, p2);
129  }
130 
131  // Interpolate if the next pose is too far
132  if (idx_path < path_size) {
133  if (idx_path - prev_idx_path == 1) {
134  // Prepare interpolation
135  tf2::Vector3 p1, p2;
136  tf2::convert(waypoints[idx_wp].position, p1);
137  tf2::convert(path.poses[idx_path].pose.position, p2);
138 
139  tf2::Quaternion q1, q2;
140  tf2::convert(waypoints[idx_wp].orientation, q1);
141  tf2::convert(path.poses[idx_path].pose.orientation, q2);
142 
143  float d = tf2::tf2Distance(p1, p2);
144  int n = d/resolution;
145 
146  // Interpolate
147  for (int k = 1; k <= n; k++) {
148  geometry_msgs::Pose new_pose;
149  tf2::toMsg( p1 + (p2-p1) * (float(k)/n), new_pose.position);
150  tf2::convert((q1 + (q2-q1) * (float(k)/n)).normalize(), new_pose.orientation);
151 
152  waypoints.emplace_back(new_pose);
153  idx_wp++;
154  }
155  } else {
156  waypoints.emplace_back(path.poses[idx_path].pose);
157  }
158  }
159  }
160 }
161 
162 
163 
164 
165 } // namespace mfcpp
Definition: common.hpp:23
Declaration of a nodelet for cheated cartesian control of a robot.
Nodelet for cheated cartesian control of a robot.