laserscanthread.cpp
Go to the documentation of this file.
1 
18 #include <laserscanthread.h>
19 #include <math.h>
20 #include <iostream>
21 #include <limits>
23 #ifndef Q_MOC_RUN
24 #include <visualization_msgs/Marker.h>
25 #include <visualization_msgs/MarkerArray.h>
26 #endif
27 
28 LaserScanThread::LaserScanThread(Abstract_LaserScanner* scanner, double segmentation_lambda, double maxVarianceFilter, double maxAngleDeviation, double variationStep, int variationStepCount)
29 {
30  this->scanner = scanner;
34  dx = new double[data_field_size];
35  data_raw = new double[data_field_size];
36  data_avg = new double[data_field_size];
37  data_filtered = new double[data_field_size];
38  data_segments = new double[data_field_size];
39  data_edges = new double[data_field_size];
40 
41  averagedRanges = new double[data_field_size];
42  for (unsigned int i = 0; i< AVERAGINGWINDOW; i++)
43  {
45  for (unsigned int j = 0; j< data_field_size; j++)
46  {
47  rotatingAccumulationWindow[i][j] = 0.0;
48  }
49  }
50  filteredRanges = new double[data_field_size];
51  coordinates = new Eigen::Vector2d[data_field_size];
52 
53  for(unsigned int i = 0; i< data_field_size; i++)
54  {
55  dx[i] = starting_angle + (double)i * (double)angle_spread/data_field_size;
56  }
57 
58  scanDataPublisher = nh.advertise<sensor_msgs::LaserScan>("average_scan_data", 1000);
59  segmentDataPublisher = nh.advertise<visualization_msgs::MarkerArray>("segmented_scan_data", 1000);
60  segmentBorderPublisher = nh.advertise<visualization_msgs::MarkerArray>("segment_border_scan_data", 1000);
61 
63  this->variationStepCount = variationStepCount;
64 
65  ROS_DEBUG_STREAM("segmentation_lambda : " << segmentation_lambda);
66  ROS_DEBUG_STREAM("maxVarianceFilter : " << maxVarianceFilter);
67  ROS_DEBUG_STREAM("maxAngleDeviation : " << maxAngleDeviation);
68  ROS_DEBUG_STREAM("variationStep : " << variationStep);
69  ROS_DEBUG_STREAM("variationStepCount : " << variationStepCount);
70 
71  this->segmentation_lambda = segmentation_lambda;
72  this->maxVarianceFilter = maxVarianceFilter;
73  this->maxAngleDeviation = maxAngleDeviation;
74  this->variationStep = variationStep;
76  ROS_INFO("Thread started");
77 }
78 
80 {
81  for (unsigned int i = 0; i< AVERAGINGWINDOW; i++)
82  {
83  delete [] rotatingAccumulationWindow[i];
85  }
86  delete [] dx;
87  dx = NULL;
88  delete [] data_raw;
89  data_raw = NULL;
90  delete [] data_avg;
91  data_avg = NULL;
92  delete [] data_filtered;
93  data_filtered = NULL;
94  delete [] data_segments;
95  data_segments = NULL;
96  delete [] data_edges;
97  data_edges = NULL;
98  delete [] averagedRanges;
99  averagedRanges = NULL;
100  delete [] filteredRanges;
101  filteredRanges = NULL;
102  delete [] coordinates;
103  coordinates = NULL;
104 }
105 
107 {
108  ROS_INFO("Laserscan thread stopping...");
109  scanner->stop();
110  ROS_INFO("Lascerscan thread stopped..");
111 }
112 
114 {
115  double x;
116  gaussFactor = 0;
117  for (unsigned int i = 0; i < 2*GAUSSIANFIELDSIZE+1; i++)
118  {
119  x = (double)(i - (int)((2*GAUSSIANFIELDSIZE+1) / 2));
120 
121  feld[i] = exp((-1.0f) * (x * x) / (2 * sigma * sigma));
122  feld[i] = feld[i] / (2 * M_PI * sigma * sigma);
123  gaussFactor += feld[i];
124  }
126 }
127 
129 {
130  launchSICK();
131 }
132 
134 {
135  ROS_INFO_STREAM("Scanner field size: " << data_field_size);
136  stepNumber = 1;
137  connect(scanner, SIGNAL(newData(const sensor_msgs::LaserScan::ConstPtr&)), this, SLOT(laserScanCallback(const sensor_msgs::LaserScan::ConstPtr&)));
138  ROS_INFO("Scanner connecting");
139  scanner->run();
140 }
141 
142 void LaserScanThread::laserScanCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
143 {
144  if (msg->ranges.size() > 0)
145  {
146  double oldValue, newValue;
147  //Ausgabe Rohdaten & Mittelung
148  for(unsigned int i=0;i<msg->ranges.size();i++) {
149  //Da die Daten spiegelverkehrt geliefert werden müssen zudem die Werte ungedreht werden
150  data_raw[i] = (double)msg->ranges[msg->ranges.size() - i - 1];
151  //Mittelung
152  oldValue = rotatingAccumulationWindow[stepNumber][i];
153  newValue = data_raw[i];
154  averagedRanges[i] = averagedRanges[i] + (newValue - oldValue) / (double)(AVERAGINGWINDOW);
155  //Speicherung der neuen Werte im rotierenden Fenster
156  rotatingAccumulationWindow[stepNumber][i] = newValue;
157  }
158 
159  if (stepNumber % 5 == 0)
160  {
161  /*for(unsigned int i=0;i<msg->ranges.size();i++)
162  {
163  averagedRanges[i] = averagedRanges[i] -
164 
165  averagedRanges[i] = 0;
166  for(unsigned int j=0;j<AVERAGINGWINDOW;j++)
167  {
168  averagedRanges[i] += rotatingAccumulationWindow[j][i];
169  }
170  averagedRanges[i] /= (float)AVERAGINGWINDOW;
171  }*/
172 
173 
174  for(unsigned int i=0;i<msg->ranges.size();i++)
175  {
176  averagedRanges[i] = 0;
177  for(unsigned int j=0;j<AVERAGINGWINDOW;j++)
178  {
180  }
181  averagedRanges[i] /= (float)AVERAGINGWINDOW;
182  }
183  //Datenfenster verarbeiten
184  segments.clear();
185  segmentsizes.clear();
186  segmentdistance.clear();
187 
188  sensor_msgs::LaserScan avgScan = *msg;
189  //Ausgabe gemittelte Daten
190  for(unsigned int i=0;i<msg->ranges.size();i++) {
191  data_avg[i] = (double)averagedRanges[i];
192  avgScan.ranges[i] = data_avg[msg->ranges.size() - i - 1];
193  }
194  scanDataPublisher.publish(avgScan);
195 
196 
197  //Gaußfilterung
198  double x;
199  for(unsigned int i=0;i<GAUSSIANFIELDSIZE;i++) {filteredRanges[i] = averagedRanges[i];}
200  for(unsigned int i=GAUSSIANFIELDSIZE;i<data_field_size -GAUSSIANFIELDSIZE;i++) {
201  x = 0;
202  for (int j = -(int)GAUSSIANFIELDSIZE; j<=(int)GAUSSIANFIELDSIZE; j++)
203  {
205  }
206 
207  filteredRanges[i] = x;
208  }
209  for(unsigned int i=data_field_size-GAUSSIANFIELDSIZE;i<data_field_size;i++) {filteredRanges[i] = averagedRanges[i];}
210  //Ausgabe gefilterte Daten
211  for(unsigned int i=0;i<msg->ranges.size();i++) {
213 
214  //TEST: Gaußfilter ignorieren
216 
217  data_segments[i] = 0;
218  data_edges[i] = 0;
219  }
220  //Koordinatentransformation
221  for(unsigned int i=0;i<data_field_size; i++)
222  {
223  coordinates[i] = Eigen::Vector2d(sin(msg->angle_increment*i), cos(msg->angle_increment*i)) * filteredRanges[i];
224  }
225 
226  //Segmentierung
227  visualization_msgs::MarkerArray myArray;
228 
229  std::vector<unsigned int> segments;
230  float distance;
231  unsigned int currentPointCloudIndex = 0;
232  for (unsigned int i=0;i<data_field_size-1;i++)
233  {
234  visualization_msgs::Marker marker;
235  marker.header.frame_id = "base_laser";
236  marker.header.stamp = ros::Time();
237  marker.ns = "segmentation";
238  marker.id = myArray.markers.size();
239  marker.type = visualization_msgs::Marker::SPHERE;
240  marker.action = visualization_msgs::Marker::ADD;
241  marker.pose.position.x = coordinates[i][0];
242  marker.pose.position.y = coordinates[i][1];
243  marker.pose.position.z = 0;
244  marker.scale.x = markersize;
245  marker.scale.y = markersize;
246  marker.scale.z = markersize;
247  marker.color.a = 1.0;
248  marker.color.r = (double)(currentPointCloudIndex % 3 == 0);
249  marker.color.g = (double)(currentPointCloudIndex % 3 == 1);
250  marker.color.b = (double)(currentPointCloudIndex % 3 == 2);
251  myArray.markers.push_back(marker);
252  distance = sqrt(pow(coordinates[i][0] - coordinates[i+1][0], 2) +pow(coordinates[i][1]-coordinates[i+1][1], 2));
253  //distance = std::abs(filteredRanges[i] * sin(data_field_size*msg->angle_increment) - filteredRanges[i+1]);
254  if (distance > segmentation_lambda) {
255  segments.push_back(i);
256  segments.push_back(i+1);
258  data_segments[i+1] = filteredRanges[i+1];
259  currentPointCloudIndex ++;
260  }
261  }
262  segmentDataPublisher.publish(myArray);
263 
264  edgesfound.clear();
265  double varianceLeft, varianceRight, varianceTotal, currentBestVariance;
266  bool segmentFound;
267  Eigen::Vector2d p1, p2, p3;
268 
269  visualization_msgs::MarkerArray borderArray;
270  //Suche nach rechtem Winkel
271  if (segments.size()> 1)
272  {
273  for (unsigned int j=0; j<segments.size()-1; j++)
274  {
275  if (segments[j+1] - segments[j] >= DETECTIONWINDOW*2+1) //Nur Bereiche untersuchen, die ausreichend groß sind
276  {
277  currentBestVariance = std::numeric_limits<double>::max();
278  segmentFound = false;
279  //Publish border elements
280  for (unsigned int i = 0;i < DETECTIONWINDOW;i++)
281  {
282  visualization_msgs::Marker leftPoint, rightPoint;
283  leftPoint.header.frame_id = rightPoint.header.frame_id = "base_laser";
284  leftPoint.header.stamp = rightPoint.header.stamp = ros::Time();
285  leftPoint.ns = rightPoint.ns = "segmentation";
286  leftPoint.id = borderArray.markers.size();
287  rightPoint.id = borderArray.markers.size() + 1;
288  leftPoint.type = rightPoint.type = visualization_msgs::Marker::SPHERE;
289  leftPoint.action = rightPoint.action = visualization_msgs::Marker::ADD;
290  leftPoint.pose.position.x = coordinates[i+segments[j]][0];
291  leftPoint.pose.position.y = coordinates[i+segments[j]][1];
292  rightPoint.pose.position.x = coordinates[-i+segments[j+1]][0];
293  rightPoint.pose.position.y = coordinates[-i+segments[j+1]][1];
294  rightPoint.pose.position.z = leftPoint.pose.position.z = 0;
295  leftPoint.scale.x = rightPoint.scale.x = markersize;
296  leftPoint.scale.y = rightPoint.scale.y = markersize;
297  leftPoint.scale.z = rightPoint.scale.z = markersize;
298  leftPoint.color.r = rightPoint.color.r = 0.0;
299  leftPoint.color.g = rightPoint.color.g = 0.0;
300  leftPoint.color.b = rightPoint.color.b = 0.0;
301  leftPoint.color.a = rightPoint.color.a = 1.0;
302  borderArray.markers.push_back(leftPoint);
303  borderArray.markers.push_back(rightPoint);
304  }
305 
306  for (unsigned int i=DETECTIONWINDOW+segments[j];i<segments[j+1]-DETECTIONWINDOW;i++)
307  {
308  visualization_msgs::Marker midPoint;
309  midPoint.header.frame_id = "base_laser";
310  midPoint.header.stamp = ros::Time();
311  midPoint.ns = "segmentation";
312  midPoint.id = borderArray.markers.size();
313  midPoint.type = visualization_msgs::Marker::SPHERE;
314  midPoint.action = visualization_msgs::Marker::ADD;
315  midPoint.pose.position.x = coordinates[i][0];
316  midPoint.pose.position.y = coordinates[i][1];
317  midPoint.pose.position.z = 0;
318  midPoint.scale.x = markersize;
319  midPoint.scale.y = markersize;
320  midPoint.scale.z = markersize;
321  midPoint.color.r = 1.0;
322  midPoint.color.g = 1.0;
323  midPoint.color.b = 1.0;
324  midPoint.color.a = 1.0;
325  borderArray.markers.push_back(midPoint);
326 
327  Eigen::Vector2d center;
328  for (int varHorizontal = -variationStepCount; varHorizontal <= variationStepCount; varHorizontal++)
329  {
330  for (int varVertical = -variationStepCount; varVertical <= variationStepCount; varVertical++)
331  {
332  center = Eigen::Vector2d((double)varHorizontal*variationStep, (double)varVertical*variationStep) + coordinates[i];
333  Eigen::Vector2d left, right;
334  ApproximationResult approximationLeft;
335  approximationLeft = linearApproximator->calculateApproximation(coordinates, segments[j], i, center);
336  varianceLeft = approximationLeft.variance;
337  if (varianceLeft < maxVarianceFilter) //Berechnung der linken Seite
338  {
339  left = approximationLeft.approximatedVector;
340  ApproximationResult approximationRight;
341  approximationRight = linearApproximator->calculateApproximation(coordinates, i+1, segments[j+1]+1, center);
342  varianceRight = approximationRight.variance;
343 
344  varianceTotal = varianceLeft* (i - segments[j]) + varianceRight * (segments[j+1] - i);
345  varianceTotal /= (double)(segments[j+1] - segments[j] - 1);
346  if (varianceRight < maxVarianceFilter && currentBestVariance > varianceTotal)
347  {
348  right = approximationRight.approximatedVector;
349  if (fabs(left.dot(right)/(left.norm()*right.norm())) < maxAngleDeviation) { //Rechter Winkel gefunden
350  // Nur vom Scanner weg ausgerichtete Winkel erfassen
351  if (filteredRanges[(int)segments[j]] < filteredRanges[i] && filteredRanges[(int)segments[j+1]] < filteredRanges[i])
352  {
353  currentBestVariance = varianceTotal;
354  segmentFound = true;
355  p1 = center + left;
356  p2 = center;
357  p3 = center + right;
358 
359  for (unsigned int k = segments[j]; k <= segments[j+1]; k++)
360  {
361  data_edges[k] = filteredRanges[k];
362  }
363  }
364  }
365  }
366  }
367  }
368  }
369  }
370  //Wenn Dreieck für aktuelles Segment gefunden wurde, trage dies in die Lösungsliste ein
371  if (segmentFound)
372  {
373  edgesfound.push_back(p1);
374  edgesfound.push_back(p2);
375  edgesfound.push_back(p3);
376  }
377  }
378  }
379 
380  }
381  segmentBorderPublisher.publish(borderArray);
383  }
384 
385  stepNumber ++;
387  valueChanged();
388  }
389 }
390 
Eigen::Vector2d approximatedVector
void publish(const boost::shared_ptr< M > &message) const
f
LaserScanThread(Abstract_LaserScanner *scanner, double segmentation_lambda, double maxVarianceFilter, double maxAngleDeviation, double variationStep, int variationStepCount)
ros::Publisher scanDataPublisher
void calculateGaussianMatrix()
static constexpr unsigned int GAUSSIANFIELDSIZE
LinearApproximator * linearApproximator
double maxVarianceFilter
unsigned int stepNumber
std::vector< int > segmentdistance
void trianglesFound(std::vector< Eigen::Vector2d, Eigen::aligned_allocator< Eigen::Vector2d > > *triangles)
static constexpr unsigned int DETECTIONWINDOW
double maxAngleDeviation
double segmentation_lambda
void laserScanCallback(const sensor_msgs::LaserScan::ConstPtr &msg)
double * rotatingAccumulationWindow[AVERAGINGWINDOW]
double feld[2 *GAUSSIANFIELDSIZE+1]
std::vector< float > segments
double * data_segments
virtual void run()=0
#define ROS_INFO(...)
static constexpr unsigned int AVERAGINGWINDOW
double * averagedRanges
Eigen::Vector2d * coordinates
double * filteredRanges
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_DEBUG_STREAM(args)
double * data_filtered
static constexpr double sigma
std::vector< int > segmentsizes
Abstract_LaserScanner * scanner
unsigned int data_field_size
#define ROS_INFO_STREAM(args)
std::vector< Eigen::Vector2d, Eigen::aligned_allocator< Eigen::Vector2d > > edgesfound
ros::NodeHandle nh
ApproximationResult calculateApproximation(Eigen::Vector2d *functionPoints, int startIndex, int endIndex, Eigen::Vector2d centerOffset)
ros::Publisher segmentBorderPublisher
virtual void stop()=0
ros::Publisher segmentDataPublisher


asr_mild_calibration_tool
Author(s): Aumann Florian, Heller Florian, Meißner Pascal
autogenerated on Mon Dec 2 2019 03:11:43