plane_supported_cuboid_estimator.h
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2015, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/o2r other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 
37 #ifndef JSK_PCL_ROS_PLANE_SUPPORTED_CUBOID_ESTIMATOR_H_
38 #define JSK_PCL_ROS_PLANE_SUPPORTED_CUBOID_ESTIMATOR_H_
39 
44 #include <boost/random.hpp>
45 #include <dynamic_reconfigure/server.h>
49 #include <algorithm>
50 
51 
52 // ROS messages
53 #include <jsk_recognition_msgs/PolygonArray.h>
54 #include <jsk_recognition_msgs/BoundingBoxArray.h>
55 #include <jsk_recognition_msgs/ModelCoefficientsArray.h>
56 #include <jsk_recognition_msgs/HistogramWithRange.h>
57 #include <jsk_pcl_ros/PlaneSupportedCuboidEstimatorConfig.h>
58 #include <sensor_msgs/PointCloud2.h>
59 #include <std_srvs/Empty.h>
60 
61 // pcl
62 #include <pcl/tracking/tracking.h>
65 #include <pcl/kdtree/kdtree_flann.h>
66 
67 namespace jsk_pcl_ros
68 {
69 
70  // Utility function to compute likelihood
75  inline double binaryLikelihood(double v, double min, double max)
76  {
77  if (v < min) {
78  return 0;
79  }
80  else if (v > max) {
81  return 0;
82  }
83  else {
84  return 1;
85  }
86  }
87 
88  template <class Config>
90  pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud,
91  const std::vector<Polygon::Ptr>& planes,
92  const Config& config)
93  {
94  double likelihood = 1.0;
95  Polygon::Ptr plane = planes[p.plane_index];
96  if (p.plane_index == -1) {
97  // Do nothing
98  }
99  else {
100  Eigen::Vector3f projected_point;
101  plane->project(Eigen::Vector3f(p.getVector3fMap()), projected_point);
102  if (plane->isInside(projected_point)) {
103  likelihood *= 1.0;
104  }
105  else {
106  likelihood = 0.0;
107  }
108  }
109  float local_z = plane->distanceToPoint(Eigen::Vector3f(p.getVector3fMap()));
110  likelihood *= binaryLikelihood(local_z, config.range_likelihood_local_min_z, config.range_likelihood_local_max_z);
111  return likelihood;
112  }
113 
114  template <class Config>
117  const std::vector<Polygon::Ptr>& planes,
118  const Config& config)
119  {
120  Polygon::Ptr plane = planes[p.plane_index];
121  if (config.use_support_plane_angular_likelihood) {
122  // double cos_likelihood = (p.toEigenMatrix().rotation() * Eigen::Vector3f::UnitZ()).dot(plane->getNormal());
123  double cos_likelihood = (p.toEigenMatrix().rotation() * Eigen::Vector3f::UnitX()).dot(plane->getNormal());
124  // ROS_INFO("cos_likelihood: %f", cos_likelihood);
125  return pow(std::abs(cos_likelihood),
126  config.support_plane_angular_likelihood_weight_power);
127  }
128  else {
129  return 1.0;
130  }
131  }
132 
133 
134  template <class Config>
137  const Config& config)
138  {
139  if (config.use_surface_area_likelihood) {
140  double v = p.area();
141  return 1.0 / (1.0 + pow(v, config.surface_area_error_power));
142  }
143  else {
144  return 1.0;
145  }
146  }
147 
148  template <class Config>
151  pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud,
152  pcl::KdTreeFLANN<pcl::PointXYZ>& tree,
153  const Eigen::Vector3f& viewpoint,
154  const Config& config)
155  {
156  Eigen::Affine3f pose = p.toEigenMatrix();
157  Eigen::Affine3f pose_inv = pose.inverse();
158  const Eigen::Vector3f local_vp = pose_inv * viewpoint;
159  std::vector<int> visible_faces = p.visibleFaceIndices(local_vp);
160  double r = sqrt(p.dx /2 * p.dx/2 + p.dy/2 * p.dy/2 + p.dz/2 * p.dz/2);
161  std::vector<int> candidate_point_indices;
162  std::vector<float> candidate_point_distances;
163  pcl::PointXYZ xyz_point;
164  xyz_point.getVector3fMap() = p.getVector3fMap();
165  size_t inliers = 0;
166  // roughly search near points by kdtree radius search
167  tree.radiusSearch(xyz_point, r + config.outlier_distance, candidate_point_indices, candidate_point_distances);
168  if (candidate_point_indices.size() < config.min_inliers) {
169  return 0;
170  }
171  else {
172  //ROS_INFO("indices: %lu", candidate_point_indices.size());
173  double error = 0.0;
174 
176  std::vector<Polygon::Ptr> faces = cube->faces();
177  for (size_t i = 0; i < candidate_point_indices.size(); i++) {
178  int index = candidate_point_indices[i];
179  Eigen::Vector3f v = cloud->points[index].getVector3fMap();
180  if (config.use_occlusion_likelihood) {
181  double d = p.distanceNearestToPlaneWithOcclusion(v, visible_faces, faces);
182  if (d <= config.outlier_distance) {
183  //error *= 1 / (1 + pow(d, config.plane_distance_error_power));
184  error += pow(d, config.plane_distance_error_power);
185  ++inliers;
186  }
187  }
188  else {
189  Eigen::Vector3f local_v = pose_inv * v;
190  double d = p.signedDistanceToPlane(local_v, p.nearestPlaneIndex(local_v));
191  if (config.use_inside_points_distance_zero) {
192  if (d < 0) {
193  d = 0;
194  }
195  }
196  else {
197  d = std::abs(d);
198  }
199  if (d <= config.outlier_distance) {
200  //error *= 1 / (1 + pow(d, config.plane_distance_error_power));
201  error += pow(d, config.plane_distance_error_power);
202  ++inliers;
203  }
204  }
205  }
206  // ROS_INFO("inliers: %lu", inliers);
207  // ROS_INFO("error: %f", error);
208  size_t expected_num = p.volume() / config.expected_density / config.expected_density / config.expected_density;
209  // ROS_INFO("expected: %lu", expected_num);
210  if (inliers < config.min_inliers) {
211  return 0;
212  }
213  else {
214  double non_inlier_value = 1 / (1 + error / inliers);
215  if (config.use_inliers) {
216  // how to compute expected inliers...?
217  // double inliers_err = std::abs(p.volume() / config.expected_density - inliers);
218  // return non_inlier_value * (1 / (1 + pow(inliers_err, config.inliers_power)));
219  double inlier_likelihood = 1 / (1 + pow(expected_num - inliers, config.inliers_power));
220  // ROS_INFO("inlier likelihood: %f", inlier_likelihood);
221  return non_inlier_value * inlier_likelihood;
222  }
223  else {
224  return non_inlier_value;
225  }
226  }
227  }
228  }
229 
230  template <class Config>
232  const std::vector<float>& polygon_likelihood,
233  const Config& config)
234  {
235  if (config.use_polygon_likelihood) {
236  return polygon_likelihood[p.plane_index];
237  }
238  else {
239  return 1.0;
240  }
241  }
242 
243  template <class Config>
245  pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud,
246  pcl::KdTreeFLANN<pcl::PointXYZ>& tree,
247  const Eigen::Vector3f& viewpoint,
248  const std::vector<Polygon::Ptr>& polygons,
249  const std::vector<float>& polygon_likelihood,
250  const Config& config)
251  {
252  double range_likelihood = 1.0;
253  if (config.use_range_likelihood) {
254  range_likelihood = rangeLikelihood(p, cloud, polygons, config);
255  }
256  //p.weight = std::abs(p.z);
257  if (range_likelihood == 0.0) {
258  return range_likelihood;
259  }
260  else {
261  return (range_likelihood * distanceFromPlaneBasedError(p, cloud, tree, viewpoint, config)
262  * supportPlaneAngularLikelihood(p, polygons, config)
263  * surfaceAreaLikelihood(p, config)
264  * planeLikelihood(p, polygon_likelihood, config));
265  }
266  }
267 
269  {
270  public:
272  typedef pcl::PointCloud<Particle> ParticleCloud;
274  typedef PlaneSupportedCuboidEstimatorConfig Config;
276  jsk_recognition_msgs::PolygonArray,
277  jsk_recognition_msgs::ModelCoefficientsArray> PolygonSyncPolicy;
278 
279  PlaneSupportedCuboidEstimator(): DiagnosticNodelet("PlaneSupportedCuboidEstimator") {}
280 
281  protected:
282  virtual void onInit();
283  virtual void subscribe();
284  virtual void unsubscribe();
285  virtual void polygonCallback(
286  const jsk_recognition_msgs::PolygonArray::ConstPtr& polygon_msg,
287  const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr& coef_msg);
288  virtual void cloudCallback(
289  const sensor_msgs::PointCloud2::ConstPtr& msg);
290  virtual void estimate(
291  const sensor_msgs::PointCloud2::ConstPtr& msg);
292  virtual void fastCloudCallback(
293  const sensor_msgs::PointCloud2::ConstPtr& msg);
294  virtual pcl::PointCloud<pcl::tracking::ParticleCuboid>::Ptr initParticles();
295  virtual size_t chooseUniformRandomPlaneIndex(const std::vector<Polygon::Ptr>& polygons);
296  virtual void configCallback(Config& config, uint32_t level);
297 
298  // For particle filtering
300  // Likelihood
301  virtual void likelihood(pcl::PointCloud<pcl::PointXYZ>::ConstPtr input,
303  virtual void publishHistogram(ParticleCloud::Ptr particles, int index,
305  const std_msgs::Header& header);
306  virtual bool resetCallback(std_srvs::EmptyRequest& req,
307  std_srvs::EmptyResponse& res);
308 
313  virtual size_t getNearestPolygon(
314  const Particle& p,
315  const std::vector<jsk_recognition_utils::ConvexPolygon::Ptr>& polygons);
323  virtual void updateParticlePolygonRelationship(ParticleCloud::Ptr particles);
344  jsk_recognition_msgs::PolygonArray::ConstPtr latest_polygon_msg_;
345  jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr latest_coefficients_msg_;
346  pcl::PointCloud<pcl::PointXYZ>::Ptr candidate_cloud_;
348  // Parameters for initialization of particles
349  // local position z is sampled by uniform distribution
350  Config config_;
365 
368 
375 
385 
386  double min_dx_;
387  double min_dy_;
388  double min_dz_;
392  std::string sensor_frame_;
393  boost::mt19937 random_generator_;
395  Eigen::Vector3f viewpoint_;
398  std::vector<Polygon::Ptr> polygons_;
399  pcl::KdTreeFLANN<pcl::PointXYZ> tree_;
400  private:
401  };
402 }
403 
404 #endif
d
message_filters::Subscriber< jsk_recognition_msgs::PolygonArray > sub_polygon_
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
double min(const OneDataStat &d)
wrapper function for min method for boost::function
Definition: one_data_stat.h:94
virtual void estimate(const sensor_msgs::PointCloud2::ConstPtr &msg)
boost::shared_ptr< message_filters::Synchronizer< PolygonSyncPolicy > > sync_polygon_
virtual size_t getNearestPolygon(const Particle &p, const std::vector< jsk_recognition_utils::ConvexPolygon::Ptr > &polygons)
Compute the nearest polygon to the particle `p&#39;.
double surfaceAreaLikelihood(const pcl::tracking::ParticleCuboid &p, const Config &config)
double max(const OneDataStat &d)
wrapper function for max method for boost::function
GLint faces[6][4]
virtual void configCallback(Config &config, uint32_t level)
config
virtual void updateParticlePolygonRelationship(ParticleCloud::Ptr particles)
Compute distances between particles and polygons and assing each particle to the nearest polygon...
double rangeLikelihood(const pcl::tracking::ParticleCuboid &p, pcl::PointCloud< pcl::PointXYZ >::ConstPtr cloud, const std::vector< Polygon::Ptr > &planes, const Config &config)
jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr latest_coefficients_msg_
Eigen::Affine3f toEigenMatrix() const
jsk_pcl_ros::Cube::Ptr toCube() const
T dot(T *pf1, T *pf2, int length)
message_filters::sync_policies::ExactTime< jsk_recognition_msgs::PolygonArray, jsk_recognition_msgs::ModelCoefficientsArray > PolygonSyncPolicy
pose
virtual void publishHistogram(ParticleCloud::Ptr particles, int index, ros::Publisher &pub, const std_msgs::Header &header)
virtual size_t chooseUniformRandomPlaneIndex(const std::vector< Polygon::Ptr > &polygons)
virtual void fastCloudCallback(const sensor_msgs::PointCloud2::ConstPtr &msg)
std::vector< int > visibleFaceIndices(const Eigen::Vector3f local_view_point) const
pcl::PointCloud< pcl::PointXYZ >::Ptr candidate_cloud_
double binaryLikelihood(double v, double min, double max)
return 1.0 if v satisfies min < v < max, return 0 otherwise.
DiagnosticNodelet(const std::string &name)
unsigned int index
double signedDistanceToPlane(const Eigen::Vector3f &v, const int plane_index) const
double sqrt()
virtual void polygonCallback(const jsk_recognition_msgs::PolygonArray::ConstPtr &polygon_msg, const jsk_recognition_msgs::ModelCoefficientsArray::ConstPtr &coef_msg)
virtual void likelihood(pcl::PointCloud< pcl::PointXYZ >::ConstPtr input, pcl::tracking::ParticleCuboid &p)
jsk_recognition_msgs::PolygonArray::ConstPtr polygon_msg
likelihood
virtual pcl::PointCloud< pcl::tracking::ParticleCuboid >::Ptr initParticles()
pcl::tracking::ROSCollaborativeParticleFilterTracker< pcl::PointXYZ, pcl::tracking::ParticleCuboid >::Ptr tracker_
boost::shared_ptr< PlaneSupportedCuboidEstimator > Ptr
pointer error(enum errorcode ec,...) pointer error(va_alist) va_dcl
boost::mutex mutex
global mutex.
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
virtual pcl::tracking::ParticleCuboid sample(const pcl::tracking::ParticleCuboid &p)
jsk_recognition_msgs::PolygonArray::ConstPtr latest_polygon_msg_
double computeLikelihood(const pcl::tracking::ParticleCuboid &p, pcl::PointCloud< pcl::PointXYZ >::ConstPtr cloud, pcl::KdTreeFLANN< pcl::PointXYZ > &tree, const Eigen::Vector3f &viewpoint, const std::vector< Polygon::Ptr > &polygons, const std::vector< float > &polygon_likelihood, const Config &config)
virtual bool resetCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
p
virtual void cloudCallback(const sensor_msgs::PointCloud2::ConstPtr &msg)
int nearestPlaneIndex(const Eigen::Vector3f &local_v) const
GLfloat v[8][3]
message_filters::Subscriber< jsk_recognition_msgs::ModelCoefficientsArray > sub_coefficients_
double distanceNearestToPlaneWithOcclusion(const Eigen::Vector3f &v, const std::vector< int > &visible_faces, std::vector< jsk_pcl_ros::Polygon::Ptr > &faces) const
double supportPlaneAngularLikelihood(const pcl::tracking::ParticleCuboid &p, const std::vector< Polygon::Ptr > &planes, const Config &config)
double planeLikelihood(const pcl::tracking::ParticleCuboid &p, const std::vector< float > &polygon_likelihood, const Config &config)
Cube cube(Eigen::Vector3f(1, 0, 0), Eigen::Quaternionf(0.108755, 0.088921, 0.108755, 0.984092), Eigen::Vector3f(0.3, 0.3, 0.3))
double distanceFromPlaneBasedError(const pcl::tracking::ParticleCuboid &p, pcl::PointCloud< pcl::PointXYZ >::ConstPtr cloud, pcl::KdTreeFLANN< pcl::PointXYZ > &tree, const Eigen::Vector3f &viewpoint, const Config &config)
polygons


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:47