path_planning.cpp
Go to the documentation of this file.
1 #include <string>
2 #include <strings.h>
3 
5 #include <ram_msgs/AdditiveManufacturingTrajectory.h>
10 #include <ros/ros.h>
11 #include <visualization_msgs/Marker.h>
12 
15 #include <ram_path_planning/ContoursAction.h>
16 #include <ram_path_planning/DonghongDingAction.h>
17 #include <ram_path_planning/FollowPosesAction.h>
18 
19 #include <unique_id/unique_id.h>
20 
21 typedef vtkSmartPointer<vtkPolyData> Polygon;
22 typedef std::vector<Polygon> PolygonVector;
23 typedef std::vector<PolygonVector> Layer;
24 
25 bool use_gui;
26 
27 std::unique_ptr<ros::Publisher> traj_pub;
28 
32 
33 //allow to visualize the generation of trajectory
34 vtkSmartPointer<vtkRendererUpdaterTimer> cb = vtkSmartPointer<vtkRendererUpdaterTimer>::New();
35 
36 std::string fileExtension(const std::string full_path)
37 {
38  size_t last_index = full_path.find_last_of("/");
39  std::string file_name = full_path.substr(last_index + 1, full_path.size());
40 
41  last_index = file_name.find_last_of("\\");
42  file_name = file_name.substr(last_index + 1, file_name.size());
43 
44  last_index = file_name.find_last_of(".");
45  if (last_index == std::string::npos)
46  return "";
47 
48  return file_name.substr(last_index + 1, file_name.size());
49 }
50 
51 // Donghong Ding algorithm
53 {
54 
55  // Change status to ACTIVE
56  gh.setAccepted();
57 
58  // Action elements
59  ram_path_planning::DonghongDingGoal goal;
60  ram_path_planning::DonghongDingResult result;
61  goal = *gh.getGoal();
62 
63  // Verify parameters
64  if (goal.file.empty())
65  {
66  result.error_msg = "File name cannot be empty";
67  ROS_ERROR_STREAM(result.error_msg);
68  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
69  gh.setAborted(result);
70  return;
71  }
72 
73  if (goal.height_between_layers <= 0)
74  {
75  result.error_msg = "Height between layers cannot be <= 0";
76  ROS_ERROR_STREAM(result.error_msg);
77  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
78  gh.setAborted(result);
79  return;
80  }
81 
82  if (goal.deposited_material_width <= 0)
83  {
84  result.error_msg = "Deposited material width cannot be <= 0";
85  ROS_ERROR_STREAM(result.error_msg);
86  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
87  gh.setAborted(result);
88  return;
89  }
90  if (goal.contours_filtering_tolerance < 0)
91  {
92  result.error_msg = "Contours filtering tolerance cannot be < 0";
93  ROS_ERROR_STREAM(result.error_msg);
94  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
95  gh.setAborted(result);
96  return;
97  }
98 
99  // Verify file extension
100  bool is_yaml_file(false);
101  const std::string file_extension(fileExtension(goal.file));
102  if (!strcasecmp(file_extension.c_str(), "yaml") || !strcasecmp(file_extension.c_str(), "yml"))
103  {
104  is_yaml_file = true;
105  if (goal.number_of_layers < 1)
106  {
107  result.error_msg = "Number of layers cannot be < 1";
108  ROS_ERROR_STREAM(result.error_msg);
109  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
110  gh.setAborted(result);
111  return;
112  }
113  }
114  else if (strcasecmp(file_extension.c_str(), "obj") && strcasecmp(file_extension.c_str(), "ply")
115  && strcasecmp(file_extension.c_str(), "stl"))
116  {
117  result.error_msg = "File is not a YAML, YML, OBJ, PLY or STL file: " + goal.file;
118  ROS_ERROR_STREAM(result.error_msg);
119  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
120  gh.setAborted(result);
121  return;
122  }
123 
124  // Create Trajectory message
125  ram_msgs::AdditiveManufacturingTrajectory msg;
126  msg.file = goal.file;
127 
128  // Add request parameter to the trajectory
129  msg.generation_info = "Deposited material width = " + std::to_string(goal.deposited_material_width * 1000.0)
130  + " mm\n";
131  msg.generation_info += "Contours filtering tolerance = " + std::to_string(goal.contours_filtering_tolerance * 1000.0)
132  + " mm\n";
133  msg.generation_info += "Height between layers = " + std::to_string(goal.height_between_layers * 1000.0) + " mm\n";
134 
135  if (!is_yaml_file)
136  {
137  msg.generation_info += "Slicing direction = " + std::to_string(goal.slicing_direction.x) + ", "
138  + std::to_string(goal.slicing_direction.y) + ", " + std::to_string(goal.slicing_direction.z);
139  }
140  else
141  {
142  msg.generation_info += "Number of layers = " + std::to_string(goal.number_of_layers);
143  }
144 
145  msg.similar_layers = is_yaml_file;
146 
147  std::array<double, 3> slicing_direction;
148  slicing_direction[0] = goal.slicing_direction.x;
149  slicing_direction[1] = goal.slicing_direction.y;
150  slicing_direction[2] = goal.slicing_direction.z;
151 
152  std::vector<Layer> additive_traj;
153  cb->current_layer_.clear();
154 
155  // Generate trajectory
156 
157  // Action feedback
158  if (!donghongding_generator.publishStatusPercentageDone("Generating trajectory", 10, gh))
159  return;
160 
161  if (is_yaml_file)
162  {
163  std::string error_message;
164  error_message = donghongding_generator.generateOneLayerTrajectory(gh, 10, 50, goal.file, cb->current_layer_,
165  goal.deposited_material_width,
166  goal.contours_filtering_tolerance, M_PI / 6,
167  false,
168  use_gui);
169 
170  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
171  return;
172 
173  if (error_message.empty())
174  {
175  // Action feedback
176  if (!donghongding_generator.publishStatusPercentageDone(
177  "Trajectory has been generated for one layer.\n Duplicating and connecting layers", 50, gh))
178  return;
179 
180  donghongding_generator.connectYamlLayers(gh, 50, 90, cb->current_layer_, msg, goal.number_of_layers,
181  goal.height_between_layers);
182 
183  }
184  else
185  {
186  result.error_msg = error_message;
187  ROS_ERROR_STREAM(result.error_msg);
188  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
189  gh.setAborted(result);
190  return;
191  }
192  }
193  else
194  {
195  // Slice the mesh
196  const unsigned nb_layers(
197  ram_path_planning::sliceMesh(additive_traj, goal.file, cb->mesh_, cb->stripper_, goal.height_between_layers,
198  slicing_direction,
199  use_gui));
200 
201  if (nb_layers < 1)
202  {
203  result.error_msg = "Slicing failed, zero slice generated";
204  ROS_ERROR_STREAM(result.error_msg);
205  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
206  gh.setAborted(result);
207  return;
208  }
209  // Action feedback
210  if (!donghongding_generator.publishStatusPercentageDone("Slicing completed", 20, gh))
211  return;
212 
213  // Generate trajectory on each layer
214  for (unsigned i(0); i < additive_traj.size(); ++i)
215  {
216  Polygon contours(additive_traj[i][0][0]);
217  contours->DeepCopy(additive_traj[i][0][0]);
218 
219  int current_progress_value = 20 + i * 30 / nb_layers; // first value is 20%
220  int next_progress_value = 20 + (i + 1) * 30 / nb_layers; // last value is 50%
221 
222  std::string error_message;
223  error_message = donghongding_generator.generateOneLayerTrajectory(gh, current_progress_value, next_progress_value,
224  contours,
225  cb->current_layer_,
226  goal.deposited_material_width,
227  goal.contours_filtering_tolerance,
228  slicing_direction,
229  M_PI / 6,
230  false,
231  use_gui);
232 
233  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
234  return;
235 
236  if (error_message.empty())
237  {
238  // Action feedback
239  if (!donghongding_generator.publishStatusPercentageDone(
240  "Trajectory of layer " + std::to_string(i) + " has been generated", next_progress_value, gh)) // percentage between 20% and 50%
241  return;
242  }
243  else
244  {
245  result.error_msg = error_message + "\n" + "Could not generate layer " + std::to_string(i);
246  ROS_ERROR_STREAM(result.error_msg);
247  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
248  gh.setAborted(result);
249  return;
250  }
251  additive_traj[i] = cb->current_layer_;
252  }
253 
254  std::string return_message;
255  return_message = donghongding_generator.connectMeshLayers(gh, 50, 90, additive_traj, msg);
256 
257  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
258  return;
259 
260  if (!return_message.empty())
261  {
262  result.error_msg = return_message + "\n" + "Error connecting layers";
263  ROS_ERROR_STREAM(result.error_msg);
264  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
265  gh.setAborted(result);
266  return;
267  }
268  }
269 
270  // Trajectory is now complete
271  // Create a message
272  // Fill response and publish trajectory
273 
274  // Action feedback
275  if (!donghongding_generator.publishStatusPercentageDone(
276  "Layers have been connected\nCreating message to publish trajectory", 90, gh))
277 
278  if (msg.poses.size() == 0)
279  {
280  result.error_msg = "Trajectory is empty";
281  ROS_ERROR_STREAM(result.error_msg);
282  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
283  gh.setAborted(result);
284  return;
285  }
286  result.number_of_poses = msg.poses.size();
287 
288  // Add UUID
289  for (auto &pose : msg.poses)
290  pose.unique_id = unique_id::toMsg(unique_id::fromRandom());
291 
292  // Set the time to zero, the trajectory is incomplete at this stage
293  // It will be published on trajectory_tmp, completed by fill_trajectory and then published on trajectory
294  msg.generated.nsec = 0;
295  msg.generated.sec = 0;
296  msg.modified = msg.generated;
297 
298  if (!donghongding_generator.publishStatusPercentageDone("Trajectory has been generated and published", 100, gh))
299  return;
300 
301  if (traj_pub->getNumSubscribers() == 0)
302  ROS_WARN_STREAM("No subscriber on topic " << traj_pub->getTopic());
303 
304  traj_pub->publish(msg);
305 
306  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
307  && gh.getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
308  return;
309 
310  gh.setSucceeded(result);
311 }
312 
314 {
315  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
316  || gh.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
317  gh.setCanceled();
318 }
319 
320 // Contours algorithm
322 {
323  // Change status to ACTIVE
324  gh.setAccepted();
325 
326  // Action elements
327  ram_path_planning::ContoursGoal goal;
328  ram_path_planning::ContoursResult result;
329  goal = *gh.getGoal();
330 
331  // Verify parameters
332  if (goal.file.empty())
333  {
334  result.error_msg = "File name cannot be empty";
335  ROS_ERROR_STREAM(result.error_msg);
336  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
337  gh.setAborted(result);
338  return;
339  }
340 
341  if (goal.height_between_layers <= 0)
342  {
343  result.error_msg = "Height between layers cannot be <= 0";
344  ROS_ERROR_STREAM(result.error_msg);
345  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
346  gh.setAborted(result);
347  return;
348  }
349 
350  if (goal.deposited_material_width <= 0)
351  {
352  result.error_msg = "Deposited material width cannot be <= 0";
353  ROS_ERROR_STREAM(result.error_msg);
354  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
355  gh.setAborted(result);
356  return;
357  }
358 
359  // Verify file extension
360  bool is_yaml_file(false);
361  const std::string file_extension(fileExtension(goal.file));
362  if (!strcasecmp(file_extension.c_str(), "yaml") || !strcasecmp(file_extension.c_str(), "yml"))
363  {
364  is_yaml_file = true;
365  if (goal.number_of_layers < 1)
366  {
367  result.error_msg = "Number of layers cannot be < 1";
368  ROS_ERROR_STREAM(result.error_msg);
369  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
370  gh.setAborted(result);
371  return;
372  }
373  }
374  else if (strcasecmp(file_extension.c_str(), "obj") && strcasecmp(file_extension.c_str(), "ply")
375  && strcasecmp(file_extension.c_str(), "stl"))
376  {
377  result.error_msg = "File is not a YAML, YML, OBJ, PLY or STL file: " + goal.file;
378  ROS_ERROR_STREAM(result.error_msg);
379  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
380  gh.setAborted(result);
381  return;
382  }
383 
384  // Create Trajectory message
385  ram_msgs::AdditiveManufacturingTrajectory msg;
386  msg.file = goal.file;
387 
388  // Add request parameter to the trajectory
389  msg.generation_info = "Deposited material width = " + std::to_string(goal.deposited_material_width * 1000.0)
390  + " mm\n";
391  msg.generation_info += "Height between layers = " + std::to_string(goal.height_between_layers * 1000.0) + " mm\n";
392 
393  if (!is_yaml_file)
394  {
395  msg.generation_info += "Slicing direction = " + std::to_string(goal.slicing_direction.x) + ", "
396  + std::to_string(goal.slicing_direction.y) + ", " + std::to_string(goal.slicing_direction.z);
397  }
398  else
399  {
400  msg.generation_info += "Number of layers = " + std::to_string(goal.number_of_layers);
401  }
402 
403  msg.similar_layers = is_yaml_file;
404  std::array<double, 3> slicing_direction;
405  slicing_direction[0] = goal.slicing_direction.x;
406  slicing_direction[1] = goal.slicing_direction.y;
407  slicing_direction[2] = goal.slicing_direction.z;
408 
409  std::vector<Layer> additive_traj;
410  cb->current_layer_.clear();
411 
412  // Generate trajectory
413 
414  // Action feedback
415  if (!contour_generator.publishStatusPercentageDone("Generating trajectory", 10, gh))
416  return;
417 
418  if (is_yaml_file)
419  {
420  std::string error_message;
421  error_message = contour_generator.generateOneLayerTrajectory(gh, goal.file, cb->current_layer_,
422  goal.deposited_material_width,
423  use_gui);
424 
425  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
426  return;
427 
428  if (error_message.empty())
429  {
430  // Action feedback
431  if (!contour_generator.publishStatusPercentageDone("Trajectory has been generated.\n Connecting Layers", 50, gh))
432  return;
433 
434  contour_generator.connectYamlLayers(gh, 50, 90, cb->current_layer_, msg, goal.number_of_layers,
435  goal.height_between_layers);
436  }
437  else
438  {
439  result.error_msg = error_message;
440  ROS_ERROR_STREAM(result.error_msg);
441  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
442  gh.setAborted(result);
443  return;
444  }
445  }
446  else
447  {
448  // Slice the mesh
449  const unsigned nb_layers(
450  ram_path_planning::sliceMesh(additive_traj, goal.file, cb->mesh_, cb->stripper_, goal.height_between_layers,
451  slicing_direction,
452  use_gui));
453 
454  if (nb_layers < 1)
455  {
456  result.error_msg = "Slicing failed, zero slice generated";
457  ROS_ERROR_STREAM(result.error_msg);
458  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
459  gh.setAborted(result);
460  return;
461  }
462  // Action feedback
463  if (!contour_generator.publishStatusPercentageDone("Slicing completed", 20, gh))
464  return;
465 
466  // Generate trajectory on each layer
467  for (unsigned i(0); i < additive_traj.size(); ++i)
468  {
469  Polygon contours(additive_traj[i][0][0]);
470  contours->DeepCopy(additive_traj[i][0][0]);
471 
472  std::string error_message;
473  error_message = contour_generator.generateOneLayerTrajectory(gh, contours, cb->current_layer_,
474  goal.deposited_material_width,
475  slicing_direction,
476  use_gui);
477 
478  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
479  return;
480 
481  if (error_message.empty())
482  {
483  // Action feedback
484  if (!contour_generator.publishStatusPercentageDone(
485  "Trajectory of layer " + std::to_string(i) + " has been generated", 20 + i * 30 / nb_layers, gh)) // percentage between 20% and 50%
486  return;
487  }
488  else
489  {
490  result.error_msg = error_message + "\n" + "Could not generate layer " + std::to_string(i);
491  ROS_ERROR_STREAM(result.error_msg);
492  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
493  gh.setAborted(result);
494  return;
495  }
496  additive_traj[i] = cb->current_layer_;
497  }
498 
499  std::string return_message;
500  return_message = contour_generator.connectMeshLayers(gh, 50, 90, additive_traj, msg);
501 
502  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
503  return;
504 
505  if (!return_message.empty())
506  {
507  result.error_msg = return_message + "\n" + "Error connecting layers";
508  ROS_ERROR_STREAM(result.error_msg);
509  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
510  gh.setAborted(result);
511  return;
512  }
513  }
514  // Trajectory is now complete
515  // Create a message
516  // Fill response and publish trajectory
517  // Action feedback
518  if (!contour_generator.publishStatusPercentageDone("Creating message to publish trajectory", 90, gh))
519  return;
520 
521  if (msg.poses.size() == 0)
522  {
523  result.error_msg = "Trajectory is empty";
524  ROS_ERROR_STREAM(result.error_msg);
525  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
526  gh.setAborted(result);
527  return;
528  }
529  result.number_of_poses = msg.poses.size();
530 
531  // Add UUID
532  for (auto &pose : msg.poses)
533  pose.unique_id = unique_id::toMsg(unique_id::fromRandom());
534 
535  // Set the time to zero, the trajectory is incomplete at this stage
536  // It will be published on trajectory_tmp, completed by fill_trajectory and then published on trajectory
537  msg.generated.nsec = 0;
538  msg.generated.sec = 0;
539  msg.modified = msg.generated;
540 
541  if (!contour_generator.publishStatusPercentageDone("Trajectory has been generated and published", 100, gh))
542  return;
543 
544  if (traj_pub->getNumSubscribers() == 0)
545  ROS_WARN_STREAM("No subscriber on topic " << traj_pub->getTopic());
546 
547  traj_pub->publish(msg);
548 
549  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
550  && gh.getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
551  return;
552 
553  gh.setSucceeded(result);
554 }
555 
557 {
558  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
559  || gh.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
560  gh.setCanceled();
561 }
562 
563 // Follow poses algorithm
565 {
566  // Change status to ACTIVE
567  gh.setAccepted();
568  // Action elements
569  ram_path_planning::FollowPosesGoal goal;
570  ram_path_planning::FollowPosesResult result;
571  goal = *gh.getGoal();
572 
573  // Action feedback
574  if (!follow_poses_generator.publishStatusPercentageDone("Checking goal parameters", 10, gh))
575  return;
576 
577  if (goal.file.empty())
578  {
579  result.error_msg = "File name cannot be empty";
580  ROS_ERROR_STREAM(result.error_msg);
581  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
582  gh.setAborted(result);
583  return;
584  }
585 
586  // Verify file extension
587  const std::string file_extension(fileExtension(goal.file));
588  if (strcasecmp(file_extension.c_str(), "yaml") && strcasecmp(file_extension.c_str(), "yml"))
589  {
590  result.error_msg = "File is not a YAML, YML, " + goal.file;
591  ROS_ERROR_STREAM(result.error_msg);
592  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
593  gh.setAborted(result);
594  return;
595  }
596  // Action feedback
597  if (!follow_poses_generator.publishStatusPercentageDone("Generating trajectory from YAML file", 40, gh))
598  return;
599 
600  // Create Trajectory message
601  ram_msgs::AdditiveManufacturingTrajectory msg;
602  msg.file = goal.file;
603 
604  // Generate trajectory
605  std::string error_message;
606  error_message = follow_poses_generator.generateTrajectory(goal.file, msg);
607  if (!error_message.empty())
608  {
609  result.error_msg = error_message;
610  ROS_ERROR_STREAM(result.error_msg);
611  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
612  gh.setAborted(result);
613  return;
614  }
615 
616  if (msg.poses.empty())
617  {
618  result.error_msg = "Generated trajectory is empty";
619  ROS_ERROR_STREAM(result.error_msg);
620  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
621  gh.setAborted(result);
622  return;
623  }
624  if (goal.duplicate_layer && msg.poses.back().layer_index != 0)
625  {
626  result.error_msg = "Trajectory contains multiple layers, cannot duplicate layers";
627  ROS_ERROR_STREAM(result.error_msg);
628  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
629  gh.setAborted(result);
630  return;
631  }
632 
633  unsigned polygon_count(0);
634  for (auto pose : msg.poses)
635  {
636  if (pose.polygon_start)
637  ++polygon_count;
638  }
639 
640  if (goal.duplicate_layer && polygon_count == 0)
641  {
642  result.error_msg = "Trajectory contains zero polygon!";
643  ROS_ERROR_STREAM(result.error_msg);
644  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
645  gh.setAborted(result);
646  return;
647  }
648 
649  if (goal.duplicate_layer && polygon_count > 1)
650  {
651  result.error_msg = "Trajectory contains multiple polygons, cannot duplicate layers";
652  ROS_ERROR_STREAM(result.error_msg);
653  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
654  gh.setAborted(result);
655  return;
656  }
657 
658  if (goal.duplicate_layer && goal.number_of_layers > 1)
659  {
660  error_message = follow_poses_generator.duplicateLayers(msg, goal.number_of_layers, goal.height_between_layers,
661  goal.invert_one_of_two_layers);
662  if (!error_message.empty())
663  {
664  result.error_msg = error_message + "\nError duplicating layers in the trajectory";
665  ROS_ERROR_STREAM(result.error_msg);
666  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
667  gh.setAborted(result);
668  return;
669  }
670  }
671 
672  // Trajectory is now complete
673  // Create a message
674  // Fill response and publish trajectory
675  // Action feedback
676  if (!follow_poses_generator.publishStatusPercentageDone("Creating message to publish trajectory from file", 70, gh))
677 
678  if (msg.poses.size() == 0)
679  {
680  result.error_msg = "Generated trajectory is empty";
681  ROS_ERROR_STREAM(result.error_msg);
682  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
683  gh.setAborted(result);
684  return;
685  }
686  result.number_of_poses = msg.poses.size();
687 
688  // The trajectory is incomplete at this stage
689  // It will be published on trajectory_tmp, completed by fill_trajectory and then published on trajectory
690 
691  // Action feedback
692  if (!follow_poses_generator.publishStatusPercentageDone("Trajectory has been generated", 100, gh))
693  return;
694 
695  if (traj_pub->getNumSubscribers() == 0)
696  ROS_ERROR_STREAM("No subscriber on topic " << traj_pub->getTopic() << ": trajectory is lost");
697 
698  traj_pub->publish(msg);
699 
700  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
701  && gh.getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
702  return;
703 
704  gh.setSucceeded(result);
705 }
706 
708 {
709  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
710  || gh.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
711  gh.setCanceled();
712 }
713 
714 int main(int argc,
715  char **argv)
716 {
717  ros::init(argc, argv, "path_planing");
720  spinner.start();
721 
722  traj_pub.reset(new ros::Publisher);
723  *traj_pub = nh.advertise<ram_msgs::AdditiveManufacturingTrajectory>("ram/trajectory_tmp", 1, true);
724 
725  // Action servers
727  donghongding_generator.service_name_,
730  false);
731  action_server_1.start();
732 
735  &contoursAlgorithmCancelCb, false);
736  action_server_2.start();
737 
739  follow_poses_generator.service_name_,
742  false);
743  action_server_3.start();
744 
745  nh.param<bool>("use_gui", use_gui, false);
746  if (use_gui)
747  {
748  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
749  vtkSmartPointer<vtkRenderWindow> render_window = vtkSmartPointer<vtkRenderWindow>::New();
750  render_window->AddRenderer(renderer);
751  render_window->SetSize(800, 600);
752 
753  vtkSmartPointer<vtkRenderWindowInteractor> render_window_interactor =
754  vtkSmartPointer<vtkRenderWindowInteractor>::New();
755  render_window_interactor->SetRenderWindow(render_window);
756  render_window_interactor->Initialize();
757 
758  vtkSmartPointer<vtkInteractorStyleTrackballCamera> image_style =
759  vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
760  render_window_interactor->SetInteractorStyle(image_style);
761 
762  render_window_interactor->AddObserver(vtkCommand::TimerEvent, cb);
763  render_window_interactor->CreateRepeatingTimer(500);
764 
765  render_window_interactor->Start();
766  }
767 
769  spinner.stop();
770  traj_pub.reset();
771  return 0;
772 }
static boost::uuids::uuid fromRandom(void)
std::string fileExtension(const std::string full_path)
unsigned sliceMesh(std::vector< Layer > &trajectory, const std::string file_name, const vtkSmartPointer< vtkPolyData > poly_data, vtkSmartPointer< vtkStripper > &stripper, const double height_between_layers, const std::array< double, 3 > slicing_direction, const bool use_gui=false)
Definition: mesh_slicer.cpp:66
void contoursAlgorithmGoalCb(actionlib::ServerGoalHandle< ram_path_planning::ContoursAction > gh)
ram_path_planning::FollowPoses< ram_path_planning::FollowPosesAction > follow_poses_generator
std::vector< PolygonVector > Layer
std::unique_ptr< ros::NodeHandle > nh
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void connectYamlLayers(actionlib::ServerGoalHandle< ActionSpec > &gh, const int current_progrress_value, const int next_progress_value, const Layer &current_layer, ram_msgs::AdditiveManufacturingTrajectory &msg, const double number_of_layers, const double height_between_layers, const std::array< double, 3 > offset_direction={0, 0, 1})
boost::shared_ptr< const Goal > getGoal() const
std::unique_ptr< ros::Publisher > traj_pub
void donghongDingAlgorithmCancelCb(actionlib::ServerGoalHandle< ram_path_planning::DonghongDingAction > gh)
void donghongDingAlgorithmGoalCb(actionlib::ServerGoalHandle< ram_path_planning::DonghongDingAction > gh)
std::string generateOneLayerTrajectory(actionlib::ServerGoalHandle< ActionSpec > &gh, const Polygon poly_data, Layer &layer, const double deposited_material_width, const std::array< double, 3 > normal_vector={0, 0, 1}, const bool use_gui=false)
vtkSmartPointer< vtkRendererUpdaterTimer > cb
void setCanceled(const Result &result=Result(), const std::string &text=std::string(""))
void spinner()
void setAccepted(const std::string &text=std::string(""))
std::string duplicateLayers(ram_msgs::AdditiveManufacturingTrajectory &msg, const unsigned number_of_layers, const double height_between_layers, bool invert_one_of_two_layers)
void FollowPosesAlgorithmCancelCb(actionlib::ServerGoalHandle< ram_path_planning::FollowPosesAction > gh)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
void FollowPosesAlgorithmGoalCb(actionlib::ServerGoalHandle< ram_path_planning::FollowPosesAction > gh)
std::string generateTrajectory(const Polygon poly_data, ram_msgs::AdditiveManufacturingTrajectory &msg)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
bool publishStatusPercentageDone(const std::string progress_msg, const unsigned percentage, actionlib::ServerGoalHandle< ActionSpec > &gh)
std::string connectMeshLayers(actionlib::ServerGoalHandle< ActionSpec > &gh, const int current_progrress_value, const int next_progress_value, std::vector< Layer > &layers, ram_msgs::AdditiveManufacturingTrajectory &msg)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
vtkSmartPointer< vtkPolyData > Polygon
#define ROS_WARN_STREAM(args)
std::vector< Polygon > PolygonVector
ram_path_planning::DonghongDing< ram_path_planning::DonghongDingAction > donghongding_generator
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
ram_path_planning::Contours< ram_path_planning::ContoursAction > contour_generator
static uuid_msgs::UniqueID toMsg(boost::uuids::uuid const &uu)
void contoursAlgorithmCancelCb(actionlib::ServerGoalHandle< ram_path_planning::ContoursAction > gh)
#define ROS_ERROR_STREAM(args)
bool use_gui
int main(int argc, char **argv)
std::string generateOneLayerTrajectory(actionlib::ServerGoalHandle< ActionSpec > &gh, const int current_progrress_value, const int next_progress_value, const Polygon poly_data, Layer &layer, const double deposited_material_width, const double contours_filtering_tolerance, const std::array< double, 3 > normal_vector={0, 0, 1}, const double polygon_division_tolerance=M_PI/6, const bool closest_to_bisector=false, const bool use_gui=false)
actionlib_msgs::GoalStatus getGoalStatus() const
ROSCPP_DECL void waitForShutdown()
vtkSmartPointer< vtkPolyData > Polygon


ram_path_planning
Author(s): Andres Campos - Institut Maupertuis
autogenerated on Mon Jun 10 2019 14:50:03