kinect_filtering.cpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2008, Willow Garage, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * * Neither the name of the Willow Garage, Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 
32 
33 
34 //#include <ros/ros.h>
35 #include <Eigen/Core>
37 #include <tf/tf.h>
38 #include <tf/transform_datatypes.h>
39 
40 
41 namespace ar_track_alvar
42 {
43 
44  namespace gm=geometry_msgs;
45 
46  using std::vector;
47  using std::cerr;
48  using std::endl;
49  using std::ostream;
50 
51  // Distance threshold for plane fitting: how far are points
52  // allowed to be off the plane?
53  const double distance_threshold_ = 0.005;
54 
55  PlaneFitResult fitPlane (ARCloud::ConstPtr cloud)
56  {
58  pcl::PointIndices::Ptr inliers=boost::make_shared<pcl::PointIndices>();
59 
60  pcl::SACSegmentation<ARPoint> seg;
61  seg.setOptimizeCoefficients(true);
62  seg.setModelType(pcl::SACMODEL_PLANE);
63  seg.setMethodType(pcl::SAC_RANSAC);
64  seg.setDistanceThreshold(distance_threshold_);
65 
66  seg.setInputCloud(cloud);
67  seg.segment(*inliers, res.coeffs);
68 
69  pcl::ExtractIndices<ARPoint> extracter;
70  extracter.setInputCloud(cloud);
71  extracter.setIndices(inliers);
72  extracter.setNegative(false);
73  extracter.filter(*res.inliers);
74 
75  return res;
76  }
77 
78  ARCloud::Ptr filterCloud (const ARCloud& cloud, const vector<cv::Point, Eigen::aligned_allocator<cv::Point> >& pixels)
79  {
80  ARCloud::Ptr out(new ARCloud());
81  //ROS_INFO(" Filtering %zu pixels", pixels.size());
82  //for (const cv::Point& p : pixels)
83  for(size_t i=0; i<pixels.size(); i++)
84  {
85  const cv::Point& p = pixels[i];
86  const ARPoint& pt = cloud(p.x, p.y);
87  if (std::isnan(pt.x) || std::isnan(pt.y) || std::isnan(pt.z)){
88  //ROS_INFO(" Skipping (%.4f, %.4f, %.4f)", pt.x, pt.y, pt.z);
89  }
90  else
91  out->points.push_back(pt);
92  }
93  return out;
94  }
95 
96  gm::Point centroid (const ARCloud& points)
97  {
98  gm::Point sum;
99  sum.x = 0;
100  sum.y = 0;
101  sum.z = 0;
102  //for (const Point& p : points)
103  for(size_t i=0; i<points.size(); i++)
104  {
105  sum.x += points[i].x;
106  sum.y += points[i].y;
107  sum.z += points[i].z;
108  }
109 
110  gm::Point center;
111  const size_t n = points.size();
112  center.x = sum.x/n;
113  center.y = sum.y/n;
114  center.z = sum.z/n;
115  return center;
116  }
117 
118  // Helper function to construct a geometry_msgs::Quaternion
119  inline
120  gm::Quaternion makeQuaternion (double x, double y, double z, double w)
121  {
122  gm::Quaternion q;
123  q.x = x;
124  q.y = y;
125  q.z = z;
126  q.w = w;
127  return q;
128  }
129 
130  // Extract and normalize plane coefficients
131  int getCoeffs (const pcl::ModelCoefficients& coeffs, double* a, double* b,
132  double* c, double* d)
133  {
134  if(coeffs.values.size() != 4)
135  return -1;
136  const double s = coeffs.values[0]*coeffs.values[0] +
137  coeffs.values[1]*coeffs.values[1] + coeffs.values[2]*coeffs.values[2];
138  if(fabs(s) < 1e-6)
139  return -1;
140  *a = coeffs.values[0]/s;
141  *b = coeffs.values[1]/s;
142  *c = coeffs.values[2]/s;
143  *d = coeffs.values[3]/s;
144  return 0;
145  }
146 
147  // Project point onto plane
148  tf::Vector3 project (const ARPoint& p, const double a, const double b,
149  const double c, const double d)
150  {
151  const double t = a*p.x + b*p.y + c*p.z + d;
152  return tf::Vector3(p.x-t*a, p.y-t*b, p.z-t*c);
153  }
154 
155  ostream& operator<< (ostream& str, const tf::Matrix3x3& m)
156  {
157  str << "[" << m[0][0] << ", " << m[0][1] << ", " << m[0][2] << "; "
158  << m[1][0] << ", " << m[1][1] << ", " << m[1][2] << "; "
159  << m[2][0] << ", " << m[2][1] << ", " << m[2][2] << "]";
160  return str;
161  }
162 
163  ostream& operator<< (ostream& str, const tf::Quaternion& q)
164  {
165  str << "[(" << q.x() << ", " << q.y() << ", " << q.z() <<
166  "), " << q.w() << "]";
167  return str;
168  }
169 
170  ostream& operator<< (ostream& str, const tf::Vector3& v)
171  {
172  str << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
173  return str;
174  }
175 
176  int extractFrame (const pcl::ModelCoefficients& coeffs,
177  const ARPoint& p1, const ARPoint& p2,
178  const ARPoint& p3, const ARPoint& p4,
179  tf::Matrix3x3 &retmat)
180  {
181  // Get plane coeffs and project points onto the plane
182  double a=0, b=0, c=0, d=0;
183  if(getCoeffs(coeffs, &a, &b, &c, &d) < 0)
184  return -1;
185 
186  const tf::Vector3 q1 = project(p1, a, b, c, d);
187  const tf::Vector3 q2 = project(p2, a, b, c, d);
188  const tf::Vector3 q3 = project(p3, a, b, c, d);
189  const tf::Vector3 q4 = project(p4, a, b, c, d);
190 
191  // Make sure points aren't the same so things are well-defined
192  if((q2-q1).length() < 1e-3)
193  return -1;
194 
195  // (inverse) matrix with the given properties
196  const tf::Vector3 v = (q2-q1).normalized();
197  const tf::Vector3 n(a, b, c);
198  const tf::Vector3 w = -v.cross(n);
199  tf::Matrix3x3 m(v[0], v[1], v[2], w[0], w[1], w[2], n[0], n[1], n[2]);
200 
201  // Possibly flip things based on third point
202  const tf::Vector3 diff = (q4-q3).normalized();
203  //ROS_INFO_STREAM("w = " << w << " and d = " << diff);
204  if (w.dot(diff)<0)
205  {
206  //ROS_INFO_STREAM("Flipping normal based on p3. Current value: " << m);
207  m[1] = -m[1];
208  m[2] = -m[2];
209  //ROS_INFO_STREAM("New value: " << m);
210  }
211 
212  // Invert and return
213  retmat = m.inverse();
214  //cerr << "Frame is " << retmat << endl;
215  return 0;
216  }
217 
218 
220  {
221  if(m.determinant() <= 0)
222  return -1;
223 
224  //tfScalar y=0, p=0, r=0;
225  //m.getEulerZYX(y, p, r);
226  //retQ.setEulerZYX(y, p, r);
227 
228  //Use Eigen for this part instead, because the ROS version of bullet appears to have a bug
229  Eigen::Matrix3f eig_m;
230  for(int i=0; i<3; i++){
231  for(int j=0; j<3; j++){
232  eig_m(i,j) = m[i][j];
233  }
234  }
235  Eigen::Quaternion<float> eig_quat(eig_m);
236 
237  // Translate back to bullet
238  tfScalar ex = eig_quat.x();
239  tfScalar ey = eig_quat.y();
240  tfScalar ez = eig_quat.z();
241  tfScalar ew = eig_quat.w();
242  tf::Quaternion quat(ex,ey,ez,ew);
243  retQ = quat.normalized();
244 
245  return 0;
246  }
247 
248 
249  int extractOrientation (const pcl::ModelCoefficients& coeffs,
250  const ARPoint& p1, const ARPoint& p2,
251  const ARPoint& p3, const ARPoint& p4,
252  gm::Quaternion &retQ)
253  {
254  tf::Matrix3x3 m;
255  if(extractFrame(coeffs, p1, p2, p3, p4, m) < 0)
256  return -1;
257  tf::Quaternion q;
258  if(getQuaternion(m,q) < 0)
259  return -1;
260  retQ.x = q.x();
261  retQ.y = q.y();
262  retQ.z = q.z();
263  retQ.w = q.w();
264  return 0;
265  }
266 
267 } // namespace
pcl::PointXYZRGB ARPoint
pcl::PointCloud< ARPoint > ARCloud
double tfScalar
int extractOrientation(const pcl::ModelCoefficients &coeffs, const ARPoint &p1, const ARPoint &p2, const ARPoint &p3, const ARPoint &p4, geometry_msgs::Quaternion &retQ)
XmlRpcServer s
ARCloud::Ptr filterCloud(const ARCloud &cloud, const std::vector< cv::Point, Eigen::aligned_allocator< cv::Point > > &pixels)
Matrix3x3 inverse() const
int getQuaternion(const tf::Matrix3x3 &m, tf::Quaternion &retQ)
TFSIMD_FORCE_INLINE Vector3 cross(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE Vector3 normalized() const
TFSIMD_FORCE_INLINE tfScalar dot(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & z() const
int getCoeffs(const pcl::ModelCoefficients &coeffs, double *a, double *b, double *c, double *d)
tf::Vector3 project(const ARPoint &p, const double a, const double b, const double c, const double d)
geometry_msgs::Point centroid(const ARCloud &points)
ostream & operator<<(ostream &str, const tf::Matrix3x3 &m)
TFSIMD_FORCE_INLINE const tfScalar & y() const
Drawable d[32]
TFSIMD_FORCE_INLINE const tfScalar & w() const
gm::Quaternion makeQuaternion(double x, double y, double z, double w)
const double distance_threshold_
tfScalar determinant() const
int extractFrame(const pcl::ModelCoefficients &coeffs, const ARPoint &p1, const ARPoint &p2, const ARPoint &p3, const ARPoint &p4, tf::Matrix3x3 &retmat)
pcl::ModelCoefficients coeffs
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
const int res
PlaneFitResult fitPlane(ARCloud::ConstPtr cloud)
Quaternion normalized() const
int ALVAR_EXPORT diff(const std::vector< C > &v, std::vector< C > &ret)
Calculates the difference between the consecutive vector elements.
Definition: Util.h:192


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:04