laserscanthread.cpp
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         //Ausgabe Rohdaten & Mittelung
00148         for(unsigned int i=0;i<msg->ranges.size();i++) {
00149           //Da die Daten spiegelverkehrt geliefert werden müssen zudem die Werte ungedreht werden
00150           data_raw[i] = (double)msg->ranges[msg->ranges.size() - i - 1];
00151           //Mittelung
00152           oldValue =  rotatingAccumulationWindow[stepNumber][i];
00153           newValue = data_raw[i];
00154           averagedRanges[i] = averagedRanges[i] + (newValue - oldValue) / (double)(AVERAGINGWINDOW);
00155           //Speicherung der neuen Werte im rotierenden Fenster
00156           rotatingAccumulationWindow[stepNumber][i] = newValue;
00157         }
00158 
00159         if (stepNumber % 5 == 0)
00160         {
00161             /*for(unsigned int i=0;i<msg->ranges.size();i++)
00162             {
00163                 averagedRanges[i] = averagedRanges[i] -
00164 
00165                 averagedRanges[i] = 0;
00166                 for(unsigned int j=0;j<AVERAGINGWINDOW;j++)
00167                 {
00168                     averagedRanges[i] += rotatingAccumulationWindow[j][i];
00169                 }
00170                 averagedRanges[i] /= (float)AVERAGINGWINDOW;
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           //Datenfenster verarbeiten
00184           segments.clear();
00185           segmentsizes.clear();
00186           segmentdistance.clear();
00187 
00188           sensor_msgs::LaserScan avgScan = *msg;
00189           //Ausgabe gemittelte Daten
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           //Gaußfilterung
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           //Ausgabe gefilterte Daten
00211           for(unsigned int i=0;i<msg->ranges.size();i++) {
00212               data_filtered[i] = filteredRanges[i];
00213 
00214               //TEST: Gaußfilter ignorieren
00215               filteredRanges[i] = averagedRanges[i];
00216 
00217               data_segments[i]  = 0;
00218               data_edges[i]  = 0;
00219           }
00220           //Koordinatentransformation
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           //Segmentierung
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               //distance = std::abs(filteredRanges[i] * sin(data_field_size*msg->angle_increment) - filteredRanges[i+1]);
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           //Suche nach rechtem Winkel
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)       //Nur Bereiche untersuchen, die ausreichend groß sind
00276                   {
00277                       currentBestVariance = std::numeric_limits<double>::max();
00278                       segmentFound = false;
00279                       //Publish border elements
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) //Berechnung der linken Seite
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) {   //Rechter Winkel gefunden
00350                                               // Nur vom Scanner weg ausgerichtete Winkel erfassen
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                       //Wenn Dreieck für aktuelles Segment gefunden wurde, trage dies in die Lösungsliste ein
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 


asr_mild_calibration_tool
Author(s): Aumann Florian, Heller Florian, Meißner Pascal
autogenerated on Thu Jun 6 2019 21:22:44