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 #include "v4r_laser_filter/v4r_laser_filter_utils.h"
00032
00033 #include <fstream>
00034 #include <boost/foreach.hpp>
00035 using namespace LaserFilter;
00036
00037
00038
00039 Pose::Pose() {};
00040 Pose::Pose(float _x, float _y, float _angle): cv::Vec3f(_x, _y, _angle) {};
00041 void Pose::set( float _x, float _y, float _angle) {
00042 val[0] = _x, val[1] = _y, val[2] = _angle;
00043 }
00044 const cv::Point2f& Pose::point() const {
00045 return *((cv::Point2f*) val);
00046 }
00047 cv::Point2f& Pose::point() {
00048 return *((cv::Point2f*) val);
00049 }
00050 const float& Pose::x() const {
00051 return val[0];
00052 };
00053 float& Pose::x() {
00054 return val[0];;
00055 };
00056 const float& Pose::y() const {
00057 return val[1];
00058 };
00059 float& Pose::y() {
00060 return val[1];;
00061 };
00062 const float& Pose::angle() const {
00063 return val[2];
00064 };
00065 float& Pose::angle() {
00066 return val[2];
00067 };
00068 void Pose::normalizeAngle() {
00069 while(val[2] > M_PI) val[2] -= 2*M_PI;
00070 while(val[2] < -M_PI) val[2] += 2*M_PI;
00071 }
00072
00073
00074
00075
00076 Beam::Beam() {};
00077 void Beam::set(float _alpha, float _range) {
00078 alpha = _alpha, range = _range;
00079 }
00080
00081
00082
00083
00084 LineEq::LineEq() {};
00085
00086 LineEq::LineEq(const cv::Vec3f& l)
00087 :cv::Vec3f(l) {};
00088
00089 LineEq::LineEq(float _a, float _b, float _c)
00090 : cv::Vec3f(_a, _b, _c) {};
00091
00092 void LineEq::set(const cv::Point2f &p0, const cv::Point2f &p1) {
00093 val[0] = +(p0.y * 1. - 1. * p1.y);
00094 val[1] = -(p0.x * 1. - 1. * p1.x);
00095 val[2] = +(p0.x * p1.y - p0.y * p1.x);
00096 float r = sqrt( val[0]* val[0]+ val[1]* val[1]);
00097 val[0] = val[0] / r, val[1] = val[1] / r, val[2] = val[2] / r;
00098 }
00099 float LineEq::distance(const cv::Point2f &p) const {
00100 return LaserFilter::dot(*this, p);
00101 }
00102
00103
00104
00105
00106
00107 Line::Line()
00108 :LineEq() {};
00109 Line::Line(const cv::Vec3f& l)
00110 :LineEq(l) {};
00111 Line::Line(const Line& l)
00112 :LineEq(l), p0(l.p0), p1(l.p1) {};
00113 Line::Line(const cv::Point2f &_p0, const cv::Point2f &_p1) {
00114 set(_p0,_p1);
00115 };
00116 void Line::set(const cv::Point2f &_p0, const cv::Point2f &_p1) {
00117 p0 = _p0, p1 = _p1;
00118 computeEquation();
00119 }
00120 void Line::computeEquation() {
00121 LineEq::set(p0, p1);
00122 }
00123 float Line::angle() const {
00124 cv::Vec2f v = vector();
00125 return atan2(v[1], v[0]);
00126 }
00127 float Line::angleDiff(const Line &l) const {
00128 float a0 = this->angle();
00129 float a1 = l.angle();
00130 float angle_between_lines = atan2(sin(a1 - a0), cos(a1 - a0));
00131 return angle_between_lines;
00132 }
00133 float Line::length() const {
00134 return norm(vector());
00135 }
00136 cv::Vec2f Line::vector() const {
00137 return cv::Vec2f(p1.x-p0.x, p1.y-p0.y);
00138 }
00139
00140
00141
00142
00143 LineSegment::LineSegment()
00144 :Line(), id(0), idx(0,0) {}
00145 LineSegment::LineSegment(const cv::Vec3f& l)
00146 : Line(l), id(0), idx(0,0) {}
00147 LineSegment::LineSegment(const Line& l)
00148 : Line(l), id(0), idx(0,0) {}
00149 LineSegment::LineSegment(const LineSegment& l)
00150 : Line(l), id(l.id), idx(l.idx) {}
00151 LineSegment::LineSegment(unsigned int idx0, unsigned int idx1, const std::vector<Measurment> &measurments)
00152 : Line(measurments[idx0], measurments[idx1]), id(0), idx(idx0,idx1) {}
00153
00154 bool LineSegment::isSupportPoint(int i) {
00155 if( (i < idx.first) || (i > idx.second)) {
00156 return false;
00157 } else {
00158 return true;
00159 }
00160 }
00161 unsigned int LineSegment::nrSupportPoint() {
00162 return idx.second - idx.first + 1;
00163 }
00164 void LineSegment::set(unsigned int _idx0, unsigned int _idx1, const std::vector<Measurment> &measurments) {
00165 idx.first = _idx0, idx.second = _idx1;
00166 Line::set(measurments[idx.first], measurments[idx.second]);
00167 }
00168
00169 void LineSegment::updateLineStatistic(const std::vector<Measurment> &measurments) {
00170 float sum_mean = 0, sum_var = 0;
00171 for(unsigned int i = idx.first; i <= idx.second; i++) {
00172 float d = this->distance(measurments[i]);
00173 sum_mean += d;
00174 sum_var += d*d;
00175 }
00176 distances_mean = sum_mean / nrSupportPoint();
00177 distances_variance = sum_var / nrSupportPoint();
00178 distances_error = sqrt(distances_variance) / length();
00179 }
00180
00181
00182 void LineSegment::estimator_theilsen(const std::vector<Measurment> &measurments, Line &line) {
00183
00184 unsigned nrOfPoints = nrSupportPoint();
00185 if(nrSupportPoint() <= 3) return;
00186 float slopeYX, slopeXY, offset;
00187 std::vector<float> slopsXY, slopsYX, offsets;
00188 slopsYX.reserve(nrOfPoints);
00189 slopsXY.reserve(nrOfPoints);
00190 for(unsigned int i = idx.first; i <= idx.second; i++) {
00191 for(unsigned int j = i; j <= idx.second; j++) {
00192 if(i == j) continue;
00193 const cv::Point2f &pi = measurments[i];
00194 const cv::Point2f &pj = measurments[j];
00195 float dx = pi.x-pj.x;
00196 float dy = pi.y-pj.y;
00197 if(fabs(dx) > FLT_MIN) {
00198 float s = dy/dx;
00199 slopsYX.push_back(s);
00200 }
00201 if(fabs(dy) > FLT_MIN) {
00202 float s = dx/dy;
00203 slopsXY.push_back(s);
00204 }
00205 }
00206 }
00207 std::sort(slopsYX.begin(), slopsYX.end());
00208 slopeYX = slopsYX[ (slopsYX.size() % 2?slopsYX.size() / 2:slopsYX.size()/2 - 1) ];
00209 std::sort(slopsXY.begin(), slopsXY.end());
00210 slopeXY = slopsXY[ (slopsXY.size() % 2?slopsXY.size() / 2:slopsXY.size()/2 - 1) ];
00211
00212 offsets.reserve(nrOfPoints);
00213 if(fabs(slopeYX) < 1.0) {
00214
00215 for(unsigned int i = idx.first; i <= idx.second; i++) {
00216 const cv::Point2f &p = measurments[i];
00217 offsets.push_back(p.y - slopeYX*p.x);
00218 }
00219
00220 std::sort(offsets.begin(), offsets.end());
00221 offset = offsets[offsets.size()/2];
00222 if ((offsets.size() % 2) == 0) {
00223 offset = (offset + offsets[offsets.size()/2 - 1]) / 2.;
00224 } else {
00225
00226 }
00227 line.p0.x = measurments[idx.first].x;
00228 line.p1.x = measurments[idx.second].x;
00229 line.p0.y = slopeYX * line.p0.x + offset;
00230 line.p1.y = slopeYX * line.p1.x + offset;
00231 line.computeEquation();
00232 } else {
00233 for(unsigned int i = idx.first; i <= idx.second; i++) {
00234 const cv::Point2f &p = measurments[i];
00235 offsets.push_back(p.x - slopeXY*p.y);
00236 }
00237
00238 std::sort(offsets.begin(), offsets.end());
00239 offset = offsets[offsets.size()/2];
00240 if ((offsets.size() % 2) == 0) {
00241 offset = (offset + offsets[offsets.size()/2 - 1]) / 2.;
00242 } else {
00243
00244 }
00245 line.p0.y = measurments[idx.first].y;
00246 line.p1.y = measurments[idx.second].y;
00247 line.p0.x = slopeXY * line.p0.y + offset;
00248 line.p1.x = slopeXY * line.p1.y + offset;
00249 line.computeEquation();
00250 }
00251 }
00252
00253
00254
00255
00256
00257 void Measurment::set(float _alpha, float _range) {
00258 nan = isnan(_range), inf = isinf(_range);
00259 if(nan || inf) {
00260 valid = false;
00261 } else {
00262 x = cos(_alpha) * _range;
00263 y = sin(_alpha) * _range;
00264 valid = true;
00265 }
00266 }
00267
00268
00269
00270
00271 Corner::Corner()
00272 : error(FLT_MAX) {};
00273
00274 Corner::Corner(const Corner &c)
00275 : Pose(c), error(c.error), l0(c.l0), l1(c.l1) {};
00276
00277 void Corner::set(const LineSegment &_l0, const LineSegment &_l1) {
00278 l0 = _l0, l1 = _l1;
00279 intersection(l0, l1, point());
00280 float angle_between_lines = l0.angleDiff(l1);
00281 this->angle() = l0.angle() - angle_between_lines / 2;
00282 normalizeAngle();
00283 }
00284
00285 bool Corner::isCorner(float threshold_angle, float max_line_diff) {
00286 bool result = false;
00287 float line_diff;
00288 float angle_between_lines = l0.angleDiff(l1);
00289 if(fabs(fabs(angle_between_lines) - M_PI/2) < threshold_angle) {
00290 intersection(l0, l1, point());
00291 float n1 = l0.length();
00292 float n2 = l1.length();
00293 line_diff = ( n1>n2 ? n1/n2 : n2/n1);
00294 if(line_diff < max_line_diff) {
00295 result = true;
00296 }
00297 }
00298 return result;
00299 }
00300
00301 void Corner::redefine(const std::vector<Measurment> &measurments) {
00302 l0.estimator_theilsen(measurments, l0);
00303 l1.estimator_theilsen(measurments, l1);
00304 set(l0, l1);
00305 }
00306 float Corner::updateError(const std::vector<Measurment> &measurments){
00307 l0.updateLineStatistic(measurments);
00308 l1.updateLineStatistic(measurments);
00309 error = sqrt(l0.distances_error*l0.distances_error + l1.distances_error*l1.distances_error);
00310 return error;
00311 }
00312
00313
00314
00315
00316
00317
00318 void LaserFilter::copy(const sensor_msgs::LaserScan& _msg, std::vector<Measurment> &_desMeasurments, std::vector<Beam> &_desBeams) {
00319 unsigned int nrOfRanges = _msg.ranges.size();
00320 _desMeasurments.resize(nrOfRanges);
00321 _desBeams.resize(nrOfRanges);
00322 float angle_increment_ = _msg.angle_increment;
00323 float angle_increment_sin_ = sin(angle_increment_);
00324 for (int i = 0; i < nrOfRanges; i++) {
00325 const float &range = _msg.ranges[i];
00326 float alpha = _msg.angle_min + (_msg.angle_increment * i);
00327 _desBeams[i].set(alpha, range);
00328 _desMeasurments[i].set(alpha, range);
00329 }
00330 }
00331
00332 void LaserFilter::intersection(const cv::Vec3f &l1, const cv::Vec3f &l2, cv::Point2f &p) {
00333 cv::Vec3f c = l1.cross(l2);
00334 p.x = c[0] / c[2], p.y = c[1] / c[2];
00335 }
00336 float LaserFilter::dot(const cv::Vec3f &l1, const cv::Point2f &p) {
00337 return l1[0]*p.x+ l1[1]*p.y+ l1[2];
00338 }
00339
00340 void LaserFilter::readScan(const std::string &filename, sensor_msgs::LaserScan &msg ) {
00341
00342 std::ifstream ifs(filename.c_str(), std::ios::in|std::ios::binary);
00343 ifs.seekg (0, std::ios::end);
00344 std::streampos end = ifs.tellg();
00345 ifs.seekg (0, std::ios::beg);
00346 std::streampos begin = ifs.tellg();
00347
00348 uint32_t file_size = end-begin;
00349 boost::shared_array<uint8_t> ibuffer(new uint8_t[file_size]);
00350 ifs.read((char*) ibuffer.get(), file_size);
00351 ros::serialization::IStream istream(ibuffer.get(), file_size);
00352 ros::serialization::deserialize(istream, msg);
00353 ifs.close();
00354 }
00355 void LaserFilter::writeScan(const std::string &filename, const sensor_msgs::LaserScan &msg ) {
00356 std::ofstream ofs(filename.c_str(), std::ios::out|std::ios::binary);
00357
00358 uint32_t serial_size = ros::serialization::serializationLength(msg);
00359 boost::shared_array<uint8_t> obuffer(new uint8_t[serial_size]);
00360
00361 ros::serialization::OStream ostream(obuffer.get(), serial_size);
00362 ros::serialization::serialize(ostream, msg);
00363 ofs.write((char*) obuffer.get(), serial_size);
00364 ofs.close();
00365 }