]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/hokuyo/shape-detect/shape_detect.h
27cec8e39e83fda7a8de26845a61ff7c9104ace0
[eurobot/public.git] / src / hokuyo / shape-detect / shape_detect.h
1 /**
2  * @file shape_detect.h
3  * @author Martin Synek
4  * @author Michal Sojka
5  * @date 11/02/25
6  *
7  * @brief Shape detection from laser scan data
8  */
9
10 /* Copyright: TODO
11  *
12  */
13
14 /**
15 \defgroup shapedet Shape detection
16
17 Library Shape detect is used for detection line segments
18 in measured data by laser scan (defaut constructor
19 is changed for Hokuyo).
20
21 Content:
22 - \ref shapedet_general
23 - \ref shapedet_debug_mode
24 - \ref shapedet_example
25 - \ref shapedet_ref
26
27 \section shapedet_general Introduction
28
29 The input is created by array laser_scan (type unsigned short) which contains
30 data expressed in polar coordinates. The first step is data conversion from 
31 polar coordinates to vector whose points are expressed in cartesian coordinates.
32 The section includes filtering of error scanned data which are lower level then 20.
33
34 In the next is divided pointvector in dependence on parametr max_distance_point.
35 Some line segment is searched by recursion in the individual parts of pointvector
36 by perpendicular line regression.
37 The line segment is detected or set is divided to achievement of parametersize
38 line_min_points.
39
40 The founded line is written into output vector lines. The method line_detect
41 is finished after research of all vectorparts. 
42
43 \section shapedet_debug_mode Debug mode
44
45 The debug mode permits detection of segment lines with connected laser scanner
46 or from scanned data, which are saved in a file. GNUPLOT can be used for graphical
47 output in debug mode or output vector can be saved in a file for next processing
48 in any application.
49
50 For setting above properties is used directives define GNUPLOT and OFFLINE.
51
52 For debugging can be used methods introduced in file main.cc.
53
54 \section shapedet_example Example
55
56 In the file main.cc are introduced examples of using class Shape_detect.
57 The first step is creation of classinstance by constructor calling
58 (default setting for Hokuyo or with applicable parameters). After that it is possible
59 preparation of output vector for saving founded segment line and calling method
60 shape_detect with applicable parameters.
61
62 The first example is work illustration with connected laser scanner Hokuyo.
63
64 \code
65 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
66                         void *recvCallBackParam)
67 {
68         Shape_detect sd;
69
70         struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
71         static int count = 0;
72
73         switch (info->status) {
74                 case NEW_DATA: {
75                         printf("Scan\n");
76                         if (++count >= 2) {
77                                 printf("Detect\n");
78                                 count = 0;
79                                 
80                                 std::vector<Shape_detect::Line> output;
81
82                                 sd.prepare((unsigned short) instance->data);
83                                 sd.line_detect(output);
84                         }
85                         break;
86                 }
87                 case DEADLINE:
88                         printf("Deadline\n");
89                         break;
90         }
91 }
92 \endcode
93
94 The second example shows values reading from datafile.
95
96 \code
97 Shape_detect sd;
98
99 unsigned short laser_scan[HOKUYO_ARRAY_SIZE];
100  
101 std::ifstream infile(argv[1], std::ios_base::in);
102
103 // line input file
104 std::string line;
105
106 // number from input file
107 int number;
108
109 int idx = 0;
110     
111 while (std::getline(infile, line, '\n')) {
112         std::stringstream strStream(line);
113         strStream >> number;
114         laser_scan[idx] = number;
115         idx++;
116 }
117         
118 std::vector<Shape_detect::Line> lines;
119 std::vector<Shape_detect::Arc> arcs;
120
121 // shape detect
122 sd.prepare(laser_scan);
123 sd.line_detect(lines);
124
125 \endcode
126
127 \section shapedet_ref References
128
129 Fast line, arc/circle and leg detection from laser scan data in a Player driver,
130 http://w3.ualg.pt/~dcastro/a1738.pdf
131
132 Mathpages, Perpendicular regression of a line,
133 http://mathpages.com/home/kmath110.htm
134
135  */
136
137 #ifndef SHAPE_DETECT
138 #define SHAPE_DETECT
139
140 #include <string>
141 #include <cstring>
142 #include <stdlib.h>
143 #include <fstream>
144 #include <iostream>
145 #include <sstream>
146 #include <math.h>
147 #include <vector>
148 #include <hokuyo.h>
149 #include <robot.h>
150 #include <robomath.h>
151 #include <robottype.h>
152 #include <roboorte_robottype.h>
153
154 /**
155  * Debug mode with GNUPLOT graph.
156  * True  -> Detected lines are painted by GNUPLOT.
157  * False -> Lines isn't painted.
158  * @ingroup shapedet
159  */
160 //#define GNUPLOT
161
162 /**
163  * Debug mode with connect Hokuyo.
164  * True  -> Hokuyo not connect and input data vector is reading from file.
165  * False -> Hokuyo is connect.
166  * @ingroup shapedet
167  */
168 #define OFFLINE 1
169
170 /**
171  * There are detected line segments in input array of measured data (laser_scan)
172  * by using perpendicular line regression.
173  * The output is formed by vector of type Line (so detected segment line - coordinates endpoints).
174  * @ingroup shapedet
175  */
176 class Shape_detect
177 {
178         public:
179                 /**
180                  * The constructor with default setting of detection properties (pro Hokuyo).
181                  * Line_min_points = 7
182                  * Line_error_threshold = 20
183                  * Max_distance_point = 300
184                  * @ingroup shapedet
185                  */
186                 Shape_detect (void);
187
188                 /**
189                  * The constructor for other setting than default setting of detection properties.
190                  * @param line_min_points the minimal number of points which can create segment line.
191                  * @param line_error_threshold the maximal pointerror from segment line of regression.
192                  * @param max_distance_point the maximal Euclidean distance of point.
193                  * @ingroup shapedet
194                  */
195                 Shape_detect (int line_min_points, int line_error_threshold, int max_distance_point);
196
197                 /**
198                  * General equation of line -> Ax + By + C = 0.
199                  * Is used for calculation of lines intersection.
200                  * @ingroup shapedet
201                  */
202                 typedef struct {float a,b,c;} General_form;
203
204                 /**
205                  * Point expressed in cartesian coordinates.
206                  * @ingroup shapedet
207                  */
208                 typedef struct {
209                         float x; /**< x coordinates point. */
210                         float y; /**< y coordinates point. */
211                 } Point;
212
213                 /**
214                  * Line defined by two points which are expressed in cartesian coordinates.
215                  * @ingroup shapedet
216                  */
217                 typedef struct {
218                         Point a; /**< start point from a line. */
219                         Point b; /**< end point from a line. */
220                 } Line;
221
222                 /**
223                  * Arc defined by TODO.
224                  * @ingroup shapedet
225                  */
226                 typedef struct {
227                         Point center;
228                         Point begin;
229                         Point end;
230                         float radius;
231                 } Arc;
232
233                 /**
234                  * TODO
235                  * @param [in] laser_scan contains laser scanned data.
236                  * @ingroup shapedet
237                  */
238                 void prepare(const unsigned short laser_scan[]);
239                 
240                 /**
241                  * There are detected line segments in input array of measured
242                  * data by using perpendicular line regression.
243                  * @param [out] &lines vector which contains detected lines.
244                  * @ingroup shapedet
245                  */
246                 void line_detect(std::vector<Line> &lines);
247
248                 /**
249                  * There are detected line segments in input array of measured
250                  * data.
251                  * @param [out] &arcs vector which contains detected arcs.
252                  * @ingroup shapedet
253                  */
254                 void arc_detect(std::vector<Arc> &arcs);
255
256         private:
257                 /**
258                  * The minimal number of points which can create segment line.
259                  * @ingroup shapedet
260                  */
261                 int Line_min_points;
262
263                 /**
264                  * The maximal pointerror from segment line of regression.
265                  * @ingroup shapedet 
266                  */
267                 int Line_error_threshold;
268
269                 /**
270                  * The maximal Euclidean distance of point.
271                  * @ingroup shapedet
272                  */
273                 int Max_distance_point;
274
275                 std::vector<Point> cartes;//(HOKUYO_ARRAY_SIZE);
276
277                 float Arc_max_aperture;
278                 float Arc_min_aperture;
279                 float Arc_std_max;
280
281 #ifdef GNUPLOT
282                 FILE *gnuplot;
283                 
284                 /**
285                  * Method paints detection lines in GNUPLOT.
286                  * For debug mode. It must be defined global flag GNUPLOT.
287                  * @param &lines is vector which contains detected lines.
288                  * @param &cartes is vector whose points are expressed in cartesian coordinates.
289                  * @ingroup shapedet
290                  */
291                 void plot_line(std::vector<Line> &lines);
292                 void plot_arc(std::vector<Arc> &arcs);
293
294                 /**
295                  * Method for initialization GNUPLOT - opens pipe and performs basic settings.
296                  * For debug mode. It must be defined global flag GNUPLOT.
297                  * @ingroup shapedet
298                  */
299                 void plot_init();
300                 void plot_close();
301 #endif
302                 /**
303                  * Calculation of lines intersection.
304                  * @param point which pertains to line.
305                  * @param gen is general equation of line.
306                  * @return point of intersection.
307                  * @ingroup shapedet
308                  */
309                 inline Point intersection_line(const Point point, const General_form gen);
310                 
311                 /**
312                  * Calculating perpendicular regression of a line in input range index points.
313                  * @param [out] &r is minimal distance between point and found line.
314                  * @param [in] begin is start point.
315                  * @param [in] end is last point.
316                  * @param [in] &cartes is vector whose points are expressed in cartesian coordinates.
317                  * @param [out] &gen is general equation of found line.
318                  * @return 0 for right course else 1.
319                  * @ingroup shapedet
320                  */
321                 int perpendicular_regression(float &r, const int begin, const int end, General_form &gen);
322                 
323                 /**
324                  * In case the input range points does not line. Is range divided and to single parts is again applied line_fitting function.
325                  * @param [in] begin is start point.
326                  * @param [in] end is last point.
327                  * @param [in] &cartes is vector whose points are expressed in cartesian coordinates.
328                  * @param [out] &lines is vector with detecting lines.
329                  * @ingroup shapedet
330                  */     
331                 void line_fitting(int begin, int end, std::vector<Line> &lines);
332
333                 /**
334                  * Convert vector expressed in polar coordinates to vector expressed in cartesian coordinates.
335                  * @param laser_scan laser scanned data expressed in polar coordinates.
336                  * @param &cartes is vector whose points are expressed in cartesian coordinates.
337                  * @ingroup shapedet
338                  */
339                 void polar_to_cartes(const unsigned short laser_scan[]);
340                 
341                 /**
342                  * Calculation of distance between points which are expressed in cartesian coordinates.
343                  * @param a is first point.
344                  * @param b is second point.
345                  * @return distance between points.
346                  * @ingroup shapedet
347                  */
348                 inline float point_distance(Point a, Point b);
349
350                 inline Point rotate(Point input_point, float rad);
351
352                 bool fit_arc(int begin, int end, std::vector<Arc> &arcs);
353 };
354
355 #endif // SHAPE_DETECT