soft_obstacle_detection.cpp
Go to the documentation of this file.
00001 #include <cmath>
00002 #include <limits>
00003 
00004 #include <Eigen/Core>
00005 #include <Eigen/Geometry>
00006 #include <Eigen/Dense>
00007 
00008 #include <pcl/point_cloud.h>
00009 #include <pcl_conversions/pcl_conversions.h>
00010 #include <pcl_ros/transforms.h>
00011 
00012 #include <sensor_msgs/PointCloud2.h>
00013 #include <hector_worldmodel_msgs/PosePercept.h>
00014 
00015 #include <hector_soft_obstacle_detection/soft_obstacle_detection.h>
00016 
00017 SoftObstacleDetection::SoftObstacleDetection()
00018 {
00019   ros::NodeHandle nh;
00020 
00021   unit_scale = 100.0;
00022   border_size = 10.0;
00023 
00024   // subscribe topics
00025   laser_scan_sub_ = nh.subscribe("/laser1/scan", 1, &SoftObstacleDetection::laserScanCallback, this);
00026 
00027   // advertise topics
00028   veil_percept_pub_ = nh.advertise<hector_worldmodel_msgs::PosePercept>("veil_percept", 20);
00029   veil_percept_pose_pub_ = nh.advertise<geometry_msgs::PoseStamped>("veil_percept_pose", 20);
00030   veil_point_cloud_pub_ = nh.advertise<sensor_msgs::PointCloud2>("veil_point_cloud", 5);
00031 
00032   // dynamic reconfigure
00033   dyn_rec_server_.setCallback(boost::bind(&SoftObstacleDetection::dynRecParamCallback, this, _1, _2));
00034 
00035   update_timer = nh.createTimer(ros::Duration(0.01), &SoftObstacleDetection::update, this);
00036 }
00037 
00038 SoftObstacleDetection::~SoftObstacleDetection()
00039 {
00040 }
00041 
00042 void SoftObstacleDetection::transformScanToImage(const sensor_msgs::LaserScanConstPtr scan, cv::Mat& img, cv::Point2i& scan_center) const
00043 {
00044   float min_x = std::numeric_limits<float>::max();
00045   float min_y = std::numeric_limits<float>::max();
00046   float max_x = std::numeric_limits<float>::min();
00047   float max_y = std::numeric_limits<float>::min();
00048 
00049   std::vector<cv::Point2f> points;
00050 
00051   // transform all points from polar coordinates into image coordinates
00052   for (unsigned int i = 0; i < scan->ranges.size(); i++)
00053   {
00054     if (!finite(scan->ranges[i]))
00055       continue;
00056 
00057     cv::Point2f p;
00058     float angle = scan->angle_max - scan->angle_increment*i;
00059     p.x = cos(angle) * scan->ranges[i]*unit_scale;
00060     p.y = sin(angle) * scan->ranges[i]*unit_scale;
00061 
00062     points.push_back(p);
00063 
00064     min_x = std::min(min_x, p.x);
00065     min_y = std::min(min_y, p.y);
00066     max_x = std::max(max_x, p.x);
00067     max_y = std::max(max_y, p.y);
00068   }
00069 
00070   if (points.empty())
00071     return;
00072 
00073   // generate image
00074   cv::Size img_size(max_x-min_x + 2*border_size, max_y-min_y + 2*border_size);
00075 
00076   if (img_size.width <= 2*border_size || img_size.height <= 2*border_size)
00077     return;
00078 
00079   scan_center.x = border_size - min_x;
00080   scan_center.y = border_size - min_y;
00081 
00082   img = cv::Mat(img_size, CV_8UC1);
00083   img = cv::Scalar::all(0);
00084 
00085   for (std::vector<cv::Point2f>::const_iterator itr = points.begin(); itr != points.end(); itr++)
00086     img.at<uchar>(std::floor(itr->y + scan_center.y), std::floor(itr->x + scan_center.x)) = 255;
00087 
00088   //cv::resize(img, img, cv::Size(400, 400));
00089 
00090 #ifdef DEBUG
00091   cv::imshow("scan", img);
00092 #endif
00093 }
00094 
00095 void SoftObstacleDetection::houghTransform(const cv::Mat& img, std::vector<cv::Vec4i>& lines) const
00096 {
00097   lines.clear();
00098 
00099   // detect lines
00100   cv::HoughLinesP(img, lines, 1, CV_PI/180, 35, 80, 30);
00101 
00102 #ifdef DEBUG
00103   // draw detected lines
00104   cv::Mat img_lines(img.size(), CV_8UC3);
00105   img_lines = cv::Scalar::all(0);
00106   for (size_t i = 0; i < lines.size(); i++)
00107   {
00108     cv::Vec4i line = lines[i];
00109     cv::line(img_lines, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(0, 0, 255), 2, CV_AA);
00110   }
00111 
00112   cv::imshow("detected_lines", img_lines);
00113 #endif
00114 }
00115 
00116 uchar SoftObstacleDetection::getMaxAtLine(const cv::Mat& img, const cv::Point& p1, const cv::Point& p2) const
00117 {
00118   uchar result = 0;
00119 
00120   cv::LineIterator it(img, p1, p2, 8);
00121   for(int i = 0; i < it.count; i++, ++it)
00122   {
00123     result = std::max(result, img.at<uchar>(it.pos()));
00124 
00125     if (result == 255)
00126       break;
00127   }
00128 
00129   return result;
00130 }
00131 
00132 void SoftObstacleDetection::getLine(const cv::Mat& img, const cv::Vec4i& line, cv::Mat& out) const
00133 {
00134   cv::Point p1(line[0], line[1]);
00135   cv::Point p2(line[2], line[3]);
00136 
00137   std::vector<uchar> signal;
00138   double r = 3.0;
00139 
00140   cv::Vec2d orth_dir(static_cast<double>(p2.y-p1.y), static_cast<double>(-(p2.x-p1.x)));
00141   orth_dir = cv::normalize(orth_dir) * r;
00142   cv::Point o(std::floor(orth_dir(2)+0.5), std::floor(orth_dir(1)+0.5));
00143 
00144   cv::LineIterator it(img, p1, p2, 8);
00145   for(int i = 0; i < it.count; i++, ++it)
00146   {
00147     uchar val1 = getMaxAtLine(img, it.pos()-o, it.pos()+o);
00148     uchar val2 = getMaxAtLine(img, it.pos()-o-cv::Point(1, 1), it.pos()+o-cv::Point(1, 1));
00149     signal.push_back(std::max(val1, val2));
00150   }
00151 
00152   out = cv::Mat(cv::Size(signal.size(), 1), CV_8UC1);
00153   for (size_t i = 0; i < signal.size(); i++)
00154     out.at<uchar>(i) = signal[i];
00155 }
00156 
00157 void SoftObstacleDetection::edgeDetection(const cv::Mat& signal, std::vector<double>& edges, std::vector<double>& centers) const
00158 {
00159   //std::vector<double> edges; // pos = abs(c), edge direction = sign(c)
00160   //std::vector<double> centers; // pos = abs(c), val = sign(c)
00161 
00162   cv::Mat sig(signal.size(), CV_8UC1);
00163   signal.copyTo(sig);
00164 
00165   // detect edges
00166   unsigned int edge_dist = 0;
00167   std::vector<unsigned int> edge_distances;
00168 
00169   // run edge detection
00170   unsigned int last_val = signal.at<uchar>(0);
00171   for (int i = 1; i < signal.cols; i++)
00172   {
00173     edge_dist++;
00174 
00175     unsigned int current_val = static_cast<int>(signal.at<uchar>(i));
00176     int d = current_val - last_val;
00177 
00178     if (std::abs(d) > 150) // positiv distances edges
00179     {
00180       int sign = d < 0 ? -1 : 1;
00181 
00182       edges.push_back(static_cast<double>(sign * (i-0.5)));
00183 
00184       if (sign < 0 || edge_dist > min_hole_size_)
00185       {
00186         edge_distances.push_back(edge_dist);
00187         centers.push_back(static_cast<double>(-sign) * (static_cast<double>(i-0.5) - 0.5*static_cast<double>(edge_dist)));
00188 
00189         edge_dist = 0;
00190       }
00191       else // ignore small holes
00192       {
00193         for (int j = i - edge_dist; j < i; j++)
00194           sig.at<uchar>(j) = 255;
00195 
00196         if (!edge_distances.empty())
00197         {
00198           edge_dist += edge_distances[edge_distances.size()-1];
00199           edge_distances.pop_back();
00200           edges.pop_back();
00201           centers.pop_back();
00202         }
00203         edges.pop_back();
00204       }
00205     }
00206 
00207     last_val = current_val;
00208   }
00209 
00210   edge_distances.push_back(edge_dist);
00211   centers.push_back((last_val == 0 ? -1.0 : 1.0) * (static_cast<double>(signal.cols-0.5) - 0.5*static_cast<double>(edge_dist)));
00212 
00213   cv::resize(sig, sig, cv::Size(sig.cols*5, 30));
00214   cv::imshow("test1", sig);
00215 }
00216 
00217 bool SoftObstacleDetection::checkSegmentsMatching(const std::vector<double>& edges, const std::vector<double>& centers, double veil_segment_size, double min_segments, double max_segments) const
00218 {
00219   if (edges.empty() || centers.empty())
00220     return false;
00221 
00222   std::vector<double> seg_sizes;
00223   std::vector<double> seg_dists;
00224 
00225   double mse = 0.0;
00226   double size_mean = 0.0;
00227   double size_var = 0.0;
00228   double dist_mean = 0.0;
00229   double dist_var = 0.0;
00230 
00231   double last_edge = std::abs(edges[0]);
00232   for (size_t i = 1; i < edges.size()-1; i++)
00233   {
00234     double size = std::abs(edges[i]) - last_edge;
00235     if (edges[i] < 0)
00236     {
00237       double e = veil_segment_size - size;
00238 
00239       mse += e*e;
00240       size_mean += size;
00241 
00242       seg_sizes.push_back(size);
00243     }
00244     else
00245     {
00246       dist_mean += size;
00247       seg_dists.push_back(size);
00248     }
00249     last_edge = std::abs(edges[i]);
00250   }
00251 
00252   if (min_segments > seg_sizes.size() || seg_sizes.size() > max_segments)
00253     return false;
00254 
00255   mse /= static_cast<double>(seg_sizes.size());
00256   size_mean /= static_cast<double>(seg_sizes.size());
00257   dist_mean /= static_cast<double>(seg_dists.size());
00258 
00259   if (size_mean/dist_mean < size_dist_ratio_*0.9 || size_mean/dist_mean > size_dist_ratio_*1.1)
00260     return false;
00261 
00262   for (std::vector<double>::const_iterator itr = seg_sizes.begin(); itr != seg_sizes.end(); itr++)
00263     size_var += (*itr - size_mean)*(*itr - size_mean);
00264   size_var /= static_cast<double>(seg_sizes.size());
00265 
00266   for (std::vector<double>::const_iterator itr = seg_dists.begin(); itr != seg_dists.end(); itr++)
00267     dist_var += (*itr - dist_mean)*(*itr - dist_mean);
00268   dist_var /= static_cast<double>(seg_dists.size());
00269 
00270 #ifdef DEBUG
00271   ROS_INFO("MSE: %f, size_mean: %f, size_var: %f, dist_mean: %f, dist_var: %f", mse, size_mean, size_var, dist_mean, dist_var);
00272 #endif
00273 
00274   return mse < max_segment_size_mse_ && size_var < max_segment_size_var_ && dist_var < max_segment_dist_var_;
00275 }
00276 
00277 double SoftObstacleDetection::evalModel(const std::vector<double>& edges, const std::vector<double>& centers, double lambda) const
00278 {
00279   if (centers.size() < 2)
00280     return -1.0;
00281 
00282   double f = (2.0*M_PI)/lambda;
00283 
00284   double mse = 0.0;
00285 
00286   double bias = std::abs(edges[0]) - (edges[0] > 0.0 ? 0.0 : 0.5*lambda);
00287 
00288   double y = centers[0] < 0.0 ? 1.0 : -1.0;
00289   for (size_t i = 0; i < centers.size(); i++)
00290   {
00291     y *= -1.0;
00292     double x = f*(std::abs(centers[i])-bias);
00293     double e = y - sin(x);
00294     mse += e*e;
00295   }
00296 
00297   y = edges[0] < 0.0 ? 1.0 : -1.0;
00298   for (size_t i = 0; i < edges.size(); i++)
00299   {
00300     y *= -1.0;
00301     double x = f*(std::abs(edges[i])-bias);
00302     double e = y - cos(x);
00303     mse += e*e;
00304   }
00305 
00306   return mse/static_cast<double>(centers.size()+edges.size());
00307 }
00308 
00309 bool SoftObstacleDetection::checkFrequencyMatching(const std::vector<double>& edges, const std::vector<double>& centers, double lambda, double min_segments, double max_segments) const
00310 {
00311   if (edges.empty() || centers.empty())
00312     return false;
00313 
00314   if (min_segments > centers.size()/2 || centers.size()/2 > max_segments)
00315     return false;
00316 
00317 //  edges.clear();
00318 //  centers.clear();
00319 
00320 //  centers.push_back(-5);
00321 //  edges.push_back(10);
00322 //  centers.push_back(15);
00323 //  edges.push_back(-20);
00324 //  centers.push_back(-25);
00325 //  edges.push_back(30);
00326 //  centers.push_back(35);
00327 //  edges.push_back(-40);
00328 //  centers.push_back(-45);
00329 
00330 //  double mse = evalModel(edges, centers, 20.0);
00331 
00332   double mse = evalModel(edges, centers, lambda);
00333 
00334 //  // get average frequency
00335 //  mean /= static_cast<double>(edge_distances.size());
00336 
00337 //  // get variance
00338 //  var = 0.0;
00339 //  for (std::vector<unsigned int>::const_iterator itr = edge_distances.begin(); itr != edge_distances.end(); itr++)
00340 //  {
00341 //    double d = (static_cast<double>(*itr) - mean);
00342 //    var += d*d;
00343 //  }
00344 //  var /= static_cast<double>(edge_distances.size());
00345 
00346 
00347 //  std::string out;
00348 //  for (int i = 0; i < edges.cols; i++)
00349 //    out += boost::lexical_cast<std::string>(static_cast<int>(edges.at<char>(i))) + std::string(" ");
00350 //  ROS_INFO("%s", out.c_str());
00351 
00352 #ifdef DEBUG
00353   std::string out("MSE: ");
00354   out += boost::lexical_cast<std::string>(mse);
00355   out += "\nCenters: ";
00356   for (size_t i = 0; i < centers.size(); i++)
00357     out += boost::lexical_cast<std::string>(centers[i]) + std::string(" ");
00358   out += "\nEdges: ";
00359   for (size_t i = 0; i < edges.size(); i++)
00360     out += boost::lexical_cast<std::string>(edges[i]) + std::string(" ");
00361 
00362   ROS_INFO("%s", out.c_str());
00363   //ROS_WARN("Mean: %f, Var: %f (Std: %f)", mean, var, sqrt(var));
00364 #endif
00365 
00366   return mse < max_frequency_mse_;
00367 
00368 
00369 
00370 //  f.clear();
00371 
00372 //  cv::Mat padded;
00373 //  int n = cv::getOptimalDFTSize(signal.cols);
00374 //  cv::copyMakeBorder(signal, padded, 0, 0, 0, n - signal.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
00375 
00376 //  cv::Mat planes[] = {cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F)};
00377 //  cv::Mat complexI;
00378 //  cv::merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
00379 
00380 //  cv::dft(complexI, complexI);            // this way the result may fit in the source matrix
00381 
00382 //  // compute the magnitude and switch to logarithmic scale
00383 //  // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
00384 //  cv::split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
00385 //  cv::magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
00386 //  cv::Mat magI = planes[0];
00387 
00388 //  magI += cv::Scalar::all(1);                    // switch to logarithmic scale
00389 //  cv::log(magI, magI);
00390 
00391 //  // crop the spectrum, if it has an odd number of rows or columns
00392 //  //magI = magI(cv::Rect(0, 0, magI.cols & -2, magI.rows & -2));
00393 
00396 
00401 
00406 
00410 
00411 //  //cv::normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
00412 //  //                                        // viewable image form (float between values 0 and 1).
00413 
00414 //  //imshow("Input Image"       , I   );    // Show the result
00415 
00416 //  std::string out;
00417 //  for (int i = 0; i < magI.cols; i++)
00418 //    out += boost::lexical_cast<std::string>(magI.at<float>(i, 1)) + std::string(" ");
00419 //  ROS_INFO("%s", out.c_str());
00420 
00421 //  cv::resize(magI, magI, cv::Size(magI.cols*5, 30));
00422 //  cv::imshow("test2", magI);
00423 
00424 //  cv::Mat sig;
00425 //  signal.copyTo(sig);
00426 //  cv::resize(sig, sig, cv::Size(sig.cols*5, 30));
00427 //  cv::imshow("test1", sig);
00428 }
00429 
00430 void SoftObstacleDetection::lineToPointCloud(const cv::Vec4i& line, const cv::Point2i& scan_center, pcl::PointCloud<pcl::PointXYZ>& out) const
00431 {
00432   out.clear();
00433 
00434   int x1 = line[0];
00435   int y1 = line[1];
00436   int x2 = line[2];
00437   int y2 = line[3];
00438 
00439   // Bresenham's line algorithm
00440   const bool steep = (std::abs(y2 - y1) > std::abs(x2 - x1));
00441   if (steep)
00442   {
00443     std::swap(x1, y1);
00444     std::swap(x2, y2);
00445   }
00446 
00447   if (x1 > x2)
00448   {
00449     std::swap(x1, x2);
00450     std::swap(y1, y2);
00451   }
00452 
00453   const int dx = x2 - x1;
00454   const int dy = std::abs(y2 - y1);
00455 
00456   int error = dx / 2;
00457   const int ystep = (y1 < y2) ? 1 : -1;
00458 
00459   int y = y1;
00460   for (int x = x1; x < x2; x++)
00461   {
00462     if (steep)
00463       out.push_back(pcl::PointXYZ(static_cast<double>(y), static_cast<double>(x), 0.0));
00464     else
00465       out.push_back(pcl::PointXYZ(static_cast<double>(x), static_cast<double>(y), 0.0));
00466 
00467     error -= dy;
00468     if (error < 0)
00469     {
00470       y += ystep;
00471       error += dx;
00472     }
00473   }
00474 }
00475 
00476 void SoftObstacleDetection::update(const ros::TimerEvent& /*event*/)
00477 {
00478   if (!last_scan)
00479     return;
00480 
00481   std_msgs::Header header = last_scan->header;
00482 
00483   cv::Mat img_scan;
00484   cv::Point2i scan_center;
00485   transformScanToImage(last_scan, img_scan, scan_center);
00486 
00487 #ifdef DEBUG
00488   cv::Mat result;
00489   cv::cvtColor(img_scan, result, CV_GRAY2RGB);
00490 #endif
00491 
00492   last_scan.reset();
00493 
00494   cv::Mat img_scan_filtered;
00495   cv::Mat kernel_dil = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3.0, 3.0));
00496   cv::dilate(img_scan, img_scan, kernel_dil);
00497 
00498   std::vector<cv::Vec4i> lines;
00499   houghTransform(img_scan, lines);
00500 
00501 
00502   //cv::erode(img_scan, img_scan, kernel_dil);
00503 
00504   //cv::dilate(img_scan, img_scan, kernel_dil);
00505   //cv::imshow("test2", img_scan);
00506 
00507   if (lines.empty())
00508     return;
00509 
00510   // get signals of each detected line
00511   std::vector<cv::Mat> signals_;
00512   for (std::vector<cv::Vec4i>::const_iterator itr = lines.begin(); itr != lines.end(); itr++)
00513   {
00514     const cv::Vec4i& line = *itr;
00515     cv::Point p1(line[0], line[1]);
00516     cv::Point p2(line[2], line[3]);
00517 
00518     double length_sq = (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y);
00519 
00520     if (length_sq > max_curtain_length_sq_)
00521       continue;
00522 
00523     cv::Mat signal;
00524     getLine(img_scan, line, signal);
00525     signals_.push_back(signal);
00526 
00527     std::vector<double> edges; // pos = abs(c), edge direction = sign(c)
00528     std::vector<double> centers; // pos = abs(c), val = sign(c)
00529 
00530     edgeDetection(signal, edges, centers);
00531 
00532     // detect based on thresholds
00533     //if (min_frequency_ <= f && f <= max_frequency_ && var <= max_var_ /*&&  mse <= max_mse_*/)
00534     //if (checkFrequencyMatching(edges, centers, 2.0*veil_segment_size_, min_segments_, max_segments_))
00535     if (checkSegmentsMatching(edges, centers, veil_segment_size_, min_segments_, max_segments_))
00536     {
00537 #ifdef DEBUG
00538       ROS_INFO("Detected");
00539 #endif
00540 
00541       if (tf_listener.canTransform("/map", "/laser1_frame", header.stamp))
00542       {
00543         // generate pose of soft obstacle
00544         geometry_msgs::PoseStamped veil_pose;
00545         veil_pose.header = header;
00546         veil_pose.pose.position.x =  static_cast<float>((p1.x + p2.x)/2 - scan_center.x) / unit_scale;
00547         veil_pose.pose.position.y = -static_cast<float>((p1.y + p2.y)/2 - scan_center.y) / unit_scale;
00548         veil_pose.pose.position.z = 0.0;
00549 
00550         double dx =  ((p2.x - p1.x));
00551         double dy = -((p2.y - p1.y));
00552         veil_pose.pose.orientation = tf::createQuaternionMsgFromYaw(atan2(dy, dx) + M_PI_2);
00553 
00554         tf_listener.transformPose("/map", veil_pose, veil_pose);
00555 
00556         // publish veil pose percept
00557         hector_worldmodel_msgs::PosePercept veil_percept;
00558         veil_percept.header = veil_pose.header;
00559         veil_percept.pose.pose = veil_pose.pose;
00560         veil_percept.info.class_id = "soft_obstacle";
00561         veil_percept.info.class_support = 1.0;
00562 
00563         veil_percept_pub_.publish(veil_percept);
00564         veil_percept_pose_pub_.publish(veil_pose);
00565 
00566         // generate line as point cloud
00567         pcl::PointCloud<pcl::PointXYZ> pc;
00568         lineToPointCloud(line, scan_center, pc);
00569 
00570         for (size_t i = 0; i < pc.size(); i++)
00571         {
00572           pcl::PointXYZ& p = pc.at(i);
00573           p.x =  (p.x-static_cast<double>(scan_center.x)) / unit_scale;
00574           p.y = -(p.y-static_cast<double>(scan_center.y)) / unit_scale;
00575           p.z = 0.0;
00576         }
00577 
00578         // publish point cloud
00579         sensor_msgs::PointCloud2 pc_msg;
00580         pcl::toROSMsg(pc, pc_msg);
00581         pc_msg.header = header;
00582         pcl_ros::transformPointCloud("/map", pc_msg, pc_msg, tf_listener);
00583         veil_point_cloud_pub_.publish(pc_msg);
00584       }
00585 
00586 #ifdef DEBUG
00587       cv::line(result, p1, p2, cv::Scalar(0, 255, 0), 2, CV_AA);
00588       cv::imshow("result", result);
00589       //cv::waitKey();
00590 #endif
00591     }
00592   }
00593 
00594 #ifdef DEBUG
00595   cv::imshow("result", result);
00596   //ROS_INFO("--------------------------------------------------------------");
00597 #endif
00598 }
00599 
00600 void SoftObstacleDetection::laserScanCallback(const sensor_msgs::LaserScanConstPtr& scan)
00601 {
00602   last_scan = scan;
00603 }
00604 
00605 void SoftObstacleDetection::dynRecParamCallback(SoftObstacleDetectionConfig& config, uint32_t /*level*/)
00606 {
00607   min_hole_size_ = config.min_hole_size;
00608   max_curtain_length_sq_ = config.max_curtain_length*config.max_curtain_length*unit_scale*unit_scale;
00609   min_frequency_ = config.min_frequency;
00610   max_frequency_ = config.max_frequency;
00611   veil_segment_size_ = config.veil_segment_size*unit_scale;
00612   min_segments_ = config.min_segments;
00613   max_segments_ = config.max_segments;
00614   max_segment_size_mse_ = config.max_segment_size_mse;
00615   max_segment_size_var_ = config.max_segment_size_std*config.max_segment_size_std;
00616   max_segment_dist_var_ = config.max_segment_dist_std*config.max_segment_dist_std;
00617   size_dist_ratio_ = config.size_dist_ratio;
00618   max_frequency_mse_ = config.max_frequency_mse;
00619   percept_class_id_ = config.percept_class_id;
00620 }
00621 
00622 int main(int argc, char **argv)
00623 {
00624 #ifdef DEBUG
00625   cv::namedWindow("scan");
00626   cv::namedWindow("detected_lines");
00627   cv::namedWindow("result");
00628   cv::namedWindow("test1");
00629   cv::namedWindow("test2");
00630   cv::startWindowThread();
00631 #endif
00632 
00633   ros::init(argc, argv, "soft_obstacle_detection");
00634   SoftObstacleDetection sod;
00635   ros::spin();
00636 
00637 #ifdef DEBUG
00638   cv::destroyWindow("scan");
00639   cv::destroyWindow("detected_lines");
00640   cv::destroyWindow("result");
00641   cv::destroyWindow("test1");
00642   cv::destroyWindow("test2");
00643 #endif
00644 
00645   return 0;
00646 }
00647 


hector_soft_obstacle_detection
Author(s): Alexander Stumpf
autogenerated on Wed Sep 16 2015 10:20:00