diff --git a/CMakeLists.txt b/CMakeLists.txt index de2f6ef5b3dd9cdb90cdd0bad765687258995717..feda53e6d5abcbbf77308df98e9dfd423563e2db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,8 @@ SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) SET(CMAKE_INSTALL_PREFIX /usr/local) IF (NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "RELEASE") + #SET(CMAKE_BUILD_TYPE "DEBUG") + SET(CMAKE_BUILD_TYPE "RELEASE") ENDIF (NOT CMAKE_BUILD_TYPE) message(STATUS "Configured to compile in ${CMAKE_BUILD_TYPE} mode.") diff --git a/Findlaser_scan_utils.cmake b/Findlaser_scan_utils.cmake index 6e76479dcc4ffde8df823fbe64f1b531edcce657..1c7aa15396ad0767ea47238c60f2eeb70ced9b51 100644 --- a/Findlaser_scan_utils.cmake +++ b/Findlaser_scan_utils.cmake @@ -1,7 +1,7 @@ #edit the following line to add the librarie's header files FIND_PATH( laser_scan_utils_INCLUDE_DIRS - NAMES corner_detector.h entities.h line_fitting.h scan_basics.h types_laser_scan_utils.h + NAMES corner_detector.h entities.h line_fitting.h scan_basics.h types_laser_scan_utils.h clustering.h PATHS /usr/local/include/iri-algorithms/laser_scan_utils ) diff --git a/src/clustering.cpp b/src/clustering.cpp index 88b0e616b5031c33af8aab94b8a3d01266b4467f..2b75d519975f0c10c56f224e3a5b4bb1bdb619a6 100644 --- a/src/clustering.cpp +++ b/src/clustering.cpp @@ -1,11 +1,266 @@ #include "clustering.h" +#include <fstream> // std::ofstream + +void laserscanutils::LaserDetectionParams::print() const +{ + std::cout << "--------------------------------------------" << std::endl + << "-- Laser Detection Algorithm Parameters --" << std::endl + << "--------------------------------------------" << std::endl + << " * Maximum Distance Between Points: " << jump_thr << std::endl + << " * Minimum Number of Points for a Cluster: " << min_num_cluster_points << std::endl + << " * Maximum Number of Points for a Cluster: " << max_num_cluster_points << std::endl; + +} + + + + +Eigen::MatrixXs laserscanutils::loadScanMatrix() +{ + std::vector<std::vector<float> > values; + std::ifstream fin("/home/vvaquero/testOneScan2.txt"); + for (std::string line; std::getline(fin, line); ) + { + std::replace(line.begin(), line.end(), ',', ' '); + std::istringstream in(line); + values.push_back( + std::vector<float>(std::istream_iterator<float>(in), + std::istream_iterator<float>())); + } + + unsigned int rows = values.size(); + unsigned int columns = 0; + + for (unsigned int k = 0; k < rows; k++) + { + if (values[k].size() > columns) + columns = values[k].size(); + } + + std::cout << "Matrix Size = " << rows << "x" << columns <<std::endl; + Eigen::MatrixXs result(rows,columns); + + for (unsigned int i = 0; i < rows; i++) + for (unsigned int j = 0; j < columns; j++) + { + result(i,j) = values[i][j]; + //std::cout << "(" << result(i,j) << ") " ; + } + return result; +} + + + + +void laserscanutils::exportData2Matlab(const Eigen::MatrixXs & _points, + const LaserDetectionParams & _alg_params, + const LaserDetectionStats & _stats, + const char * _file_name) +{ + std::ofstream fileMatlab; + fileMatlab.open (_file_name, std::ofstream::out); // | std::ofstream::app); + + // FILE HEADER + fileMatlab << "% ***** Autogenerated File - vvg ***** \n\n"; + fileMatlab << " clc,\n clear all,\n close all \n\n\n"; + + // Algorithm Params + fileMatlab << "% Algorithm Params \n"; + fileMatlab << "alg_params = struct(" + " 'jump_thr', " << _alg_params.jump_thr << "," + "'min_num_cluster_points', " << _alg_params.min_num_cluster_points << "," + "'max_num_cluster_points', " << _alg_params.max_num_cluster_points << "); \n\n"; + + // Algorithm Status Variables + fileMatlab << "% Algorithm Status Variables \n"; + fileMatlab << "alg_stats = struct(" + "'filteredTotalPoints', " << _stats.filteredTotalPoints << "," + "'numberOfClusters', " << _stats.numberOfClusters << "," + "'numberOfValidClusters', " << _stats.numberOfValidClusters << "," + "'scanTotalPoints', " << _stats.scanTotalPoints << "," + "'cluster_indxs_', [" ; + + for (unsigned int cluster = 0; cluster < _stats.cluster_indxs_.size(); cluster++) + { + std::pair<int,int> tempCluster = _stats.cluster_indxs_[cluster]; + fileMatlab << tempCluster.first << "; " << tempCluster.second << "; "; + } + fileMatlab << "]);\n"; + fileMatlab << "alg_stats.cluster_indxs_ = reshape(alg_stats.cluster_indxs_,[2,length(alg_stats.cluster_indxs_)/2]); \n\n"; + + // Scanner Points in Homogeneous coordinates + fileMatlab << "% Writing Scanner Points in Homogeneous coordinates \n"; + fileMatlab << "scanMatrixHomo = ["; + for (unsigned int row = 0; row < 3; row++) + { + for (unsigned int col = 0; col < _stats.filteredTotalPoints; col++) + { + fileMatlab << _points(row,col) << ","; + } + fileMatlab << "\n"; + } + fileMatlab << "]; \n\n"; + + // Rotating Points Matrix + fileMatlab << "% Rotating Points Matrix \n"; + fileMatlab << "scanMatrix = scanMatrixHomo(1:2, :); \n" ; + fileMatlab << "alfa = pi/2; \n"; + fileMatlab << "rotateM = [cos(alfa), -sin(alfa); sin(alfa), -cos(alfa)]; \n"; + fileMatlab << "scanMatrixRot = rotateM*scanMatrix; \n\n"; + + + // Drawing Rotated Scan + fileMatlab << "% Drawing Rotated Scan \n"; + fileMatlab << "scatter(scanMatrixRot(1,:), scanMatrixRot(2,:),30,'filled'); axis equal; grid on; \n\n"; + + + fileMatlab.close(); +} + + + + + + + + + + +//**************************************************** +//********** preFilterScan +//**************************************************** +void laserscanutils::preFilterScan(const ScanParams & _params, + const std::vector<float> & _ranges, + Eigen::MatrixXs & _points, + LaserDetectionStats &_stats) +{ + //std::cout << "[PreFiltering SCAN... "; + //assert( (_ranges.size() == _points.cols() ) &&(_points.rows() == (unsigned int)3) &&("Error: [laserPolar2xy] points Matrix size is different than number of ranges. Wrong Matrix Size.")); + + unsigned int matPosition = 0; + float act_range = -1; + float act_theta = 0.0; + + for(unsigned int i=0; i<_ranges.size(); ++i) + { + act_range = _ranges[i]; + + if ( (act_range >=_params.range_min_) && (act_range <= _params.range_max_) && !(isnan(act_range)) && !(isinf(act_range)) ) + { + act_theta = _params.angle_min_+ _params.angle_step_*(i); + + _points.col(matPosition) << act_range*cos(act_theta), act_range*sin(act_theta), 1; + + matPosition++; + } + else + { + //std::cout << "Invalid Point: " << scan.ranges[i] << " - index: " << i << std::endl; + } + + + } // END FOR scan ranges + + // Filling stats + _stats.scanTotalPoints = _ranges.size(); + _stats.filteredTotalPoints = matPosition; + + //std::cout << "..DONE] " << std::endl; +} + + + + + + +//**************************************************** +//********** findClusters +//**************************************************** +void laserscanutils::findClusters(const LaserDetectionParams & _alg_params, + const Eigen::MatrixXs & _points, + LaserDetectionStats & _stats) +{ + + _stats.cluster_indxs_.clear(); + + std::pair<int,int> seg; // saves the first and last point for each segment + + float points_distance = 0.0; + int count_num_cluster = 0; + int count_num_valid_cluster = 0; + + + // Initial Segment +// count_num_cluster = 1; + seg.first = 0; + float sq_threshold = pow(_alg_params.jump_thr,2.0); + + for (unsigned int col = 1; col < _points.cols(); col++) + { + points_distance = ( pow( ( _points(0,col) -_points(0,col-1) ), 2.0 ) + pow( ( _points(1,col) - _points(1,col-1) ), 2.0) ); + + if ( points_distance <= sq_threshold) // same segment points + { + // Same segment -> TODO counter? + } + + else // if ( col != _points.cols() ) // new segment + { + //std::cout << "P " << pos << " - A - (" << pointA.x << "-" << pointA.y << ") - B - (" << pointB.x << "-" << pointB.y << ") -> distance: " << points_distance << " More Than th" << std:endl; + + seg.second = col-1; // end of the previous segment + + // check length of the cluster + if ( ( (seg.second - seg.first)+1 >= _alg_params.min_num_cluster_points ) && ( (seg.second - seg.first)+1 <= _alg_params.max_num_cluster_points) ) + { + _stats.cluster_indxs_.push_back(seg); + count_num_valid_cluster++; // count cluster as valid + //std::cout << "CLUSTER IS VALID" << std::endl; + } + // TODO: else: save the invalid cluster in other vector of bad clusters to further analysis + count_num_cluster++; // count any cluster + + seg.first = col; + } + + } + // last point close last segment + seg.second = _points.cols()-1; + if (seg.second - seg.first >= _alg_params.min_num_cluster_points && seg.second - seg.first <= _alg_params.max_num_cluster_points) + { + _stats.cluster_indxs_.push_back(seg); + count_num_valid_cluster++; // count cluster as valid + std::cout << "CLUSTER IS VALID" << std::endl; + } + count_num_cluster++; // count any cluster + + + // Stats + _stats.numberOfClusters = count_num_cluster; + _stats.numberOfValidClusters = count_num_valid_cluster; + + std::cout << "numberOfValidClusters = " << count_num_valid_cluster << std::endl; +} + + + + + + + + +// NOT USED!!!! // VV - Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. -unsigned int laserscanutils::scanProcess(const ScanParams & _params, const std::vector<float> & _ranges, const float _jump_threshold, Eigen::MatrixXs & _points, std::vector<unsigned int> & _jumps_id_) +unsigned int laserscanutils::scanProcess(const ScanParams & _params, + const std::vector<float> & _ranges, + const float _jump_threshold, + Eigen::MatrixXs & _points, + std::vector<unsigned int> & _jumps_id_) { - assert( (_ranges.size() == _points.cols() ) &&(_points.rows() == 3) &&("Error: [laserPolar2xy] points Matrix size is different than number of ranges. Wrong Matrix Size.")); + //assert( (_ranges.size() == _points.cols() ) &&(_points.rows() == 3) &&("Error: [laserPolar2xy] points Matrix size is different than number of ranges. Wrong Matrix Size.")); _jumps_id_.clear(); @@ -59,6 +314,45 @@ unsigned int laserscanutils::scanProcess(const ScanParams & _params, const std:: +// VV - test to check results in txt +void laserscanutils::printMatrix2File(const unsigned int _num_points, + Eigen::MatrixXs & _points, + std::vector<unsigned int> & _jumps_id_) +{ + std::ofstream filePoints; + filePoints.open ("/home/vvaquero/TestInfoScanPoints.txt", std::ofstream::out | std::ofstream::app); + + // TO PRINT IN ONE ROW +// for (int numpoint = 0; numpoint < _num_points; numpoint++) +// { +// filePoints << _points.col(numpoint) << "\n"; +// } +// filePoints.close(); + + for (unsigned int row = 0; row < 3; row++) + { + for (unsigned int col = 0; col < _num_points; col++) + { + filePoints << _points(row,col) << ","; + } + filePoints << "\n"; + } + filePoints.close(); + + + std::ofstream fileSegments; + fileSegments.open ("/home/vvaquero/TestInfoScanSegments.txt", std::ofstream::out | std::ofstream::app); + for (unsigned int segnum = 1; segnum<_jumps_id_.size(); segnum++) + { + if (segnum == 1) + fileSegments << "Segment Number: 0 - from 0 " << " to " << _jumps_id_[segnum] << "\n"; + else + fileSegments << "Segment Number: "<< segnum << " - from " << _jumps_id_[segnum-1] << " to " << _jumps_id_[segnum] << "\n"; + } + fileSegments.close(); + //std::cout << "PRINTING OUT " << std::endl; +} + @@ -70,132 +364,6 @@ unsigned int laserscanutils::scanProcess(const ScanParams & _params, const std:: -//unsigned int laserscanutils::extractLineInSegs(const Segment & _mySegment , std::list<laserscanutils::Line> & _line_list) -//{ -// //local variables -// ScalarT cos_theta, theta; -// Line line; -// std::list<Line>::iterator line_it1, line_it2; -// std::queue<unsigned int> jumps; -// bool update_iterators; -// ScalarT max_distance_sq(_alg_params.max_distance*_alg_params.max_distance); //init max distance as the squared value to avoid sqroot on comparisons -// //init random generator -// std::default_random_engine generator(1); -// std::uniform_int_distribution<int> rand_window_overlapping(1,_alg_params.segment_window_size); -// //STEP 0: convert range polar data to cartesian points, and keep range jumps -//// for (unsigned int ii = 0; ii<_ranges.size(); ii++) -//// { -//// //range 2 polar -//// azimuth = _params.angle_max_ - _params.angle_step_ * ii; -//// points.col(ii) << _ranges(ii)*cos(azimuth), _ranges(ii)*sin(azimuth), 1; //points.row0-> x coordinate, points.row1->y coordinate -//// -//// //check range jump and keep it -//// if (ii > 0 && fabs(_ranges(ii)-_ranges(ii-1)) > _alg_params.max_distance) jumps.push(ii); -//// } -// Eigen::MatrixXs points = laserPolar2xy(_params, _ranges, _alg_params.max_distance, jumps); -// std::cout << "jumps: " << jumps.size() << std::endl; -// std::cout << "points: " << points.rows() << "x" << points.cols()<< std::endl; -// // STEP 1: find line segments running over the scan -// for (unsigned int ii = _alg_params.segment_window_size-1; ii<points.cols(); ii=ii+rand_window_overlapping(generator) ) -// { -// unsigned int i_from = ii - _alg_params.segment_window_size + 1; - -// // update the jump to be checked -// while (!jumps.empty() && i_from > jumps.front()) -// jumps.pop(); - -// // check if there is a jump inside the window (not fitting if it is the case) -// if (jumps.front() > i_from && jumps.front() <= ii) -// continue; - -// //Found the best fitting line over points within the window [ii - segment_window_size + 1, ii] -// //fitLine(i_from, ii, points, line); -// fitLine(points.block(0,i_from, 3, ii-i_from+1), line); - -// //if error below stdev, add line to ScalarT cornerAperture(const Eigen::Vector3s & _p1, const Eigen::Vector3s & _c, const Eigen::Vector3s & _p2);result set -// if ( line.error_ < _params.range_std_dev_*_alg_params.k_sigmas ) -// { -// line.first_ = i_from; -// line.last_ = ii; -// line.point_first_ = points.col(line.first_); -// line.point_last_ = points.col(line.last_); -// line.np_ = line.last_ - line.first_ + 1; -// _line_list.push_back(line); -// } -// } -// std::cout << "Lines fitted: " << _line_list.size() << std::endl; - -// //In case just less than two lines found, return with 0 corners -// if ( _line_list.size() < 2 ) return 0; - -// //STEP 2: concatenate lines -// line_it1 = _line_list.begin(); -// line_it2 = line_it1; -// line_it2 ++; -// while ( line_it1 != _line_list.end() ) -// { -// //if no concatenation found, iterators will run forward -// update_iterators = true; - -// // check if last of line1 and first of line2 are within the threshold -// if ( ( line_it2->first_ - line_it1->last_ ) <= _alg_params.max_beam_distance ) -// { -// //compute angle between lines 1 and 2 -// cos_theta = (line_it1->vector_).dot(line_it2->vector_) / ( (line_it1->vector_).norm()*(line_it2->vector_).norm() ); -// theta = acos (cos_theta); //theta is in [0,PI] -// if (theta > M_PI/2) theta = M_PI - theta;//assures theta>0 AND either theta close to 0 or close to PI will always map to theta close to 0. -//// std::cout << std::endl << "cos_theta: " << cos_theta << std::endl << "theta: " << theta << std::endl << -//// "*index_it1: " << *index_it1 << std::endl << "*index_it2: " << *index_it2 << std::endl; -//// " (*line_it1).dot(*line_it2): " << (*line_it1).dot(*line_it2) << std::endl << -//// " (*line_it1).norm()*(*line_it2).norm(): " << (*line_it1).norm()*(*line_it2).norm() << std::endl; - -// //Check angle threshold -// if ( theta < _alg_params.theta_max_parallel ) //fabs(theta) not required since theta>0 -// { -// //compute a new line with all involved points -// Line new_line; -// fitLine(points.block(0,line_it1->first_, 3, line_it2->last_-line_it1->first_+1), new_line); - -// //check if error below a threshold to effectively concatenate -// if ( new_line.error_ < _params.range_std_dev_*_alg_params.k_sigmas ) -// { -// //update line1 as the concatenation of l1 and l2 -// new_line.first_ = line_it1->first_; -// new_line.last_ = line_it2->last_; -// new_line.point_first_ = points.col(new_line.first_); -// new_line.point_last_ = points.col(new_line.last_); -// new_line.np_ = new_line.last_ - new_line.first_ + 1; -// *line_it1 = new_line; - -// //remove l2 from the list -// line_it2 = _line_list.erase(line_it2); - -// //in that case do not update iterators to allow concatenation of the new l1 with the next line in the list, if any -// update_iterators = false; - -//// std::cout << "lines concatenated" << std::endl; -//// std::cout << "line 1: " << std::endl << line_it1->first << std::endl << -//// line_it1->last << std::endl << line_it1->vector_.transpose() << std::endl << line_it1->error << std::endl; -//// std::cout << "line 2: " << std::endl << line_it2->first << std::endl << -//// line_it2->last << std::endl << line_it2->vector_.transpose() << std::endl << line_it2->error << std::endl; -//// std::cout << "line resultant: "<< std::endl << new_line.first << std::endl << -//// new_line.last << std::endl << new_line.vector_.transpose() << std::endl << new_line.error << std::endl; -// } -// } -// } - -// //update iterators -// if (update_iterators) -// { -// line_it1 ++; -// line_it2 = line_it1; -// line_it2 ++; -// } -// } -// std::cout << "Lines after concatenation: " << _line_list.size() << std::endl; - -// return _line_list.size(); -//} diff --git a/src/clustering.h b/src/clustering.h index 8eb060610ba3361ec179e59a6fa792add798189c..82a0b0732ea53b849eae5a4d43e870dc0c210441 100644 --- a/src/clustering.h +++ b/src/clustering.h @@ -7,6 +7,17 @@ #include "scan_basics.h" #include "corner_detector.h" + +#include <fstream> +#include <iostream> +#include <iterator> +#include <sstream> +#include <string> +#include <vector> +#include <eigen3/Eigen/Dense> + +//#include <fstream> // File Printing for tests + //#include "segment.h" @@ -15,12 +26,109 @@ namespace laserscanutils { - /** \brief TODO - * - * Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. - * - **/ - unsigned int scanProcess(const ScanParams & _params, const std::vector<float> & _ranges, const float _jump_threshold, Eigen::MatrixXs & _points, std::vector<unsigned int> & _jumps_id_); + /** \brief Set of tunning parameters + * + * Set of tunning parameters for corner extraction + * + */ + struct LaserDetectionParams + { + //members + float jump_thr; //max distance between points + float min_num_cluster_points; //minimum number of points for a cluster + float max_num_cluster_points; //maximum number of points for a cluster + + void print() const; + }; + + struct LaserDetectionStats + { + // Mid variables for the algorithm, storing information needed for the correct working + + unsigned int scanTotalPoints; //Total number of points in the raw scan + unsigned int filteredTotalPoints; //Total number of valid points after pre filter + unsigned int numberOfClusters; //Total number of clusters found in the scan + unsigned int numberOfValidClusters; //Total number of valid clusters found in the scan + std::vector< std::pair<int,int> > cluster_indxs_; // Contains initial and final columns (of the filtered homogeneous matrix) for clusters. + + }; + + + // TEST + Eigen::MatrixXs loadScanMatrix(); + + + /** \brief Test Porpuses to create a Matlab script with all the variables. + **/ + void exportData2Matlab(const Eigen::MatrixXs & _points, + const LaserDetectionParams & _alg_params, + const LaserDetectionStats & _stats, + const char * _file_name); + + + + /** \brief Filters the valid ranges on a scan and converts them to homogeneous coordinates. + * + * Valid ranges are filtered according to scan parameters. + * Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. + * + * \param _params is the laser_scan_utils structure of the laser parameters. + * \param _ranges is the raw scan measures. Vector of float ranges. + * \param _points is the returned points from the conversion of ranges to homogeneous coordinates + * \param _stats is the statistics structure where number of valid points is saved under _stats.filteredTotalPoints + * + **/ + void preFilterScan(const ScanParams & _params, + const std::vector<float> & _ranges, + Eigen::MatrixXs & _points, + LaserDetectionStats & _stats); + + + + /** \brief Find the clusters in the valid points from the scan. + * + * Check distance between valid points in homogeneous coordinates. If it is more than the threshold, considers it as a different cluster. + * + * \param _alg_params is the structure of algorithm params for the Laser Detection Algorithm. + * \param _points is the returned points from the conversion of ranges to homogeneous coordinates + * \param _stats is the statistics structure (TODO: What is used here? - Number of Clusters) + **/ + void findClusters(const LaserDetectionParams & _alg_params, + const Eigen::MatrixXs & _points, + LaserDetectionStats & _stats); + + + + + + + /** \brief Converts ranges from a laserScan to homogeneous coordinates. Check validity of the ranges and look cluster jumps. + * + * Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. + * Valid ranges are filtered and at the same time cluster jumps are checked. + * TODO (jumpThreshold) + * + * \param _params is the laser_scan_utils structure of the laser parameters. + * \param _ranges is the raw scan measures. Vector os ranges. + * \param _jump_threshold is the jump to diferenciate between clusters -> TODO in algorithm parameters + * \param _points is the returned points from the conversion of ranges to homogeneous coordinates + * \param _jumps_id_ is the vector containing in which column of the _points matrix exist a cluster jump. + **/// NOT USED!! + unsigned int scanProcess(const ScanParams & _params, + const std::vector<float> & _ranges, + const float _jump_threshold, + Eigen::MatrixXs & _points, + std::vector<unsigned int> & _jumps_id_); + + + + + void printMatrix2File(const unsigned int _num_points, + Eigen::MatrixXs & _points, + std::vector<unsigned int> & _jumps_id_); + + + /** \brief Analyse clusters and extract the geometry primitives - line, corner... diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index a121632f9e66ba51897e1d8e442c95d236bf50df..330d3de351619f5d85df78dfe9a61ac97895ac29 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -7,3 +7,7 @@ ENDIF(faramotics_FOUND) # corner aperture test ADD_EXECUTABLE(test_corner_aperture test_corner_aperture.cpp) TARGET_LINK_LIBRARIES(test_corner_aperture ${PROJECT_NAME}) + +# Object Detector test +ADD_EXECUTABLE(test_laser_detector test_laser_detector.cpp) +TARGET_LINK_LIBRARIES(test_laser_detector ${PROJECT_NAME}) diff --git a/src/examples/testOneScan.txt b/src/examples/testOneScan.txt new file mode 100644 index 0000000000000000000000000000000000000000..859c61e67dbc2064d77ae68b39e2372aa80ceeb6 --- /dev/null +++ b/src/examples/testOneScan.txt @@ -0,0 +1,3 @@ +2.47857,2.40308,2.46936,2.49425,2.58269,2.6075,2.6976,2.67785,2.75212,2.81579,2.88573,2.93293,2.9802,3.02752,3.07489,3.12231,3.20072,3.26732,3.31537,3.36345,3.43738,3.51185,3.56706,3.58244,3.68457,3.78771,3.81647,3.88631,3.91461,4.01289,4.09067,4.14022,4.21861,4.29739,4.38391,4.42651,4.50619,4.61629,4.6969,4.71678,4.85908,4.94062,4.96786,5.07315,5.21855,5.26954,5.38442,5.49995,5.55117,5.67566,5.78439,5.86879,6.01984,6.10489,6.19005,6.34295,6.42867,6.58285,6.66897,6.85886,6.94558,7.13698,7.22426,7.41708,7.50468,7.69889,7.78679,8.018,8.17831,8.3029,8.53652,8.66171,8.89682,9.13282,9.36953,9.50533,9.77104,10.0097,10.2865,10.5641,10.8424,11.1214,11.4011,11.6813,12.0002,12.3675,12.8314,13.1143,13.6283,13.8832,14.409,15.6434,16.1826,16.6058,17.1172,17.6488,18.3473,19.0567,19.7473,20.6452,21.5048,22.4048,23.5033,24.6522,25.8219,27.3595,76.0194,75.946,30.8241,75.9103,75.8487,75.8609,75.8273,75.6581,76.332,76.1013,91.4294,91.4046,91.4127,91.3939,91.3481,91.4349,146.41,145.369,145.355,54.1523,49.9382,46.2363,44.6039,42.9663,42.9377,42.9911,42.8599,42.9149,42.89,42.8329,42.9128,42.8853,42.8537,42.8924,42.834,42.7902,42.8156,42.7908,42.8072,42.7463,42.6903,42.7922,42.7359,42.7112,42.7083, +-4.25007,-4.03921,-4.06938,-4.03067,-4.09332,-4.05381,-4.11453,-4.00768,-4.04203,-4.05894,-4.08321,-4.0741,-4.06448,-4.05435,-4.04369,-4.03252,-4.06009,-4.071,-4.05782,-4.04411,-4.0604,-4.0757,-4.06745,-4.01379,-4.0564,-4.09752,-4.05703,-4.05969,-4.01846,-4.04806,-4.05513,-4.03323,-4.03844,-4.04258,-4.05244,-4.02076,-4.02193,-4.04838,-4.04711,-3.99305,-4.04126,-4.03666,-3.98713,-3.99935,-4.04063,-4.00705,-4.02074,-4.03273,-3.99627,-4.01116,-4.01278,-3.99591,-4.02233,-4.00254,-3.98158,-4.00211,-3.97818,-3.99457,-3.96762,-3.99997,-3.96972,-3.9969,-3.96337,-3.98534,-3.94841,-3.96519,-3.92486,-3.95404,-3.94475,-3.9159,-3.93539,-3.90182,-3.91469,-3.92377,-3.92897,-3.88873,-3.89825,-3.89258,-3.89719,-3.89729,-3.89281,-3.88376,-3.87014,-3.85191,-3.84129,-3.84021,-3.86182,-3.82248,-3.84359,-3.78501,-3.79356,-3.97291,-3.95986,-3.91015,-3.87323,-3.83194,-3.81625,-3.79061,-3.74914,-3.73326,-3.69521,-3.64886,-3.6175,-3.5744,-3.51421,-3.48057,-8.99749,-8.31744,-3.10383,-6.97518,-6.30254,-5.63744,-4.96998,-4.29618,-3.66649,-2.99003,3.59227,4.39048,5.19079,5.99027,6.78833,7.59765,18.6256,22.3744,23.6725,13.251,13.1476,13.04,13.0008,12.9314,13.3325,13.7616,14.1331,14.5676,14.9778,15.3786,15.8314,16.2478,16.6649,17.1123,17.5239,17.9434,18.395,18.8284,19.2833,19.7063,20.134,20.6405,21.075,21.5282,21.9962, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, diff --git a/src/examples/test_laser_detector.cpp b/src/examples/test_laser_detector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45e05f89ad948c7cfe9e0041a812166adcf4bb8a --- /dev/null +++ b/src/examples/test_laser_detector.cpp @@ -0,0 +1,166 @@ +#include <algorithm> +#include <fstream> +#include <iostream> +#include <iterator> +#include <sstream> +#include <string> +#include <vector> +#include <eigen3/Eigen/Dense> + +//#include <graphics.h> +#include <GL/gl.h> +#include <GL/glut.h> +#include <GL/glu.h> + +//laserscanutils +#include "entities.h" +#include "clustering.h" + + +/* //TEST For graphical output +void setup() { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); } + +void display() + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glColor3f(0.0f, 0.0f, 0.0f); + glRectf(-0.75f,0.75f, 0.75f, -0.75f); + glutSwapBuffers(); + } +*/ + + + +void initParameters(laserscanutils::LaserDetectionParams & _parameters) +{ + _parameters.jump_thr = 0.9; + _parameters.max_num_cluster_points = 200; + _parameters.min_num_cluster_points = 5; + + //_parameters.print(); +} + + + +int main() +{ +/* //TEST For graphical output + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutInitWindowSize(800,600); + glutCreateWindow("Hello World"); + + setup(); + glutDisplayFunc(display); + glutMainLoop(); + */ + + // ***** INITIALIZATION ***** // + + laserscanutils::LaserDetectionParams alg_parameters; // structure with the parameters to tune the algorithm + laserscanutils::LaserDetectionStats alg_stats; // structure with the internal variables of the algorithm + initParameters(alg_parameters); + alg_parameters.print(); + + + // get laser Scan Parameters from real laser rosbag + // Laser 2D Scan Parameters : + // Angle min: -1.0472 + // Angle max: 0.610865 + // Angle step: 0.00436332 + // Scan time: 6.95332e-310 + // Range min: 0.1 + // Range max: 200 + // Range std dev: 6.91555e-310 + laserscanutils::ScanParams scan_params; + scan_params.angle_min_ = -1.0472; + scan_params.angle_max_ = 0.610865; + scan_params.angle_step_ = 0.00436332; + scan_params.scan_time_ = 0.01;//not relevant + scan_params.range_min_ = 0.1; + scan_params.range_max_ = 200; + scan_params.range_std_dev_ = 6.91555e-310; + scan_params.print(); + + + + // ***** READING LASER POINTS FOR TEST ***** // + std::vector<std::vector<float> > values; // temp for reading the file values + std::ifstream fin("/home/vvaquero/iri-lab/matlab/laser_detection_mat/testOneScanMatrix.txt"); // input file stream with name + + for (std::string line; std::getline(fin, line); ) + { + std::replace(line.begin(), line.end(), ',', ' '); + std::istringstream in(line); + values.push_back( + std::vector<float>(std::istream_iterator<float>(in), + std::istream_iterator<float>())); + } + + unsigned int rows = values.size(); + unsigned int columns = 0; + + for (unsigned int k = 0; k < rows; k++) + { + if (values[k].size() > columns) + columns = values[k].size(); + } + + std::cout << "Matrix Size = " << rows << "x" << columns <<std::endl; + Eigen::MatrixXs result(rows,columns); + + for (unsigned int i = 0; i < rows; i++) + for (unsigned int j = 0; j < columns; j++) + { + result(i,j) = values[i][j]; + } + + alg_stats.scanTotalPoints = 380; + alg_stats.filteredTotalPoints = columns; + + //std::cout << "Matrix = " << std::endl << result <<std::endl; + + + // | + // " + // Till here, everything is like a scan has been received and prefiltered + + + + // Finding clusters on the scan + laserscanutils::findClusters(alg_parameters, result,alg_stats); + + std::cout << "Clusters: " << std::endl << + " TotalFound = " << alg_stats.numberOfClusters << std::endl << + " Valid Ones = " << alg_stats.numberOfValidClusters << std::endl << + " Indexes = " ; + + for (unsigned int j = 0; j < alg_stats.cluster_indxs_.size(); j++) + { + std::pair<int,int> tempSeg = alg_stats.cluster_indxs_[j]; + std::cout << "(" << tempSeg.first << "," << tempSeg.second << ") | " ; + } + + // Prin Info to Matlab Script + laserscanutils::exportData2Matlab(result, alg_parameters, alg_stats, + "/home/vvaquero/iri-lab/matlab/laser_detection_mat/auto_laserDetection_ClustersScript.m"); + + + + + + + + + +// // TESTING LINE EXTRACTION + + +// // extract corners +// std::list<laserscanutils::Corner> corner_list; +// std::vector<double> corner_vector; +// laserscanutils::extractCorners(scan_params, alg_parameters, myScan, corner_list); + + + +} diff --git a/src/scan_basics.cpp b/src/scan_basics.cpp index 94146f8d19e0e5219dcb98a2587c897fdd1cb943..962a18f029ed32ca41cd3dd079cf2f30cacf8075 100644 --- a/src/scan_basics.cpp +++ b/src/scan_basics.cpp @@ -44,9 +44,7 @@ Eigen::MatrixXs laserscanutils::laserPolar2xy(const ScanParams & _params, std::v Eigen::Map<Eigen::MatrixXs> matrixReturn(xy_scan_points.data(),3, xy_scan_points.size()/3); -// std::cout << "EIGEN Matrix return: " << matrixReturn.col(3).transpose() << std::endl; return matrixReturn; // Remap the vector to the Matrix - } @@ -83,10 +81,10 @@ Eigen::MatrixXs laserscanutils::laserPolar2xy(const ScanParams & _params, const -// VV Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. +// VV [To be deleted] Converts ranges from a laserScan to homogeneous coordinates and save it to a matrix of same size than ranges size, returning index till valid values. unsigned int laserscanutils::ranges2xyh(const ScanParams & _params, std::vector<float> & _ranges, Eigen::MatrixXs & _points) { - assert( (_ranges.size() == _points.cols() ) &&(_points.rows() == 3) &&("Error: [laserPolar2xy] points Matrix size is different than number of ranges. Wrong Matrix Size.")); + //assert( (_ranges.size() == _points.cols() ) &&(_points.rows() == 3) &&("Error: [laserPolar2xy] points Matrix size is different than number of ranges. Wrong Matrix Size.")); double thetaPos = 0.0; unsigned int matPosition = 0; @@ -109,8 +107,6 @@ unsigned int laserscanutils::ranges2xyh(const ScanParams & _params, std::vector< }//END for return matPosition-1; // Remap the vector to the Matrix - Accounting for 0 - - }