5 #include <ram_msgs/AdditiveManufacturingTrajectory.h> 11 #include <visualization_msgs/Marker.h> 15 #include <ram_path_planning/ContoursAction.h> 16 #include <ram_path_planning/DonghongDingAction.h> 17 #include <ram_path_planning/FollowPosesAction.h> 21 typedef vtkSmartPointer<vtkPolyData>
Polygon;
23 typedef std::vector<PolygonVector>
Layer;
34 vtkSmartPointer<vtkRendererUpdaterTimer>
cb = vtkSmartPointer<vtkRendererUpdaterTimer>::New();
38 size_t last_index = full_path.find_last_of(
"/");
39 std::string file_name = full_path.substr(last_index + 1, full_path.size());
41 last_index = file_name.find_last_of(
"\\");
42 file_name = file_name.substr(last_index + 1, file_name.size());
44 last_index = file_name.find_last_of(
".");
45 if (last_index == std::string::npos)
48 return file_name.substr(last_index + 1, file_name.size());
59 ram_path_planning::DonghongDingGoal goal;
60 ram_path_planning::DonghongDingResult result;
64 if (goal.file.empty())
66 result.error_msg =
"File name cannot be empty";
68 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
73 if (goal.height_between_layers <= 0)
75 result.error_msg =
"Height between layers cannot be <= 0";
77 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
82 if (goal.deposited_material_width <= 0)
84 result.error_msg =
"Deposited material width cannot be <= 0";
86 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
90 if (goal.contours_filtering_tolerance < 0)
92 result.error_msg =
"Contours filtering tolerance cannot be < 0";
94 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
100 bool is_yaml_file(
false);
102 if (!strcasecmp(file_extension.c_str(),
"yaml") || !strcasecmp(file_extension.c_str(),
"yml"))
105 if (goal.number_of_layers < 1)
107 result.error_msg =
"Number of layers cannot be < 1";
109 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
114 else if (strcasecmp(file_extension.c_str(),
"obj") && strcasecmp(file_extension.c_str(),
"ply")
115 && strcasecmp(file_extension.c_str(),
"stl"))
117 result.error_msg =
"File is not a YAML, YML, OBJ, PLY or STL file: " + goal.file;
119 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
125 ram_msgs::AdditiveManufacturingTrajectory msg;
126 msg.file = goal.file;
129 msg.generation_info =
"Deposited material width = " + std::to_string(goal.deposited_material_width * 1000.0)
131 msg.generation_info +=
"Contours filtering tolerance = " + std::to_string(goal.contours_filtering_tolerance * 1000.0)
133 msg.generation_info +=
"Height between layers = " + std::to_string(goal.height_between_layers * 1000.0) +
" mm\n";
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);
142 msg.generation_info +=
"Number of layers = " + std::to_string(goal.number_of_layers);
145 msg.similar_layers = is_yaml_file;
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;
152 std::vector<Layer> additive_traj;
153 cb->current_layer_.clear();
163 std::string error_message;
165 goal.deposited_material_width,
166 goal.contours_filtering_tolerance, M_PI / 6,
170 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
173 if (error_message.empty())
177 "Trajectory has been generated for one layer.\n Duplicating and connecting layers", 50, gh))
180 donghongding_generator.
connectYamlLayers(gh, 50, 90,
cb->current_layer_, msg, goal.number_of_layers,
181 goal.height_between_layers);
186 result.error_msg = error_message;
188 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
196 const unsigned nb_layers(
203 result.error_msg =
"Slicing failed, zero slice generated";
205 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
214 for (
unsigned i(0); i < additive_traj.size(); ++i)
216 Polygon contours(additive_traj[i][0][0]);
217 contours->DeepCopy(additive_traj[i][0][0]);
219 int current_progress_value = 20 + i * 30 / nb_layers;
220 int next_progress_value = 20 + (i + 1) * 30 / nb_layers;
222 std::string error_message;
226 goal.deposited_material_width,
227 goal.contours_filtering_tolerance,
233 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
236 if (error_message.empty())
240 "Trajectory of layer " + std::to_string(i) +
" has been generated", next_progress_value, gh))
245 result.error_msg = error_message +
"\n" +
"Could not generate layer " + std::to_string(i);
247 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
251 additive_traj[i] =
cb->current_layer_;
254 std::string return_message;
255 return_message = donghongding_generator.
connectMeshLayers(gh, 50, 90, additive_traj, msg);
257 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
260 if (!return_message.empty())
262 result.error_msg = return_message +
"\n" +
"Error connecting layers";
264 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
276 "Layers have been connected\nCreating message to publish trajectory", 90, gh))
278 if (msg.poses.size() == 0)
280 result.error_msg =
"Trajectory is empty";
282 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
286 result.number_of_poses = msg.poses.size();
289 for (
auto &pose : msg.poses)
294 msg.generated.nsec = 0;
295 msg.generated.sec = 0;
296 msg.modified = msg.generated;
301 if (
traj_pub->getNumSubscribers() == 0)
306 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
307 && gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
315 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
316 || gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
327 ram_path_planning::ContoursGoal goal;
328 ram_path_planning::ContoursResult result;
332 if (goal.file.empty())
334 result.error_msg =
"File name cannot be empty";
336 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
341 if (goal.height_between_layers <= 0)
343 result.error_msg =
"Height between layers cannot be <= 0";
345 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
350 if (goal.deposited_material_width <= 0)
352 result.error_msg =
"Deposited material width cannot be <= 0";
354 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
360 bool is_yaml_file(
false);
362 if (!strcasecmp(file_extension.c_str(),
"yaml") || !strcasecmp(file_extension.c_str(),
"yml"))
365 if (goal.number_of_layers < 1)
367 result.error_msg =
"Number of layers cannot be < 1";
369 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
374 else if (strcasecmp(file_extension.c_str(),
"obj") && strcasecmp(file_extension.c_str(),
"ply")
375 && strcasecmp(file_extension.c_str(),
"stl"))
377 result.error_msg =
"File is not a YAML, YML, OBJ, PLY or STL file: " + goal.file;
379 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
385 ram_msgs::AdditiveManufacturingTrajectory msg;
386 msg.file = goal.file;
389 msg.generation_info =
"Deposited material width = " + std::to_string(goal.deposited_material_width * 1000.0)
391 msg.generation_info +=
"Height between layers = " + std::to_string(goal.height_between_layers * 1000.0) +
" mm\n";
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);
400 msg.generation_info +=
"Number of layers = " + std::to_string(goal.number_of_layers);
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;
409 std::vector<Layer> additive_traj;
410 cb->current_layer_.clear();
420 std::string error_message;
422 goal.deposited_material_width,
425 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
428 if (error_message.empty())
434 contour_generator.
connectYamlLayers(gh, 50, 90,
cb->current_layer_, msg, goal.number_of_layers,
435 goal.height_between_layers);
439 result.error_msg = error_message;
441 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
449 const unsigned nb_layers(
456 result.error_msg =
"Slicing failed, zero slice generated";
458 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
467 for (
unsigned i(0); i < additive_traj.size(); ++i)
469 Polygon contours(additive_traj[i][0][0]);
470 contours->DeepCopy(additive_traj[i][0][0]);
472 std::string error_message;
474 goal.deposited_material_width,
478 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
481 if (error_message.empty())
485 "Trajectory of layer " + std::to_string(i) +
" has been generated", 20 + i * 30 / nb_layers, gh))
490 result.error_msg = error_message +
"\n" +
"Could not generate layer " + std::to_string(i);
492 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
496 additive_traj[i] =
cb->current_layer_;
499 std::string return_message;
500 return_message = contour_generator.
connectMeshLayers(gh, 50, 90, additive_traj, msg);
502 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
505 if (!return_message.empty())
507 result.error_msg = return_message +
"\n" +
"Error connecting layers";
509 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
521 if (msg.poses.size() == 0)
523 result.error_msg =
"Trajectory is empty";
525 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
529 result.number_of_poses = msg.poses.size();
532 for (
auto &pose : msg.poses)
537 msg.generated.nsec = 0;
538 msg.generated.sec = 0;
539 msg.modified = msg.generated;
544 if (
traj_pub->getNumSubscribers() == 0)
549 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
550 && gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
558 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
559 || gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
569 ram_path_planning::FollowPosesGoal goal;
570 ram_path_planning::FollowPosesResult result;
577 if (goal.file.empty())
579 result.error_msg =
"File name cannot be empty";
581 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
588 if (strcasecmp(file_extension.c_str(),
"yaml") && strcasecmp(file_extension.c_str(),
"yml"))
590 result.error_msg =
"File is not a YAML, YML, " + goal.file;
592 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
601 ram_msgs::AdditiveManufacturingTrajectory msg;
602 msg.file = goal.file;
605 std::string error_message;
607 if (!error_message.empty())
609 result.error_msg = error_message;
611 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
616 if (msg.poses.empty())
618 result.error_msg =
"Generated trajectory is empty";
620 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
624 if (goal.duplicate_layer && msg.poses.back().layer_index != 0)
626 result.error_msg =
"Trajectory contains multiple layers, cannot duplicate layers";
628 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
633 unsigned polygon_count(0);
634 for (
auto pose : msg.poses)
636 if (pose.polygon_start)
640 if (goal.duplicate_layer && polygon_count == 0)
642 result.error_msg =
"Trajectory contains zero polygon!";
644 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
649 if (goal.duplicate_layer && polygon_count > 1)
651 result.error_msg =
"Trajectory contains multiple polygons, cannot duplicate layers";
653 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
658 if (goal.duplicate_layer && goal.number_of_layers > 1)
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())
664 result.error_msg = error_message +
"\nError duplicating layers in the trajectory";
666 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
678 if (msg.poses.size() == 0)
680 result.error_msg =
"Generated trajectory is empty";
682 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
686 result.number_of_poses = msg.poses.size();
695 if (
traj_pub->getNumSubscribers() == 0)
700 if (gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE
701 && gh.
getGoalStatus().status != actionlib_msgs::GoalStatus::PREEMPTING)
709 if (gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
710 || gh.
getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
723 *
traj_pub = nh.
advertise<ram_msgs::AdditiveManufacturingTrajectory>(
"ram/trajectory_tmp", 1,
true);
731 action_server_1.start();
736 action_server_2.
start();
743 action_server_3.
start();
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);
753 vtkSmartPointer<vtkRenderWindowInteractor> render_window_interactor =
754 vtkSmartPointer<vtkRenderWindowInteractor>::New();
755 render_window_interactor->SetRenderWindow(render_window);
756 render_window_interactor->Initialize();
758 vtkSmartPointer<vtkInteractorStyleTrackballCamera> image_style =
759 vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
760 render_window_interactor->SetInteractorStyle(image_style);
762 render_window_interactor->AddObserver(vtkCommand::TimerEvent,
cb);
763 render_window_interactor->CreateRepeatingTimer(500);
765 render_window_interactor->Start();
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)
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 ¤t_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 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 ¶m_name, T ¶m_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)
const std::string service_name_
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)
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