00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00040 #include <ros/ros.h>
00041 #include <ar_track_alvar/kinect_filtering.h>
00042 #include <tf/transform_datatypes.h>
00043 #include <Eigen/Core>
00044
00045 namespace ar_track_alvar
00046 {
00047
00048 namespace gm=geometry_msgs;
00049
00050 using std::vector;
00051 using std::cerr;
00052 using std::endl;
00053 using std::ostream;
00054
00055
00056
00057 const double distance_threshold_ = 0.005;
00058
00059 PlaneFitResult fitPlane (ARCloud::ConstPtr cloud)
00060 {
00061 PlaneFitResult res;
00062 pcl::PointIndices::Ptr inliers=boost::make_shared<pcl::PointIndices>();
00063
00064 pcl::SACSegmentation<ARPoint> seg;
00065 seg.setOptimizeCoefficients(true);
00066 seg.setModelType(pcl::SACMODEL_PLANE);
00067 seg.setMethodType(pcl::SAC_RANSAC);
00068 seg.setDistanceThreshold(distance_threshold_);
00069
00070 seg.setInputCloud(cloud);
00071 seg.segment(*inliers, res.coeffs);
00072
00073 pcl::ExtractIndices<ARPoint> extracter;
00074 extracter.setInputCloud(cloud);
00075 extracter.setIndices(inliers);
00076 extracter.setNegative(false);
00077 extracter.filter(*res.inliers);
00078
00079 return res;
00080 }
00081
00082 ARCloud::Ptr filterCloud (const ARCloud& cloud, const vector<cv::Point>& pixels)
00083 {
00084 ARCloud::Ptr out(new ARCloud());
00085
00086
00087 for(size_t i=0; i<pixels.size(); i++)
00088 {
00089 const cv::Point& p = pixels[i];
00090 const ARPoint& pt = cloud(p.x, p.y);
00091 if (isnan(pt.x) || isnan(pt.y) || isnan(pt.z)){
00092
00093 }
00094 else
00095 out->points.push_back(pt);
00096 }
00097 return out;
00098 }
00099
00100 gm::Point centroid (const ARCloud& points)
00101 {
00102 gm::Point sum;
00103 sum.x = 0;
00104 sum.y = 0;
00105 sum.z = 0;
00106
00107 for(size_t i=0; i<points.size(); i++)
00108 {
00109 sum.x += points[i].x;
00110 sum.y += points[i].y;
00111 sum.z += points[i].z;
00112 }
00113
00114 gm::Point center;
00115 const size_t n = points.size();
00116 center.x = sum.x/n;
00117 center.y = sum.y/n;
00118 center.z = sum.z/n;
00119 return center;
00120 }
00121
00122
00123 inline
00124 gm::Quaternion makeQuaternion (double x, double y, double z, double w)
00125 {
00126 gm::Quaternion q;
00127 q.x = x;
00128 q.y = y;
00129 q.z = z;
00130 q.w = w;
00131 return q;
00132 }
00133
00134
00135 int getCoeffs (const pcl::ModelCoefficients& coeffs, double* a, double* b,
00136 double* c, double* d)
00137 {
00138 if(coeffs.values.size() != 4)
00139 return -1;
00140 const double s = coeffs.values[0]*coeffs.values[0] +
00141 coeffs.values[1]*coeffs.values[1] + coeffs.values[2]*coeffs.values[2];
00142 if(fabs(s) < 1e-6)
00143 return -1;
00144 *a = coeffs.values[0]/s;
00145 *b = coeffs.values[1]/s;
00146 *c = coeffs.values[2]/s;
00147 *d = coeffs.values[3]/s;
00148 return 0;
00149 }
00150
00151
00152 btVector3 project (const ARPoint& p, const double a, const double b,
00153 const double c, const double d)
00154 {
00155 const double t = a*p.x + b*p.y + c*p.z + d;
00156 return btVector3(p.x-t*a, p.y-t*b, p.z-t*c);
00157 }
00158
00159 ostream& operator<< (ostream& str, const btMatrix3x3& m)
00160 {
00161 str << "[" << m[0][0] << ", " << m[0][1] << ", " << m[0][2] << "; "
00162 << m[1][0] << ", " << m[1][1] << ", " << m[1][2] << "; "
00163 << m[2][0] << ", " << m[2][1] << ", " << m[2][2] << "]";
00164 return str;
00165 }
00166
00167 ostream& operator<< (ostream& str, const btQuaternion& q)
00168 {
00169 str << "[(" << q.x() << ", " << q.y() << ", " << q.z() <<
00170 "), " << q.w() << "]";
00171 return str;
00172 }
00173
00174 ostream& operator<< (ostream& str, const btVector3& v)
00175 {
00176 str << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
00177 return str;
00178 }
00179
00180 int extractFrame (const pcl::ModelCoefficients& coeffs,
00181 const ARPoint& p1, const ARPoint& p2,
00182 const ARPoint& p3, const ARPoint& p4,
00183 btMatrix3x3 &retmat)
00184 {
00185
00186 double a=0, b=0, c=0, d=0;
00187 if(getCoeffs(coeffs, &a, &b, &c, &d) < 0)
00188 return -1;
00189
00190 const btVector3 q1 = project(p1, a, b, c, d);
00191 const btVector3 q2 = project(p2, a, b, c, d);
00192 const btVector3 q3 = project(p3, a, b, c, d);
00193 const btVector3 q4 = project(p4, a, b, c, d);
00194
00195
00196 if((q2-q1).length() < 1e-3)
00197 return -1;
00198
00199
00200 const btVector3 v = (q2-q1).normalized();
00201 const btVector3 n(a, b, c);
00202 const btVector3 w = -v.cross(n);
00203 btMatrix3x3 m(v[0], v[1], v[2], w[0], w[1], w[2], n[0], n[1], n[2]);
00204
00205
00206 const btVector3 diff = (q4-q3).normalized();
00207
00208 if (w.dot(diff)<0)
00209 {
00210
00211 m[1] = -m[1];
00212 m[2] = -m[2];
00213
00214 }
00215
00216
00217 retmat = m.inverse();
00218
00219 return 0;
00220 }
00221
00222
00223 int getQuaternion (const btMatrix3x3& m, btQuaternion &retQ)
00224 {
00225 if(m.determinant() <= 0)
00226 return -1;
00227
00228
00229
00230
00231
00232
00233 Eigen::Matrix3f eig_m;
00234 for(int i=0; i<3; i++){
00235 for(int j=0; j<3; j++){
00236 eig_m(i,j) = m[i][j];
00237 }
00238 }
00239 Eigen::Quaternion<float> eig_quat(eig_m);
00240
00241
00242 btScalar ex = eig_quat.x();
00243 btScalar ey = eig_quat.y();
00244 btScalar ez = eig_quat.z();
00245 btScalar ew = eig_quat.w();
00246 btQuaternion quat(ex,ey,ez,ew);
00247 retQ = quat.normalized();
00248
00249 return 0;
00250 }
00251
00252
00253 int extractOrientation (const pcl::ModelCoefficients& coeffs,
00254 const ARPoint& p1, const ARPoint& p2,
00255 const ARPoint& p3, const ARPoint& p4,
00256 gm::Quaternion &retQ)
00257 {
00258 btMatrix3x3 m;
00259 if(extractFrame(coeffs, p1, p2, p3, p4, m) < 0)
00260 return -1;
00261 btQuaternion q;
00262 if(getQuaternion(m,q) < 0)
00263 return -1;
00264 tf::quaternionTFToMsg(q, retQ);
00265 return 0;
00266 }
00267
00268 }