Corentin Chauvin-Hameau – 2019-2020
Coverage Path Planning for an underwater robot surveying a marine farm
output.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * \brief Definition of output functions
5  * \author Corentin Chauvin-Hameau
6  * \date 2019
7  */
8 
9 #include "camera_nodelet.hpp"
10 #include "mf_sensors_simulator/CameraOutput.h"
12 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
13 #include <geometry_msgs/Point.h>
14 #include <visualization_msgs/Marker.h>
15 #include <std_msgs/ColorRGBA.h>
16 #include <random>
17 #include <vector>
18 
19 using namespace std;
20 
21 
22 namespace mfcpp {
23 
24 void CameraNodelet::publish_rviz_fov()
25 {
26  MarkerArgs args;
27  args.stamp = ros::Time::now();
28  args.frame_id = camera_frame_;
29  args.ns = "FieldOfView";
30  args.duration = ros::Duration(1/camera_freq_);
31  args.color.r = fov_color_[0];
32  args.color.g = fov_color_[1];
33  args.color.b = fov_color_[2];
34  args.color.a = fov_color_[3];
35 
36  visualization_msgs::Marker marker = rviz_marker_triangles(args);
37  marker.points.reserve(18);
38  marker.colors.resize(6, args.color);
39 
40  // Form the limit points of the field of view
41  float a = fov_distance_ / sqrt(
42  pow(sensor_width_/2, 2) + pow(sensor_height_/2, 2) + pow(focal_length_, 2)
43  );
44  float m_x[4] = {-1, 1, 1, -1}; // multiplicators to form the points
45  float m_y[4] = {-1, -1, 1, 1};
46  tf2::Vector3 origin(0, 0, -focal_length_);
47  vector<tf2::Vector3> p(4);
48 
49  for (int k = 0; k < 4; k++) {
50  p[k] = tf2::Vector3(m_x[k] * a * sensor_width_ / 2,
51  m_y[k] * a * sensor_height_ / 2,
52  a * focal_length_);
53  }
54 
55  // Create the corresponding triangles
56  geometry_msgs::Point point;
57  marker.points.emplace_back(tf2::toMsg(origin, point));
58  marker.points.emplace_back(tf2::toMsg(p[0], point));
59  marker.points.emplace_back(tf2::toMsg(p[1], point));
60 
61  marker.points.emplace_back(tf2::toMsg(origin, point));
62  marker.points.emplace_back(tf2::toMsg(p[1], point));
63  marker.points.emplace_back(tf2::toMsg(p[2], point));
64 
65  marker.points.emplace_back(tf2::toMsg(origin, point));
66  marker.points.emplace_back(tf2::toMsg(p[2], point));
67  marker.points.emplace_back(tf2::toMsg(p[3], point));
68 
69  marker.points.emplace_back(tf2::toMsg(origin, point));
70  marker.points.emplace_back(tf2::toMsg(p[3], point));
71  marker.points.emplace_back(tf2::toMsg(p[0], point));
72 
73  marker.points.emplace_back(tf2::toMsg(p[0], point));
74  marker.points.emplace_back(tf2::toMsg(p[1], point));
75  marker.points.emplace_back(tf2::toMsg(p[2], point));
76  marker.points.emplace_back(tf2::toMsg(p[0], point));
77  marker.points.emplace_back(tf2::toMsg(p[2], point));
78  marker.points.emplace_back(tf2::toMsg(p[3], point));
79 
80  // Publish the marker
81  rviz_pub_.publish(marker);
82 }
83 
84 
85 void CameraNodelet::prepare_out_msgs(
86  mf_sensors_simulator::CameraOutput &out_msg,
87  visualization_msgs::Marker &ray_marker,
88  visualization_msgs::Marker &pts_marker)
89 {
90  // Prepare output message
91  out_msg.header.stamp = ros::Time::now();
92  out_msg.header.frame_id = camera_frame_;
93 
94  int nbr_pts = n_pxl_height_*n_pxl_width_;
95  out_msg.x.reserve(nbr_pts);
96  out_msg.y.reserve(nbr_pts);
97  out_msg.z.reserve(nbr_pts);
98  out_msg.value.reserve(nbr_pts);
99 
100  // Prepare Rviz marker for displaying rays
101  ray_marker.header.stamp = ros::Time::now();
102  ray_marker.header.frame_id = camera_frame_;
103  ray_marker.ns = "Rays";
104  ray_marker.lifetime = ros::Duration(1/camera_freq_);
105  ray_marker.color.r = 1.0;
106  ray_marker.color.g = 0.0;
107  ray_marker.color.b = 0.0;
108  ray_marker.color.a = 1.0;
109  ray_marker.type = visualization_msgs::Marker::LINE_LIST;
110  ray_marker.action = visualization_msgs::Marker::ADD;
111  ray_marker.scale.x = 0.01;
112  ray_marker.points.reserve(nbr_pts);
113 
114  // Prepare Rviz marker for displaying hit points
115  pts_marker.header.stamp = ros::Time::now();
116  pts_marker.header.frame_id = fixed_frame_;
117  pts_marker.ns = "Hit point";
118  pts_marker.lifetime = ros::Duration(1/camera_freq_);
119  pts_marker.color.r = 0.0;
120  pts_marker.color.g = 0.0;
121  pts_marker.color.b = 1.0;
122  pts_marker.color.a = 1.0;
123  pts_marker.type = visualization_msgs::Marker::POINTS;
124  pts_marker.action = visualization_msgs::Marker::ADD;
125  pts_marker.scale.x = 0.02;
126  pts_marker.scale.y = 0.02;
127  pts_marker.points.reserve(nbr_pts);
128  pts_marker.colors.reserve(nbr_pts);
129 }
130 
131 
132 void CameraNodelet::add_pt_to_marker(visualization_msgs::Marker &marker,
133  const tf2::Vector3 &pt, float color_r, float color_g, float color_b)
134 {
135  geometry_msgs::Point p;
136  p.x = pt.getX();
137  p.y = pt.getY();
138  p.z = pt.getZ();
139  marker.points.emplace_back(p);
140 
141  std_msgs::ColorRGBA color;
142  color.r = color_r;
143  color.g = color_g;
144  color.b = color_b;
145  color.a = 1.0;
146  marker.colors.emplace_back(color);
147 }
148 
149 
150 void CameraNodelet::add_line_to_marker(visualization_msgs::Marker &marker,
151  const tf2::Vector3 &pt1, const tf2::Vector3 &pt2)
152 {
153  geometry_msgs::Point p;
154  p.x = pt1.getX();
155  p.y = pt1.getY();
156  p.z = pt1.getZ();
157  marker.points.emplace_back(p);
158  p.x = pt2.getX();
159  p.y = pt2.getY();
160  p.z = pt2.getZ();
161  marker.points.emplace_back(p);
162 }
163 
164 
165 void CameraNodelet::publish_output()
166 {
167  // Prepare output message
168  mf_sensors_simulator::CameraOutput out_msg;
169  visualization_msgs::Marker ray_marker;
170  visualization_msgs::Marker pts_marker;
171 
172  prepare_out_msgs(out_msg, ray_marker, pts_marker);
173 
174  // Selects algae that are in field of view of the camera
175  coll_mutex_.lock();
176  update_fov_pose();
177  overlap_fov(fov_body_);
178 
179  // Get their position and dimension, and compute their axes
180  int n = ray_bodies_.size();
181  vector<float> w_algae(n); // width of algae
182  vector<float> h_algae(n); // height of algae
183  vector<float> inc_y3(n); // increment along y3 axis of algae
184  vector<float> inc_z3(n); // increment along z3 axis of algae
185  vector<geometry_msgs::TransformStamped> tf_algae(n); // transforms of local frames
186 
187  get_ray_algae_carac(w_algae, h_algae, inc_y3, inc_z3, tf_algae);
188 
189  int n_heat_height = heatmaps_[0].size(); // height of the heatmap
190  int n_heat_width = heatmaps_[0][0].size(); // width of the heatmap
191 
192  // Initialise randomisation of heatmap values
193  std::random_device seed_initialiser;
194  std::mt19937 random_generator(seed_initialiser());
195 
196  // For each pixel
197  for (unsigned int i = 0; i < n_pxl_height_; i++) {
198  for (unsigned int j = 0; j < n_pxl_width_; j++) {
199  // Perform ray casting
200  tf2::Vector3 aim_pt = get_aim_pt(i, j);
201 
202  int alga_idx;
203  tf2::Vector3 hit_pt;
204  bool alga_hit = raycast_alga(aim_pt, hit_pt, alga_idx, fixed_camera_tf_);
205 
206  if (alga_hit) {
207  // Transform hit point in alga frame
208  geometry_msgs::Pose hit_pose, tf_pose;
209  hit_pose.position.x = hit_pt.getX();
210  hit_pose.position.y = hit_pt.getY();
211  hit_pose.position.z = hit_pt.getZ();
212  tf2::doTransform(hit_pose, tf_pose, tf_algae[alga_idx]);
213  float z = tf_pose.position.z + h_algae[alga_idx]/2;
214  float y = tf_pose.position.y + w_algae[alga_idx]/2;
215 
216  // Get alga disease value
217  int k = z / inc_z3[alga_idx];
218  int l = y / inc_y3[alga_idx];
219  k = min(k, n_heat_height-1); // prevent problems with the last element
220  l = min(l, n_heat_width-1);
221 
222  float value = heatmaps_[corr_algae_[alga_idx]][k][l];
223 
224  // Transform hit point in camera frame
225  geometry_msgs::Pose out_pose;
226  tf2::doTransform(hit_pose, out_pose, camera_fixed_tf_);
227 
228  // Noise disease value
229  if (noise_meas_) {
230  geometry_msgs::Point p = out_pose.position;
231  float distance = sqrt(pow(p.x, 2) + pow(p.y, 2) + pow(p.z, 2));
232  float sigma = noise_std_ * (1 - exp(-distance/noise_decay_));
233  std::normal_distribution<float> distribution(0, sigma);
234 
235  float noise = distribution(random_generator);
236  value += noise;
237 
238  if (value > 1.0)
239  value = 1.0;
240  else if (value < 0.0)
241  value = 0.0;
242  }
243 
244  // Fill output message
245  out_msg.x.emplace_back(out_pose.position.x);
246  out_msg.y.emplace_back(out_pose.position.y);
247  out_msg.z.emplace_back(out_pose.position.z);
248  out_msg.value.emplace_back(value);
249 
250  // Fill point marker
251  add_pt_to_marker(pts_marker, hit_pt, value, value, value);
252  }
253 
254  // Fill ray marker
255  add_line_to_marker(ray_marker, tf2::Vector3(0, 0, 0), aim_pt);
256  }
257  }
258 
259  coll_mutex_.unlock();
260 
261  // Publish markers
262  out_pub_.publish(out_msg);
263  rviz_pub_.publish(pts_marker);
264  rviz_pub_.publish(ray_marker);
265 }
266 
267 
268 } // namespace mfcpp
Definition: common.hpp:23
Declaration of common structures and functions for farm simulator.
Arguments used to create a Rviz maker.
ros::Time stamp
Time stamp for the ROS message.
std::string frame_id
Frame in which position/orientation of the object is.
float distance(const geometry_msgs::Point &p1, const geometry_msgs::Point &p2)
Computes the the euclidean distance between two positions.
Definition: common.hpp:69
visualization_msgs::Marker rviz_marker_triangles(const MarkerArgs &common_args)
Creates a blank Rviz marker to display triangles.
ros::Duration duration
Duration of the marker (in sec)
std::string ns
Namespace for the Rviz marker.
std_msgs::ColorRGBA color
Color of the marker.
Declaration of a nodelet simulating a camera.