33 #include <Eigen/Eigen> 34 #include <pcl/filters/project_inliers.h> 35 #include <pcl/surface/convex_hull.h> 42 const pcl::ModelCoefficients::Ptr model,
43 pcl::PointCloud<pcl::PointXYZRGB>& output,
44 shape_msgs::SolidPrimitive& shape,
45 geometry_msgs::Pose&
pose)
48 double min_volume = 1000.0;
49 Eigen::Matrix3f transformation;
53 for (
size_t i = 0; i < input.size(); ++i)
55 Eigen::Vector4f pp(input[i].
x, input[i].y, input[i].
z, 1);
56 Eigen::Vector4f m(model->values[0], model->values[1], model->values[2], model->values[3]);
57 double distance_to_plane = fabs(pp.dot(m));
58 if (distance_to_plane > height)
59 height = distance_to_plane;
63 pcl::PointCloud<pcl::PointXYZRGB>::Ptr flat(
new pcl::PointCloud<pcl::PointXYZRGB>);
64 pcl::ProjectInliers<pcl::PointXYZRGB> projection;
65 projection.setModelType(pcl::SACMODEL_PLANE);
66 projection.setInputCloud(input.makeShared());
67 projection.setModelCoefficients(model);
68 projection.filter(*flat);
71 pcl::PointCloud<pcl::PointXYZRGB>::Ptr flat_projected(
new pcl::PointCloud<pcl::PointXYZRGB>);
72 Eigen::Vector3f normal(model->values[0], model->values[1], model->values[2]);
73 Eigen::Quaternionf qz; qz.setFromTwoVectors(normal, Eigen::Vector3f::UnitZ());
74 Eigen::Matrix3f plane_rotation = qz.toRotationMatrix();
75 Eigen::Matrix3f inv_plane_rotation = plane_rotation.inverse();
77 for (
size_t i = 0; i < flat->size(); ++i)
80 p.getVector3fMap() = plane_rotation * (*flat)[i].getVector3fMap();
81 flat_projected->push_back(p);
85 pcl::PointCloud<pcl::PointXYZRGB> hull;
86 pcl::ConvexHull<pcl::PointXYZRGB> convex_hull;
87 convex_hull.setInputCloud(flat_projected);
88 convex_hull.setDimension(2);
89 convex_hull.reconstruct(hull);
92 shape_msgs::SolidPrimitive rect;
94 rect.dimensions.resize(3);
95 for (
size_t i = 0; i < hull.size() - 1; ++i)
98 double rise = hull[i+1].y - hull[i].y;
99 double run = hull[i+1].x - hull[i].x;
102 double l = sqrt((rise * rise) + (run * run));
108 Eigen::Matrix3f rotation;
109 rotation(0, 0) = run;
110 rotation(0, 1) = rise;
111 rotation(0, 2) = 0.0;
112 rotation(1, 0) = -rise;
113 rotation(1, 1) = run;
114 rotation(1, 2) = 0.0;
115 rotation(2, 0) = 0.0;
116 rotation(2, 1) = 0.0;
117 rotation(2, 2) = 1.0;
118 Eigen::Matrix3f inv_rotation = rotation.inverse();
121 pcl::PointCloud<pcl::PointXYZRGB> projected_cloud;
122 for (
size_t j = 0; j < hull.size(); ++j)
125 p.getVector3fMap() = rotation * hull[j].getVector3fMap();
126 projected_cloud.push_back(p);
130 double x_min = 1000.0;
131 double x_max = -1000.0;
132 double y_min = 1000.0;
133 double y_max = -1000.0;
134 for (
size_t j = 0; j < projected_cloud.size(); ++j)
136 if (projected_cloud[j].
x < x_min)
137 x_min = projected_cloud[j].x;
138 if (projected_cloud[j].
x > x_max)
139 x_max = projected_cloud[j].x;
141 if (projected_cloud[j].y < y_min)
142 y_min = projected_cloud[j].y;
143 if (projected_cloud[j].y > y_max)
144 y_max = projected_cloud[j].y;
148 double area = (x_max - x_min) * (y_max - y_min);
149 if (area*height < min_volume)
151 transformation = inv_plane_rotation * inv_rotation;
153 rect.dimensions[0] = (x_max - x_min);
154 rect.dimensions[1] = (y_max - y_min);
155 rect.dimensions[2] =
height;
157 Eigen::Vector3f pose3f((x_max + x_min)/2.0, (y_max + y_min)/2.0,
158 projected_cloud[0].
z + height/2.0);
159 pose3f = transformation * pose3f;
160 pose.position.x = pose3f(0);
161 pose.position.y = pose3f(1);
162 pose.position.z = pose3f(2);
164 Eigen::Quaternionf q(transformation);
165 pose.orientation.x = q.x();
166 pose.orientation.y = q.y();
167 pose.orientation.z = q.z();
168 pose.orientation.w = q.w();
170 min_volume = area *
height;
176 shape_msgs::SolidPrimitive cylinder;
177 cylinder.type = cylinder.CYLINDER;
178 cylinder.dimensions.resize(2);
179 for (
size_t i = 0; i < hull.size(); ++i)
181 for (
size_t j = i + 1; j < hull.size(); ++j)
186 p.x = (hull[i].x + hull[j].x) / 2.0;
187 p.y = (hull[i].y + hull[j].y) / 2.0;
190 for (
size_t k = 0; k < hull.size(); ++k)
192 double dx = hull[k].x - p.x;
193 double dy = hull[k].y - p.y;
194 double r = sqrt((dx * dx) + (dy * dy));
199 double volume = M_PI * radius * radius *
height;
200 if (volume < min_volume)
202 transformation = inv_plane_rotation;
204 cylinder.dimensions[0] =
height;
205 cylinder.dimensions[1] = radius;
207 Eigen::Vector3f pose3f(p.x, p.y, hull[0].z + height/2.0);
208 pose3f = transformation * pose3f;
209 pose.position.x = pose3f(0);
210 pose.position.y = pose3f(1);
211 pose.position.z = pose3f(2);
222 Eigen::Vector3f origin(pose.position.x, pose.position.y, pose.position.z);
223 for (
size_t j = 0; j < input.size(); ++j)
226 p.getVector3fMap() = transformation * (input[j].getVector3fMap() - origin);
233 pcl::PointCloud<pcl::PointXYZRGB>& output,
234 shape_msgs::SolidPrimitive& shape,
235 geometry_msgs::Pose&
pose)
238 pcl::ModelCoefficients::Ptr coefficients(
new pcl::ModelCoefficients);
239 coefficients->values.resize(4);
240 coefficients->values[0] = 0.0;
241 coefficients->values[1] = 0.0;
242 coefficients->values[2] = 1.0;
243 coefficients->values[3] = 1000.0;
244 for (
size_t i = 0; i < input.size(); ++i)
246 if (input[i].z < coefficients->
values[3])
247 coefficients->values[3] = input[i].z;
249 coefficients->values[3] = -coefficients->values[3];
250 return extractShape(input, coefficients, output, shape, pose);
254 shape_msgs::SolidPrimitive& shape,
255 geometry_msgs::Pose&
pose)
257 double x_min = 1000.0;
258 double x_max = -1000.0;
259 double y_min = 1000.0;
260 double y_max = -1000.0;
261 double z_min = 1000.0;
262 double z_max = -1000.0;
264 for (
size_t i = 0; i < input.size(); ++i)
266 if (input[i].
x < x_min)
268 if (input[i].
x > x_max)
271 if (input[i].y < y_min)
273 if (input[i].y > y_max)
276 if (input[i].
z < z_min)
278 if (input[i].
z > z_max)
282 pose.position.x = (x_min + x_max)/2.0;
283 pose.position.y = (y_min + y_max)/2.0;
284 pose.position.z = (z_min + z_max)/2.0;
286 shape.type = shape.BOX;
287 shape.dimensions.push_back(x_max-x_min);
288 shape.dimensions.push_back(y_max-y_min);
289 shape.dimensions.push_back(z_max-z_min);
std::vector< double > values
bool extractShape(const pcl::PointCloud< pcl::PointXYZRGB > &input, pcl::PointCloud< pcl::PointXYZRGB > &output, shape_msgs::SolidPrimitive &shape, geometry_msgs::Pose &pose)
Find the smallest shape primitive we can fit around this object.
bool extractUnorientedBoundingBox(const pcl::PointCloud< pcl::PointXYZRGB > &input, shape_msgs::SolidPrimitive &shape, geometry_msgs::Pose &pose)
Find a bounding box around a cloud. This method does not attempt to find best orientation and so the ...
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE const tfScalar & z() const
void run(ClassLoader *loader)