Go to the documentation of this file.00001
00018 #include <laserscanthread.h>
00019 #include <math.h>
00020 #include <iostream>
00021 #include <limits>
00022 #include <MathHelpers/Resectionsolver/resectionsolver.h>
00023 #ifndef Q_MOC_RUN
00024 #include <visualization_msgs/Marker.h>
00025 #include <visualization_msgs/MarkerArray.h>
00026 #endif
00027
00028 LaserScanThread::LaserScanThread(Abstract_LaserScanner* scanner, double segmentation_lambda, double maxVarianceFilter, double maxAngleDeviation, double variationStep, int variationStepCount)
00029 {
00030 this->scanner = scanner;
00031 data_field_size = scanner->calibration_scan_values;
00032 angle_spread = scanner->calibration_angle_spread;
00033 starting_angle = scanner->calibration_starting_angle;
00034 dx = new double[data_field_size];
00035 data_raw = new double[data_field_size];
00036 data_avg = new double[data_field_size];
00037 data_filtered = new double[data_field_size];
00038 data_segments = new double[data_field_size];
00039 data_edges = new double[data_field_size];
00040
00041 averagedRanges = new double[data_field_size];
00042 for (unsigned int i = 0; i< AVERAGINGWINDOW; i++)
00043 {
00044 rotatingAccumulationWindow[i] = new double[data_field_size];
00045 for (unsigned int j = 0; j< data_field_size; j++)
00046 {
00047 rotatingAccumulationWindow[i][j] = 0.0;
00048 }
00049 }
00050 filteredRanges = new double[data_field_size];
00051 coordinates = new Eigen::Vector2d[data_field_size];
00052
00053 for(unsigned int i = 0; i< data_field_size; i++)
00054 {
00055 dx[i] = starting_angle + (double)i * (double)angle_spread/data_field_size;
00056 }
00057
00058 scanDataPublisher = nh.advertise<sensor_msgs::LaserScan>("average_scan_data", 1000);
00059 segmentDataPublisher = nh.advertise<visualization_msgs::MarkerArray>("segmented_scan_data", 1000);
00060 segmentBorderPublisher = nh.advertise<visualization_msgs::MarkerArray>("segment_border_scan_data", 1000);
00061
00062 linearApproximator = new LinearApproximator();
00063 this->variationStepCount = variationStepCount;
00064
00065 ROS_DEBUG_STREAM("segmentation_lambda : " << segmentation_lambda);
00066 ROS_DEBUG_STREAM("maxVarianceFilter : " << maxVarianceFilter);
00067 ROS_DEBUG_STREAM("maxAngleDeviation : " << maxAngleDeviation);
00068 ROS_DEBUG_STREAM("variationStep : " << variationStep);
00069 ROS_DEBUG_STREAM("variationStepCount : " << variationStepCount);
00070
00071 this->segmentation_lambda = segmentation_lambda;
00072 this->maxVarianceFilter = maxVarianceFilter;
00073 this->maxAngleDeviation = maxAngleDeviation;
00074 this->variationStep = variationStep;
00075 calculateGaussianMatrix();
00076 ROS_INFO("Thread started");
00077 }
00078
00079 LaserScanThread::~LaserScanThread()
00080 {
00081 for (unsigned int i = 0; i< AVERAGINGWINDOW; i++)
00082 {
00083 delete [] rotatingAccumulationWindow[i];
00084 rotatingAccumulationWindow[i] = NULL;
00085 }
00086 delete [] dx;
00087 dx = NULL;
00088 delete [] data_raw;
00089 data_raw = NULL;
00090 delete [] data_avg;
00091 data_avg = NULL;
00092 delete [] data_filtered;
00093 data_filtered = NULL;
00094 delete [] data_segments;
00095 data_segments = NULL;
00096 delete [] data_edges;
00097 data_edges = NULL;
00098 delete [] averagedRanges;
00099 averagedRanges = NULL;
00100 delete [] filteredRanges;
00101 filteredRanges = NULL;
00102 delete [] coordinates;
00103 coordinates = NULL;
00104 }
00105
00106 void LaserScanThread::stop()
00107 {
00108 ROS_INFO("Laserscan thread stopping...");
00109 scanner->stop();
00110 ROS_INFO("Lascerscan thread stopped..");
00111 }
00112
00113 void LaserScanThread::calculateGaussianMatrix()
00114 {
00115 double x;
00116 gaussFactor = 0;
00117 for (unsigned int i = 0; i < 2*GAUSSIANFIELDSIZE+1; i++)
00118 {
00119 x = (double)(i - (int)((2*GAUSSIANFIELDSIZE+1) / 2));
00120
00121 feld[i] = exp((-1.0f) * (x * x) / (2 * sigma * sigma));
00122 feld[i] = feld[i] / (2 * M_PI * sigma * sigma);
00123 gaussFactor += feld[i];
00124 }
00125 gaussFactor = 1/gaussFactor;
00126 }
00127
00128 void LaserScanThread::run()
00129 {
00130 launchSICK();
00131 }
00132
00133 void LaserScanThread::launchSICK()
00134 {
00135 ROS_INFO_STREAM("Scanner field size: " << data_field_size);
00136 stepNumber = 1;
00137 connect(scanner, SIGNAL(newData(const sensor_msgs::LaserScan::ConstPtr&)), this, SLOT(laserScanCallback(const sensor_msgs::LaserScan::ConstPtr&)));
00138 ROS_INFO("Scanner connecting");
00139 scanner->run();
00140 }
00141
00142 void LaserScanThread::laserScanCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
00143 {
00144 if (msg->ranges.size() > 0)
00145 {
00146 double oldValue, newValue;
00147
00148 for(unsigned int i=0;i<msg->ranges.size();i++) {
00149
00150 data_raw[i] = (double)msg->ranges[msg->ranges.size() - i - 1];
00151
00152 oldValue = rotatingAccumulationWindow[stepNumber][i];
00153 newValue = data_raw[i];
00154 averagedRanges[i] = averagedRanges[i] + (newValue - oldValue) / (double)(AVERAGINGWINDOW);
00155
00156 rotatingAccumulationWindow[stepNumber][i] = newValue;
00157 }
00158
00159 if (stepNumber % 5 == 0)
00160 {
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 for(unsigned int i=0;i<msg->ranges.size();i++)
00175 {
00176 averagedRanges[i] = 0;
00177 for(unsigned int j=0;j<AVERAGINGWINDOW;j++)
00178 {
00179 averagedRanges[i] += rotatingAccumulationWindow[j][i];
00180 }
00181 averagedRanges[i] /= (float)AVERAGINGWINDOW;
00182 }
00183
00184 segments.clear();
00185 segmentsizes.clear();
00186 segmentdistance.clear();
00187
00188 sensor_msgs::LaserScan avgScan = *msg;
00189
00190 for(unsigned int i=0;i<msg->ranges.size();i++) {
00191 data_avg[i] = (double)averagedRanges[i];
00192 avgScan.ranges[i] = data_avg[msg->ranges.size() - i - 1];
00193 }
00194 scanDataPublisher.publish(avgScan);
00195
00196
00197
00198 double x;
00199 for(unsigned int i=0;i<GAUSSIANFIELDSIZE;i++) {filteredRanges[i] = averagedRanges[i];}
00200 for(unsigned int i=GAUSSIANFIELDSIZE;i<data_field_size -GAUSSIANFIELDSIZE;i++) {
00201 x = 0;
00202 for (int j = -(int)GAUSSIANFIELDSIZE; j<=(int)GAUSSIANFIELDSIZE; j++)
00203 {
00204 x += gaussFactor*averagedRanges[i+j]*feld[j+GAUSSIANFIELDSIZE];
00205 }
00206
00207 filteredRanges[i] = x;
00208 }
00209 for(unsigned int i=data_field_size-GAUSSIANFIELDSIZE;i<data_field_size;i++) {filteredRanges[i] = averagedRanges[i];}
00210
00211 for(unsigned int i=0;i<msg->ranges.size();i++) {
00212 data_filtered[i] = filteredRanges[i];
00213
00214
00215 filteredRanges[i] = averagedRanges[i];
00216
00217 data_segments[i] = 0;
00218 data_edges[i] = 0;
00219 }
00220
00221 for(unsigned int i=0;i<data_field_size; i++)
00222 {
00223 coordinates[i] = Eigen::Vector2d(sin(msg->angle_increment*i), cos(msg->angle_increment*i)) * filteredRanges[i];
00224 }
00225
00226
00227 visualization_msgs::MarkerArray myArray;
00228
00229 std::vector<unsigned int> segments;
00230 float distance;
00231 unsigned int currentPointCloudIndex = 0;
00232 for (unsigned int i=0;i<data_field_size-1;i++)
00233 {
00234 visualization_msgs::Marker marker;
00235 marker.header.frame_id = "base_laser";
00236 marker.header.stamp = ros::Time();
00237 marker.ns = "segmentation";
00238 marker.id = myArray.markers.size();
00239 marker.type = visualization_msgs::Marker::SPHERE;
00240 marker.action = visualization_msgs::Marker::ADD;
00241 marker.pose.position.x = coordinates[i][0];
00242 marker.pose.position.y = coordinates[i][1];
00243 marker.pose.position.z = 0;
00244 marker.scale.x = markersize;
00245 marker.scale.y = markersize;
00246 marker.scale.z = markersize;
00247 marker.color.a = 1.0;
00248 marker.color.r = (double)(currentPointCloudIndex % 3 == 0);
00249 marker.color.g = (double)(currentPointCloudIndex % 3 == 1);
00250 marker.color.b = (double)(currentPointCloudIndex % 3 == 2);
00251 myArray.markers.push_back(marker);
00252 distance = sqrt(pow(coordinates[i][0] - coordinates[i+1][0], 2) +pow(coordinates[i][1]-coordinates[i+1][1], 2));
00253
00254 if (distance > segmentation_lambda) {
00255 segments.push_back(i);
00256 segments.push_back(i+1);
00257 data_segments[i] = filteredRanges[i];
00258 data_segments[i+1] = filteredRanges[i+1];
00259 currentPointCloudIndex ++;
00260 }
00261 }
00262 segmentDataPublisher.publish(myArray);
00263
00264 edgesfound.clear();
00265 double varianceLeft, varianceRight, varianceTotal, currentBestVariance;
00266 bool segmentFound;
00267 Eigen::Vector2d p1, p2, p3;
00268
00269 visualization_msgs::MarkerArray borderArray;
00270
00271 if (segments.size()> 1)
00272 {
00273 for (unsigned int j=0; j<segments.size()-1; j++)
00274 {
00275 if (segments[j+1] - segments[j] >= DETECTIONWINDOW*2+1)
00276 {
00277 currentBestVariance = std::numeric_limits<double>::max();
00278 segmentFound = false;
00279
00280 for (unsigned int i = 0;i < DETECTIONWINDOW;i++)
00281 {
00282 visualization_msgs::Marker leftPoint, rightPoint;
00283 leftPoint.header.frame_id = rightPoint.header.frame_id = "base_laser";
00284 leftPoint.header.stamp = rightPoint.header.stamp = ros::Time();
00285 leftPoint.ns = rightPoint.ns = "segmentation";
00286 leftPoint.id = borderArray.markers.size();
00287 rightPoint.id = borderArray.markers.size() + 1;
00288 leftPoint.type = rightPoint.type = visualization_msgs::Marker::SPHERE;
00289 leftPoint.action = rightPoint.action = visualization_msgs::Marker::ADD;
00290 leftPoint.pose.position.x = coordinates[i+segments[j]][0];
00291 leftPoint.pose.position.y = coordinates[i+segments[j]][1];
00292 rightPoint.pose.position.x = coordinates[-i+segments[j+1]][0];
00293 rightPoint.pose.position.y = coordinates[-i+segments[j+1]][1];
00294 rightPoint.pose.position.z = leftPoint.pose.position.z = 0;
00295 leftPoint.scale.x = rightPoint.scale.x = markersize;
00296 leftPoint.scale.y = rightPoint.scale.y = markersize;
00297 leftPoint.scale.z = rightPoint.scale.z = markersize;
00298 leftPoint.color.r = rightPoint.color.r = 0.0;
00299 leftPoint.color.g = rightPoint.color.g = 0.0;
00300 leftPoint.color.b = rightPoint.color.b = 0.0;
00301 leftPoint.color.a = rightPoint.color.a = 1.0;
00302 borderArray.markers.push_back(leftPoint);
00303 borderArray.markers.push_back(rightPoint);
00304 }
00305
00306 for (unsigned int i=DETECTIONWINDOW+segments[j];i<segments[j+1]-DETECTIONWINDOW;i++)
00307 {
00308 visualization_msgs::Marker midPoint;
00309 midPoint.header.frame_id = "base_laser";
00310 midPoint.header.stamp = ros::Time();
00311 midPoint.ns = "segmentation";
00312 midPoint.id = borderArray.markers.size();
00313 midPoint.type = visualization_msgs::Marker::SPHERE;
00314 midPoint.action = visualization_msgs::Marker::ADD;
00315 midPoint.pose.position.x = coordinates[i][0];
00316 midPoint.pose.position.y = coordinates[i][1];
00317 midPoint.pose.position.z = 0;
00318 midPoint.scale.x = markersize;
00319 midPoint.scale.y = markersize;
00320 midPoint.scale.z = markersize;
00321 midPoint.color.r = 1.0;
00322 midPoint.color.g = 1.0;
00323 midPoint.color.b = 1.0;
00324 midPoint.color.a = 1.0;
00325 borderArray.markers.push_back(midPoint);
00326
00327 Eigen::Vector2d center;
00328 for (int varHorizontal = -variationStepCount; varHorizontal <= variationStepCount; varHorizontal++)
00329 {
00330 for (int varVertical = -variationStepCount; varVertical <= variationStepCount; varVertical++)
00331 {
00332 center = Eigen::Vector2d((double)varHorizontal*variationStep, (double)varVertical*variationStep) + coordinates[i];
00333 Eigen::Vector2d left, right;
00334 ApproximationResult approximationLeft;
00335 approximationLeft = linearApproximator->calculateApproximation(coordinates, segments[j], i, center);
00336 varianceLeft = approximationLeft.variance;
00337 if (varianceLeft < maxVarianceFilter)
00338 {
00339 left = approximationLeft.approximatedVector;
00340 ApproximationResult approximationRight;
00341 approximationRight = linearApproximator->calculateApproximation(coordinates, i+1, segments[j+1]+1, center);
00342 varianceRight = approximationRight.variance;
00343
00344 varianceTotal = varianceLeft* (i - segments[j]) + varianceRight * (segments[j+1] - i);
00345 varianceTotal /= (double)(segments[j+1] - segments[j] - 1);
00346 if (varianceRight < maxVarianceFilter && currentBestVariance > varianceTotal)
00347 {
00348 right = approximationRight.approximatedVector;
00349 if (fabs(left.dot(right)/(left.norm()*right.norm())) < maxAngleDeviation) {
00350
00351 if (filteredRanges[(int)segments[j]] < filteredRanges[i] && filteredRanges[(int)segments[j+1]] < filteredRanges[i])
00352 {
00353 currentBestVariance = varianceTotal;
00354 segmentFound = true;
00355 p1 = center + left;
00356 p2 = center;
00357 p3 = center + right;
00358
00359 for (unsigned int k = segments[j]; k <= segments[j+1]; k++)
00360 {
00361 data_edges[k] = filteredRanges[k];
00362 }
00363 }
00364 }
00365 }
00366 }
00367 }
00368 }
00369 }
00370
00371 if (segmentFound)
00372 {
00373 edgesfound.push_back(p1);
00374 edgesfound.push_back(p2);
00375 edgesfound.push_back(p3);
00376 }
00377 }
00378 }
00379
00380 }
00381 segmentBorderPublisher.publish(borderArray);
00382 trianglesFound(&(edgesfound));
00383 }
00384
00385 stepNumber ++;
00386 stepNumber = stepNumber % AVERAGINGWINDOW;
00387 valueChanged();
00388 }
00389 }
00390