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 #include "v4r_laser_filter/v4r_laser_line_filter_node.h"
00031
00032 #include <fstream>
00033
00034 using namespace LaserFilter;
00035
00036 int main(int argc, char **argv) {
00037
00038 ros::init(argc, argv, "LineFilter");
00039 ros::NodeHandle n;
00040 LaserLineFilterNode my_node(n);
00041 ros::spin();
00042 return 0;
00043 }
00044
00045 LaserLineFilterNode::LaserLineFilterNode ( ros::NodeHandle &n )
00046 :n_ ( n ), n_param_ ( "~" ) {
00047 sub_ = n_.subscribe("scan", 1000, &LaserLineFilterNode::callback, this);
00048 pub_laser_line_split_ = n_.advertise<sensor_msgs::LaserScan>("scan_lines_split", 1000);
00049 pub_laser_line_fit_ = n_.advertise<sensor_msgs::LaserScan>("scan_lines_fit", 1000);
00050 pub_laser_input_ = n_.advertise<sensor_msgs::LaserScan>("scan_input", 1000);
00051 pub_marker_ = n.advertise<visualization_msgs::Marker>("visualization_marker", 1000);
00052 pub_laser_lines_ = n_.advertise<geometry_msgs::PolygonStamped>("line_segments", 1000);
00053
00054 double tmp;
00055
00056 n_param_.param<bool>("publish_marker", param_.publish_marker, V4R_LASER_LINE_FILTER_PUBLISH_MARKER);
00057 ROS_INFO("%s: publish_marker: %s", n_param_.getNamespace().c_str(), ((param_.publish_marker) ? "true" : "false"));
00058
00059 n_param_.param<bool>("publish_lines", param_.publish_lines, V4R_LASER_LINE_FILTER_PUBLISH_LINES);
00060 ROS_INFO("%s: publish_lines: %s", n_param_.getNamespace().c_str(), ((param_.publish_lines) ? "true" : "false"));
00061
00062 n_param_.param<bool>("fit_lines", param_.fit_lines, V4R_LASER_LINE_FILTER_FIT_LINES);
00063 ROS_INFO("%s: fit_lines: %s", n_param_.getNamespace().c_str(), ((param_.fit_lines) ? "true" : "false"));
00064
00065 n_param_.param<bool>("split_scan", param_.split_scan, V4R_LASER_LINE_FILTER_SPLIT_SCAN);
00066 ROS_INFO("%s: split_scan: %s", n_param_.getNamespace().c_str(), ((param_.split_scan) ? "true" : "false"));
00067
00068
00069 n_param_.getParam("read_scan", param_.read_scan);
00070 ROS_INFO("%s: read_scan: %s", n_param_.getNamespace().c_str(), ((param_.read_scan) ? "true" : "false"));
00071 n_param_.getParam("write_scan", param_.write_scan);
00072 ROS_INFO("%s: write_scan: %s", n_param_.getNamespace().c_str(), ((param_.write_scan) ? "true" : "false"));
00073 n_param_.getParam("scan_filename", param_.scan_filename);
00074 ROS_INFO("%s: scan_filename: %s", n_param_.getNamespace().c_str(), param_.scan_filename.c_str());
00075
00076 n_param_.param<double>("threshold_split", tmp, V4R_LASER_LINE_FILTER_THRESHOLD_SPLIT);
00077 param_.threshold_split = tmp;
00078 ROS_INFO("%s: threshold_split: %4.3f", n_param_.getNamespace().c_str(), param_.threshold_split);
00079 n_param_.getParam("threshold_split_neighbor", param_.threshold_split_neighbor);
00080 ROS_INFO("%s: threshold_split_neighbor: %s", n_param_.getNamespace().c_str(), ((param_.threshold_split_neighbor) ? "true" : "false"));
00081
00082 n_param_.param<double>("min_length", tmp, V4R_LASER_LINE_FILTER_MIN_LENGTH);
00083 param_.min_length = tmp;
00084 ROS_INFO("%s: min_length: %4.3f", n_param_.getNamespace().c_str(), param_.min_length);
00085
00086 n_param_.param<int>("min_points_per_line", param_.min_points_per_line, V4R_LASER_LINE_FILTER_MIN_POINTS_PER_LINE);
00087 ROS_INFO("%s: min_points_per_line: %i", n_param_.getNamespace().c_str(), param_.min_points_per_line);
00088
00089 n_param_.param<double>("min_points_per_meter", tmp, V4R_LASER_LINE_FILTER_MIN_POINTS_PER_METER);
00090 param_.min_points_per_meter = tmp;
00091 ROS_INFO("%s: min_points_per_meter: %4.3f", n_param_.getNamespace().c_str(), param_.min_points_per_meter);
00092
00093
00094
00095 reconfigureFnc_ = boost::bind(&LaserLineFilterNode::callbackParameters, this, _1, _2);
00096 reconfigureServer_.setCallback(reconfigureFnc_);
00097 }
00098
00099 void LaserLineFilterNode::callbackParameters ( v4r_laser_filter::LineFilterConfig &config, uint32_t level ) {
00100 param_.publish_marker = config.publish_marker;
00101 param_.threshold_split = config.threshold_split;
00102 param_.threshold_split_neighbor = config.threshold_split_neighbor;
00103 param_.min_length = config.min_length;
00104 param_.min_points_per_line = config.min_points;
00105 param_.min_points_per_meter = config.min_points_per_meter;
00106 param_.fit_lines = config.fit_lines;
00107 param_.split_scan = config.split_scan;
00108 param_.write_scan = config.write_scan;
00109 param_.read_scan = config.read_scan;
00110 }
00111
00112 void LaserLineFilterNode::callback (const sensor_msgs::LaserScan::ConstPtr& _msg) {
00113
00114 if(param_.write_scan) LaserFilter::writeScan(param_.scan_filename, *_msg);
00115 if(param_.read_scan) LaserFilter::readScan(param_.scan_filename, msg_scan_);
00116 else msg_scan_ = *_msg;
00117
00118 if(pub_laser_input_.getNumSubscribers() > 0) {
00119 pub_laser_input_.publish(msg_scan_);
00120 }
00121
00122 LaserFilter::copy(msg_scan_, measurments_, beams_);
00123
00124 splitStart();
00125 sensor_msgs::LaserScan msg = msg_scan_;
00126 if(param_.split_scan) {
00127 for (int i = 0; i < msg_scan_.ranges.size(); i++) msg.ranges[i] = nanf("");
00128
00129 for(unsigned int i = 0; i < lineSegments_.size(); i++) {
00130 for(unsigned int idx = lineSegments_[i].idx.first; idx < lineSegments_[i].idx.second; idx++) {
00131 msg.ranges[idx] = msg_scan_.ranges[idx];
00132 }
00133 }
00134 }
00135 pub_laser_line_split_.publish(msg);
00136
00137
00138 if(param_.fit_lines) {
00139 lineFitStart();
00140 }
00141
00142 if(param_.publish_marker) {
00143 publish_marker();
00144 }
00145
00146 if(param_.publish_lines){
00147 msg_lines.header = msg.header;
00148 msg_lines.polygon.points.clear();
00149 msg_lines.polygon.points.reserve(lineSegments_.size()*2);
00150 geometry_msgs::Point32 p0, p1;
00151 for(unsigned int i = 0; i < lineSegments_.size(); i++) {
00152 p0.x = lineSegments_[i].p0.x, p0.y = lineSegments_[i].p0.y, p0.z = 0;
00153 p1.x = lineSegments_[i].p1.x, p1.y = lineSegments_[i].p1.y, p0.z = 0;
00154 msg_lines.polygon.points.push_back(p0);
00155 msg_lines.polygon.points.push_back(p1);
00156 }
00157 pub_laser_lines_.publish(msg_lines);
00158 }
00159 }
00160
00161 void LaserLineFilterNode::publish_marker () {
00162 msg_line_list_.header = msg_scan_.header;
00163 msg_line_list_.ns = "lines";
00164 msg_line_list_.action = visualization_msgs::Marker::ADD;
00165 msg_line_list_.pose.orientation.w = 1.0;
00166 msg_line_list_.id = 0;
00167 msg_line_list_.type = visualization_msgs::Marker::LINE_LIST;
00168 msg_line_list_.scale.x = 0.01;
00169 msg_line_list_.color.r = 1.0;
00170 msg_line_list_.color.g = 0.0;
00171 msg_line_list_.color.b = 0.0;
00172 msg_line_list_.color.a = 1.0;
00173 geometry_msgs::Point p0, p1;
00174 msg_line_list_.points.clear();
00175 for(unsigned int i = 0; i < lineSegments_.size(); i++) {
00176 p0.x = lineSegments_[i].p0.x, p0.y = lineSegments_[i].p0.y;
00177 p1.x = lineSegments_[i].p1.x, p1.y = lineSegments_[i].p1.y;
00178 msg_line_list_.points.push_back(p0);
00179 msg_line_list_.points.push_back(p1);
00180 }
00181 pub_marker_.publish(msg_line_list_);
00182 }
00183
00184 void LaserLineFilterNode::lineFitStart() {
00185
00186 std::vector<cv::Point2f> points;
00187 lines_.resize(lineSegments_.size());
00188 for(unsigned int i = 0; i < lineSegments_.size(); i++) {
00189 lineSegments_[i].estimator_theilsen(measurments_, lineSegments_[i]);
00190 lines_[i].set(lineSegments_[i].p0,lineSegments_[i].p1);
00191 }
00192 }
00193
00194 void LaserLineFilterNode::splitStart() {
00195 connectedMeasurments_.clear();
00196 lineSegments_.clear();
00197
00198 if(measurments_.size() > 0) {
00199
00200 std::pair< unsigned int, unsigned int> idx;
00201 idx.first = 0;
00202
00203 while(idx.first < measurments_.size()) {
00204 idx.second = idx.first + 1;
00205 float threshold = 4 * cv::norm(measurments_[idx.second] - measurments_[idx.second+1]);
00206 while((idx.second < measurments_.size()) && (measurments_[idx.second].valid)) {
00207 if(param_.threshold_split_neighbor) {
00208 float d = cv::norm(measurments_[idx.second] - measurments_[idx.second+1]);
00209 if(d > threshold) {
00210 break;
00211 }
00212 threshold = 4 * d;
00213 }
00214 idx.second++;
00215 }
00216 if((idx.second - idx.first) > 2) {
00217 connectedMeasurments_.push_back(idx);
00218 }
00219 idx.first = idx.second+1;
00220 }
00221
00222 for(unsigned int i = 0; i < connectedMeasurments_.size(); i++) {
00223 unsigned int idx0 = connectedMeasurments_[i].first;
00224 unsigned int idx1 = connectedMeasurments_[i].second;
00225 while((idx0 < connectedMeasurments_[i].second) && (measurments_[idx0].valid == false)) {
00226 idx0++;
00227 }
00228 while((idx1 > idx0) && (measurments_[idx1].valid == false)) {
00229 idx1--;
00230 }
00231 if(idx1 > idx0) {
00232 LineSegment line;
00233 line.set(idx0, idx1, measurments_);
00234 split(line);
00235 }
00236 }
00237 }
00238 }
00239
00240 void LaserLineFilterNode::split(LineSegment &line) {
00241 unsigned int idxMax=line.idx.first;
00242 float d;
00243 float dMax = 0;
00244 for(unsigned int i = line.idx.first; i < line.idx.second; i++) {
00245 d = fabs(line.distance(measurments_[i]));
00246 if(d > dMax) {
00247 dMax = d, idxMax = i;
00248 }
00249 }
00250 if(dMax > param_.threshold_split) {
00251 LineSegment l0,l1;
00252 if(line.idx.first+param_.min_points_per_line < idxMax) {
00253 l0.set(line.idx.first, idxMax, measurments_);
00254 split(l0);
00255 }
00256 if(idxMax+param_.min_points_per_line < line.idx.second) {
00257 l1.set(idxMax, line.idx.second, measurments_);
00258 split(l1);
00259 }
00260 } else {
00261 if(line.length() < param_.min_length) {
00262 return;
00263 }
00264 if(((float) line.nrSupportPoint()) / line.length() < param_.min_points_per_meter) {
00265 return;
00266 }
00267 if(fabs(line.distance(cv::Point2f(0,0))) < (param_.threshold_split*param_.threshold_split)) {
00268
00269 return;
00270 }
00271 line.id = lineSegments_.size();
00272 lineSegments_.push_back(line);
00273 }
00274 }
00275