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
00039 #include <laser_slam/scan_intersection.h>
00040 #include <boost/foreach.hpp>
00041 #include <boost/optional.hpp>
00042 #include <ros/assert.h>
00043
00044 namespace laser_slam
00045 {
00046
00047 using std::vector;
00048 using boost::optional;
00049 typedef vector<btTransform> Scans;
00050
00051 inline
00052 double pointToLineSegment (const btVector3& p, const btVector3& p1,
00053 const btVector3& p2)
00054 {
00055 const double dx = p.x() - p1.x();
00056 const double dy = p.y() - p1.y();
00057 const double dx1 = p2.x() - p1.x();
00058 const double dy1 = p2.y() - p1.y();
00059
00060 return fabs(dx*dy1-dy*dx1)/sqrt(dx1*dx1+dy1*dy1);
00061 }
00062
00063
00064
00065
00066
00067
00068 double ScanIntersection::unseenProportion (const btTransform& scan,
00069 const Scans& scans) const
00070 {
00071 unsigned unseen=0;
00072 BOOST_FOREACH (const btVector3& pt, grid_) {
00073 const btVector3 p = scan*pt;
00074 bool found=false;
00075 BOOST_FOREACH (const btTransform& ref, scans) {
00076 if (contains(ref, p)) {
00077 found=true;
00078 break;
00079 }
00080 }
00081 if (!found)
00082 unseen++;
00083 }
00084 return (double)unseen/(double)grid_.size();
00085 }
00086
00087
00088 ScanIntersection::ScanIntersection (const ScanIntersection& i) :
00089 poly_(i.poly_), grid_(i.grid_), center_(i.center_),
00090 inradius2_(i.inradius2_), circumradius2_(i.circumradius2_)
00091 {
00092
00093
00094 }
00095
00096 ScanIntersection::ScanIntersection (vector<btVector3> poly,
00097 const unsigned grid_size) :
00098 poly_(poly)
00099 {
00100
00101 ROS_ASSERT_MSG (poly[0].distance(btVector3(0,0,0))<1e-6,
00102 "First point of polygon %.2f, %.2f, %.2f wasn't origin",
00103 poly[0].x(), poly[0].y(), poly[0].z());
00104
00105
00106 using std::min;
00107 using std::max;
00108 double sx=0, sy=0;
00109 optional<double> min_x, min_y, max_x, max_y;
00110 BOOST_FOREACH (const btVector3& p, poly) {
00111 sx += p.x();
00112 sy += p.y();
00113 if (!min_x || p.x()<*min_x)
00114 min_x = p.x();
00115 if (!max_x || p.x()>*max_x)
00116 max_x = p.x();
00117 if (!min_y || p.y()<*min_y)
00118 min_y = p.y();
00119 if (!max_y || p.y()>*max_y)
00120 max_y = p.y();
00121 }
00122 center_.setX(sx/poly.size());
00123 center_.setY(sy/poly.size());
00124
00125
00126 boost::optional<double> inradius, circumradius;
00127
00128 for (int i=0; i<(int)poly.size(); i++) {
00129 int j = i==0 ? poly.size()-1 : i-1;
00130 const double ri = pointToLineSegment(center_, poly[j], poly[i]);
00131 if (!inradius || ri<*inradius)
00132 inradius = ri;
00133 const double rc = center_.distance(poly[i]);
00134 if (!circumradius || rc > *circumradius)
00135 circumradius = rc;
00136 ROS_ASSERT_MSG (ri < rc, "Polygon is not convex!");
00137 }
00138 inradius2_ = (*inradius) * (*inradius);
00139 circumradius2_ = (*circumradius) * (*circumradius);
00140
00141
00142
00143 const double x_step = (*max_x - *min_x)/sqrt(grid_size);
00144 const double y_step = (*max_y - *min_y)/sqrt(grid_size);
00145
00146 btTransform id;
00147 id.setIdentity();
00148 for (double x=*min_x; x<*max_x; x+=x_step)
00149 {
00150 for (double y=*min_y; y<*max_y; y+=y_step)
00151 {
00152 const btVector3 p(x,y,0);
00153 if (contains(id, p))
00154 grid_.push_back(btVector3(x,y,0));
00155 }
00156 }
00157
00158 }
00159
00160
00161
00162
00163 }