1 #ifndef RAM_PATH_PLANNING_DONGHONG_DINGBASE_IMP_HPP 2 #define RAM_PATH_PLANNING_DONGHONG_DINGBASE_IMP_HPP 7 template<
class ActionSpec>
9 const std::string description,
10 const std::string service_name) :
15 template<
class ActionSpec>
21 template<
class ActionSpec>
23 const int current_progrress_value,
24 const int next_progress_value,
25 std::vector<Layer> &layers,
26 ram_msgs::AdditiveManufacturingTrajectory &msg)
33 unsigned first_layer = 0;
34 unsigned n_polygons = layers[0].size();
37 return "connectMeshLayers: function to connect layers with several polygons is not implemented";
39 for (
unsigned layer_id(0); layer_id < layers.size(); ++layer_id)
41 if (layers[layer_id].size() != n_polygons)
43 return "connectMeshLayers: function to connect layers with several polygons is not implemented";
59 template<
class ActionSpec>
61 const int current_progrress_value,
62 const int next_progress_value,
63 const Layer ¤t_layer,
64 ram_msgs::AdditiveManufacturingTrajectory &msg,
65 const double number_of_layers,
66 const double height_between_layers,
67 const std::array<double, 3> offset_direction)
70 int progress_value = 0;
72 double offset_dir[3] = {offset_direction[0], offset_direction[1], offset_direction[2]};
74 if (vtkMath::Norm(offset_dir) == 0)
79 vtkMath::Normalize(offset_dir);
81 unsigned layer_index(0);
82 for (
auto polygon_vector : current_layer)
84 for (
auto polygon : polygon_vector)
86 vtkIdType n_points = polygon->GetNumberOfPoints();
87 for (vtkIdType layer_id(0); layer_id < number_of_layers; ++layer_id)
89 double offset_vector[3];
90 offset_vector[0] = height_between_layers * layer_id * offset_dir[0];
91 offset_vector[1] = height_between_layers * layer_id * offset_dir[1];
92 offset_vector[2] = height_between_layers * layer_id * offset_dir[2];
94 for (vtkIdType point_id(0); point_id <= n_points; ++point_id)
97 Eigen::Isometry3d pose_isometry = Eigen::Isometry3d::Identity();
98 polygon->GetCell(0)->GetPoints()->GetPoint(point_id % n_points, p);
100 pose_isometry.translation()[0] = (p[0] + offset_vector[0]);
101 pose_isometry.translation()[1] = (p[1] + offset_vector[1]);
102 pose_isometry.translation()[2] = (p[2] + offset_vector[2]);
104 ram_msgs::AdditiveManufacturingPose pose_srv;
106 pose_srv.layer_level = layer_id;
107 pose_srv.layer_index = layer_index;
109 if (layer_id == 0 && point_id == 0)
111 pose_srv.polygon_start =
true;
113 msg.poses.push_back(pose_srv);
116 v = (layer_id + 1.0) / number_of_layers;
117 progress_value = (int)(current_progrress_value + v * (next_progress_value - current_progrress_value));
119 "Adding layer " + std::to_string(layer_index) +
" to a trajectory message", progress_value, gh))
122 msg.poses.back().polygon_end =
true;
127 template<
class ActionSpec>
129 const int current_progrress_value,
130 const int next_progress_value,
131 std::vector<Layer> &layers,
132 ram_msgs::AdditiveManufacturingTrajectory &msg,
133 const unsigned first_layer)
136 int progress_value = 0;
137 unsigned n_layers(layers.size());
143 double p_first_layer[3];
145 layers.back()[0][0]->GetCell(0)->GetPoints()->GetPoint(0, l2);
148 vtkMath::Subtract(p_first_layer, l2, l2_p);
151 vtkMath::Add(l2, l2_l1, l1);
153 for (
unsigned layer_id(0); layer_id < n_layers; ++layer_id)
155 vtkIdType n_points = layers[layer_id][0][0]->GetCell(0)->GetNumberOfPoints();
157 vtkIdType closest_edge_id = 0;
158 double connection_point[3] = {0, 0, 0};
159 double shortest_distance = DBL_MAX;
160 bool is_close_to_a_vertex =
false;
163 for (vtkIdType
id(0);
id < n_points; ++id)
167 layers[layer_id][0][0]->GetCell(0)->GetEdge(
id)->GetPoints()->GetPoint(0, e_p0);
168 layers[layer_id][0][0]->GetCell(0)->GetEdge(
id)->GetPoints()->GetPoint(1, e_p1);
169 double closestPt1[3];
170 double closestPt2[3];
173 double distance_to_line = vtkLine::DistanceBetweenLineSegments(l1, l2, e_p0, e_p1, closestPt1, closestPt2, t1,
176 if (distance_to_line < shortest_distance)
178 shortest_distance = distance_to_line;
182 closest_edge_id = id;
184 connection_point[0] = e_p0[0];
185 connection_point[1] = e_p0[1];
186 connection_point[2] = e_p0[2];
187 is_close_to_a_vertex =
true;
191 closest_edge_id =
id + 1;
193 connection_point[0] = e_p1[0];
194 connection_point[1] = e_p1[1];
195 connection_point[2] = e_p1[2];
196 is_close_to_a_vertex =
true;
200 closest_edge_id = id;
202 connection_point[0] = closestPt2[0];
203 connection_point[1] = closestPt2[1];
204 connection_point[2] = closestPt2[2];
205 is_close_to_a_vertex =
false;
210 Eigen::Isometry3d first_pose_isometry = Eigen::Isometry3d::Identity();
211 ram_msgs::AdditiveManufacturingPose first_pose_srv;
213 first_pose_isometry.translation()[0] = connection_point[0];
214 first_pose_isometry.translation()[1] = connection_point[1];
215 first_pose_isometry.translation()[2] = connection_point[2];
218 first_pose_srv.layer_level = layer_id + first_layer;
219 first_pose_srv.layer_index = first_pose_srv.layer_level;
222 first_pose_srv.polygon_start =
true;
223 msg.poses.push_back(first_pose_srv);
225 for (vtkIdType i(0); i < n_points; ++i)
228 layers[layer_id][0][0]->GetCell(0)->GetPoints()->GetPoint((closest_edge_id + i + 1) % n_points, p);
229 Eigen::Isometry3d pose_isometry = Eigen::Isometry3d::Identity();
230 ram_msgs::AdditiveManufacturingPose pose_srv;
232 pose_isometry.translation()[0] = p[0];
233 pose_isometry.translation()[1] = p[1];
234 pose_isometry.translation()[2] = p[2];
237 pose_srv.layer_level = layer_id + first_layer;
238 pose_srv.layer_index = pose_srv.layer_level;
240 msg.poses.push_back(pose_srv);
242 if (!is_close_to_a_vertex)
244 first_pose_srv.polygon_start =
false;
245 first_pose_srv.layer_level = layer_id + first_layer;
246 msg.poses.push_back(first_pose_srv);
249 v = (layer_id + 1.0) / n_layers;
250 progress_value = (int)(current_progrress_value + v * (next_progress_value - current_progrress_value));
256 msg.poses.back().polygon_end =
true;
260 template<
class ActionSpec>
264 double norm = vtkMath::Norm(v1) * vtkMath::Norm(v2);
266 double cross_v1_v2[3];
267 vtkMath::Cross(v1, v2, cross_v1_v2);
268 double sin_angle = vtkMath::Dot(
normal_vector_, cross_v1_v2) / norm;
269 double cos_angle = vtkMath::Dot(v1, v2) / norm;
270 return atan2(sin_angle, cos_angle);
273 template<
class ActionSpec>
277 double ax, ay, az, bx, by, bz;
279 vtkIdType n_points = p->GetNumberOfPoints();
285 for (vtkIdType i = 0; i < n_points; ++i)
290 p->GetPoint((i + 1) % n_points, v2);
300 n[0] += (ay * bz - az * by);
301 n[1] += (az * bx - ax * bz);
302 n[2] += (ax * by - ay * bx);
305 vtkMath::Normalize(n);
308 template<
class ActionSpec>
310 const double deposited_material_width)
312 vtkSmartPointer<vtkCellArray> polygon_array = vtkSmartPointer<vtkCellArray>::New();
313 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
314 vtkIdType n_cells = poly_data->GetNumberOfCells();
315 for (vtkIdType cell_id = 0; cell_id < n_cells; ++cell_id)
317 vtkIdType n_points = poly_data->GetCell(cell_id)->GetNumberOfPoints();
318 vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
319 for (vtkIdType point_id = 0; point_id < n_points; ++point_id)
325 poly_data->GetCell(cell_id)->GetPoints()->GetPoint((n_points - 1), p0);
327 poly_data->GetCell(cell_id)->GetPoints()->GetPoint((point_id - 1), p0);
328 poly_data->GetCell(cell_id)->GetPoints()->GetPoint(point_id, p1);
329 poly_data->GetCell(cell_id)->GetPoints()->GetPoint((point_id + 1) % n_points, p2);
332 vtkMath::Subtract(p0, p1, v1);
333 vtkMath::Subtract(p2, p1, v2);
334 vtkMath::Normalize(v1);
335 vtkMath::Normalize(v2);
338 vtkMath::Add(v1, v2, bisector);
339 vtkMath::Normalize(bisector);
341 for (
int k = 0; k < 3; ++k)
342 new_point[k] = p1[k] + deposited_material_width /
sin(angle / 2) * bisector[k];
344 polygon->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
345 polygon->GetPoints()->InsertNextPoint(new_point);
346 points->InsertNextPoint(new_point);
350 for (vtkIdType i(0); i < n_points; ++i)
354 poly_data->GetCell(cell_id)->GetPoints()->GetPoint(i, p_i);
355 polygon->GetPoints()->GetPoint(i, new_p_i);
357 for (vtkIdType j(0); j < n_points; ++j)
361 poly_data->GetCell(cell_id)->GetPoints()->GetPoint(j, p_j);
362 polygon->GetPoints()->GetPoint(j, new_p_j);
366 int intersection = vtkLine::Intersection3D(p_i, new_p_i, p_j, new_p_j, u, v);
368 if (intersection == 2)
370 ROS_ERROR_STREAM(
"offsetPolygonContour: one or multiple edges are too short! Lines: " << i <<
" and " << j);
375 polygon_array->InsertNextCell(polygon);
377 poly_data->SetPolys(polygon_array);
378 poly_data->SetPoints(points);
383 template<
class ActionSpec>
386 vtkIdType n_cells = poly_data->GetNumberOfCells();
388 for (vtkIdType i(0); i < n_cells; ++i)
390 for (vtkIdType j(i + 1); j < n_cells; ++j)
393 vtkIdType n_edges_i = poly_data->GetCell(i)->GetNumberOfEdges();
394 vtkIdType n_edges_j = poly_data->GetCell(j)->GetNumberOfEdges();
395 for (vtkIdType e_i(0); e_i < n_edges_i; ++e_i)
397 for (vtkIdType e_j(0); e_j < n_edges_j; ++e_j)
402 poly_data->GetCell(i)->GetEdge(e_i)->GetPoints()->GetPoint(0, ei_p1);
403 poly_data->GetCell(i)->GetEdge(e_i)->GetPoints()->GetPoint(1, ei_p2);
407 poly_data->GetCell(j)->GetEdge(e_j)->GetPoints()->GetPoint(0, ej_p1);
408 poly_data->GetCell(j)->GetEdge(e_j)->GetPoints()->GetPoint(1, ej_p2);
412 int intersection = vtkLine::Intersection3D(ei_p1, ei_p2, ej_p1, ej_p2, u, v);
414 if (intersection == 2)
416 ROS_ERROR_STREAM(
"intersectionBetweenContours: contours " << i <<
" and " << j <<
" intersects");
419 else if (intersection == 3)
422 double closest_pt1[3];
423 double closest_pt2[3];
424 if (vtkLine::DistanceBetweenLineSegments(ei_p1, ei_p2, ej_p1, ej_p2, closest_pt1, closest_pt2, u, v) == 0)
426 ROS_ERROR_STREAM(
"intersectionBetweenContours: contours " << i <<
" and " << j <<
" are overlapping");
437 template<
class ActionSpec>
439 std::vector<int> &level,
440 std::vector<int> &father)
442 vtkIdType n_cells = poly_data->GetNumberOfCells();
445 std::vector<std::vector<int> > relationship(n_cells, std::vector<int>(n_cells, 0));
447 level = std::vector<int>(n_cells, 0);
448 father = std::vector<int>(n_cells, -1);
450 for (vtkIdType i(0); i < n_cells; ++i)
453 vtkSmartPointer<vtkPoints> point_list = vtkSmartPointer<vtkPoints>::New();
454 point_list = poly_data->GetCell(i)->GetPoints();
457 vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
458 for (vtkIdType k(0); k < point_list->GetNumberOfPoints(); ++k)
461 point_list->GetPoint(k, p);
462 polygon->GetPoints()->InsertNextPoint(p[0], p[1], p[2]);
468 polygon->GetPoints()->GetBounds(bounds);
470 for (vtkIdType j(0); j < n_cells; ++j)
476 poly_data->GetCell(j)->GetPoints()->GetPoint(0, p);
477 int in_polygon = polygon->PointInPolygon(
478 p, polygon->GetPoints()->GetNumberOfPoints(),
479 static_cast<double*
>(polygon->GetPoints()->GetData()->GetVoidPointer(0)),
484 relationship[i][j] = 1;
490 for (
unsigned j(0); j < n_cells; ++j)
492 for (
unsigned i(0); i < n_cells; ++i)
494 if (relationship[i][j] == 1 && level[i] == (level[j] - 1))
504 template<
class ActionSpec>
506 const std::vector<int> level,
507 const std::vector<int> father,
510 typedef vtkSmartPointer<vtkPolygon> Contour;
514 ROS_ERROR_STREAM(
"organizePolygonContoursInLayer: poly_data is not initialized!");
518 vtkIdType n_cells_contours = poly_data->GetNumberOfCells();
519 if (n_cells_contours == 0)
527 for (vtkIdType i(0); i < n_cells_contours; ++i)
529 if (level[i] % 2 != 0)
532 vtkSmartPointer<vtkCellArray> contour_array = vtkSmartPointer<vtkCellArray>::New();
533 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
535 Contour contour = Contour::New();
536 vtkSmartPointer<vtkPoints> point_list = vtkSmartPointer<vtkPoints>::New();
537 point_list = poly_data->GetCell(i)->GetPoints();
547 ROS_ERROR_STREAM(
"organizePolygonContoursInLayer: Contour is not co-planar to slicing plane ");
553 for (vtkIdType k(0); k < point_list->GetNumberOfPoints(); ++k)
556 point_list->GetPoint(k, p);
557 contour->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
558 points->InsertNextPoint(p);
563 for (vtkIdType k = point_list->GetNumberOfPoints(); k > 0; --k)
566 point_list->GetPoint((k - 1), p);
567 contour->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
568 points->InsertNextPoint(p);
572 contour_array->InsertNextCell(contour);
575 for (vtkIdType j(0); j < n_cells_contours; ++j)
580 contour = vtkSmartPointer<vtkPolygon>::New();
581 point_list = vtkSmartPointer<vtkPoints>::New();
582 point_list = poly_data->GetCell(j)->GetPoints();
589 ROS_ERROR_STREAM(
"organizePolygonContoursInLayer: Contour is not co-planar to slicing plane ");
594 for (vtkIdType k = 0; k < point_list->GetNumberOfPoints(); k++)
597 point_list->GetPoint(k, p);
598 contour->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
599 points->InsertNextPoint(p[0], p[1], p[2]);
604 for (vtkIdType k = point_list->GetNumberOfPoints(); k > 0; k--)
607 point_list->GetPoint((k - 1), p);
608 contour->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
609 points->InsertNextPoint(p);
614 ROS_ERROR_STREAM(
"organizePolygonContoursInLayer: normal vector is not parallel to Z axis");
617 contour_array->InsertNextCell(contour);
622 Polygon polygon = Polygon::New();
624 polygon->SetPolys(contour_array);
625 polygon->SetPoints(points);
626 poly_vector.push_back(polygon);
627 layer.push_back(poly_vector);
633 template<
class ActionSpec>
635 const double tolerance)
665 vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
666 cleaner->SetInputData(poly_data);
667 cleaner->ToleranceIsAbsoluteOn();
668 cleaner->SetAbsoluteTolerance(tolerance);
670 if (cleaner->GetOutput()->GetNumberOfPoints() < 3)
673 "removeDuplicatePoints: Not enough points" << std::endl <<
674 "vtkPolyData contains " << cleaner->GetOutput()->GetNumberOfPoints() <<
" points");
677 poly_data->ShallowCopy(cleaner->GetOutput());
682 template<
class ActionSpec>
684 const double tolerance)
686 vtkSmartPointer<vtkCellArray> polygon_array = vtkSmartPointer<vtkCellArray>::New();
687 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
688 vtkSmartPointer<vtkPolyData> new_poly_data = vtkSmartPointer<vtkPolyData>::New();
690 vtkIdType n_cells = polygon->GetNumberOfCells();
691 for (vtkIdType cell_id(0); cell_id < n_cells; ++cell_id)
693 vtkIdType n_points = polygon->GetCell(cell_id)->GetNumberOfPoints();
694 vtkSmartPointer<vtkPolygon> contour = vtkSmartPointer<vtkPolygon>::New();
696 polygon->GetCell(cell_id)->GetPoints()->GetPoint(0, p0);
697 for (vtkIdType point_id(0); point_id < n_points; ++point_id)
701 polygon->GetCell(cell_id)->GetPoints()->GetPoint((point_id + 1) % n_points, p1);
702 polygon->GetCell(cell_id)->GetPoints()->GetPoint((point_id + 2) % n_points, p2);
704 double distance =
sqrt(vtkLine::DistanceToLine(p1, p0, p2));
705 if (std::abs(distance) > tolerance)
708 contour->GetPointIds()->InsertNextId(points->GetNumberOfPoints());
709 points->InsertNextPoint(p1);
716 if (contour->GetPointIds()->GetNumberOfIds() < 3)
719 "mergeColinearEdges: Cell " << cell_id <<
" must have at least 3 points outside the region of tolerance");
723 polygon_array->InsertNextCell(contour);
726 new_poly_data->SetPolys(polygon_array);
727 new_poly_data->SetPoints(points);
729 polygon->ShallowCopy(new_poly_data);
733 template<
class ActionSpec>
735 ram_msgs::AdditiveManufacturingTrajectory &msg,
736 const unsigned first_layer)
738 std::vector<Layer> layers_vector;
740 unsigned n_polygons = layers[0].size();
741 vtkSmartPointer<vtkCenterOfMass> center_of_mass_filter = vtkSmartPointer<vtkCenterOfMass>::New();
743 while (n_polygons > 0)
748 center_of_mass_filter->SetInputData(layers[0][0][0]);
749 center_of_mass_filter->SetUseScalarsAsWeights(
false);
750 center_of_mass_filter->Update();
751 center_of_mass_filter->GetCenter(center_0);
753 current_layer.clear();
754 layers_vector.clear();
755 current_layer.push_back(layers[0][0]);
756 layers_vector.push_back(current_layer);
758 layers[0].erase(layers[0].begin());
760 for (
unsigned layer_id(1); layer_id < layers.size(); ++layer_id)
762 unsigned closest_polygon_vector_id = 0;
763 double min_distance = DBL_MAX;
764 for (
unsigned polygon_vector_id(1); polygon_vector_id < layers[layer_id].size(); ++polygon_vector_id)
767 center_of_mass_filter->SetInputData(layers[layer_id][polygon_vector_id][0]);
768 center_of_mass_filter->SetUseScalarsAsWeights(
false);
769 center_of_mass_filter->Update();
770 center_of_mass_filter->GetCenter(center_1);
772 double distance =
sqrt(vtkMath::Distance2BetweenPoints(center_0, center_1));
773 if (distance < min_distance)
775 min_distance = distance;
776 closest_polygon_vector_id = polygon_vector_id;
780 current_layer.clear();
781 current_layer.push_back(layers[layer_id][closest_polygon_vector_id]);
782 layers_vector.push_back(current_layer);
784 layers[layer_id].erase(layers[layer_id].begin() + closest_polygon_vector_id);
double angleBetweenVectors(const double v1[3], const double v2[3])
void identifyRelationships(const Polygon poly_data, std::vector< int > &level, std::vector< int > &father)
bool mergeColinearEdges(const Polygon poly_data, const double tolerance=1e-6)
std::vector< Polygon > PolygonVector
virtual ~DonghongDingBase()=0
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
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})
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
void computeNormal(vtkPoints *p, double *n)
bool organizePolygonContoursInLayer(const Polygon poly_data, const std::vector< int > level, const std::vector< int > father, Layer &layer)
bool publishStatusPercentageDone(const std::string progress_msg, const unsigned percentage, actionlib::ServerGoalHandle< ActionSpec > &gh)
bool removeDuplicatePoints(const Polygon poly_data, const double tolerance=1e-6)
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)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
vtkSmartPointer< vtkPolyData > Polygon
std::vector< PolygonVector > Layer
double deposited_material_width_
bool intersectionBetweenContours(const Polygon poly_data)
const double calculation_tol_
bool offsetPolygonContour(const Polygon poly_data, const double deposited_material_width)
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
void connectLayersWithOnePolygon(actionlib::ServerGoalHandle< ActionSpec > &gh, const int current_progrress_value, const int next_progress_value, std::vector< Layer > &layers, ram_msgs::AdditiveManufacturingTrajectory &msg, const unsigned first_layer)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
#define ROS_ERROR_STREAM(args)
void divideInLayersWithOnePolygon(std::vector< Layer > &layers, ram_msgs::AdditiveManufacturingTrajectory &msg, const unsigned first_layer)
DonghongDingBase(const std::string name, const std::string description, const std::string service_name)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)