]> rtime.felk.cvut.cz Git - eurobot/public.git/commitdiff
Merge branch 'master' of ssh://rtime.felk.cvut.cz/eurobot
authorMartin Synek <synekmar@fel.cvut.cz>
Sat, 11 Dec 2010 15:52:03 +0000 (16:52 +0100)
committerMartin Synek <synekmar@fel.cvut.cz>
Sat, 11 Dec 2010 15:52:03 +0000 (16:52 +0100)
src/hokuyo/shape-detect/Makefile.omk
src/hokuyo/shape-detect/main.cc

index 6f15f6097fc37abd2a3ba854bfc5213cdff72033..e6b9bdd1d9fe210b0965dd024fe6e80fcacf43db 100644 (file)
@@ -3,4 +3,4 @@
 bin_PROGRAMS = shape_detect
 
 shape_detect_SOURCES = main.cc
-shape_detect_LIBS = roboorte robottype orte
+#shape_detect_LIBS = roboorte robottype orte
index d615fcb065a393159688faa532fdbeead1c31eb6..773dc53de5922f19c82de1e80c8c232ae9f6a762 100644 (file)
@@ -1,4 +1,5 @@
 #include <string>
+#include <cstring>
 #include <stdlib.h>
 #include <fstream>
 #include <iostream>
@@ -6,19 +7,22 @@
 #include <math.h>
 #include <vector>
 #include <hokuyo.h>
+#include <robot.h>
 #include <robomath.h>
+#include <robottype.h>
+#include <roboorte_robottype.h>
 
 #define LINE_MIN_POINTS 7
-#define LINE_ERROR_THRESHOLD 25
+#define LINE_ERROR_THRESHOLD 20
+#define MAX_DISTANCE_POINT 300
 
 using namespace std;
 
 typedef struct {float x,y;} Point;
 
-vector<Point> cartes;
-vector<Point> lines;
+typedef struct {Point a,b;} Line;
 
-int perpendicular_regression(float &r, int &max_diff_idx, const int begin, const int end)
+int perpendicular_regression(float &r, int &max_diff_idx, const int begin, const int end, vector<Point> &cartes)
 {
        int number_points = abs(end-begin) + 1;
   
@@ -35,14 +39,17 @@ int perpendicular_regression(float &r, int &max_diff_idx, const int begin, const
        float med_x = sum_x / number_points;
        float med_y = sum_y / number_points;
 
-       vector<Point> point_average;
-               
+       vector<Point> point_average(number_points);
+
        Point tmp;
 
+       int j = 0;
+
        for (int i = begin; i <= end; i++) {
                tmp.x = cartes[i].x - med_x;
                tmp.y = cartes[i].y - med_y;
-               point_average.push_back(tmp);
+               point_average[j] = tmp;
+               j++;
        }
 
        float A = 0;
@@ -59,7 +66,7 @@ int perpendicular_regression(float &r, int &max_diff_idx, const int begin, const
 
        // tan(q)^2 + A*tan(q) - 1 = 0 ( tan(q) sign as m ) -> quadratic equation
        float m1 = (-A + sqrt(A*A + 4)) / 2;
-       float m2 = (-A + sqrt(A*A + 4)) / 2;
+       float m2 = (-A - sqrt(A*A + 4)) / 2;
 
        float b1 = med_y - m1*med_x;
        float b2 = med_y - m2*med_x;
@@ -69,80 +76,110 @@ int perpendicular_regression(float &r, int &max_diff_idx, const int begin, const
        unsigned ir = -1;
        float dist;
 
+       float r1 = 0;
+       unsigned ir1 = -1;
+       float dist1;
+
        for (int i = begin; i < end; i++) {
                // distance point from the line (A = m1, B = -1, C = b1)
                dist = fabs( (cartes[i].x*m1 - cartes[i].y + b1) / sqrt(m1*m1 + 1) );
+               dist1 = fabs( (cartes[i].x*m2 - cartes[i].y + b2) / sqrt(m2*m2 + 1) );
+               
+               if (dist1 > r1) {
+                       r1 = dist1;
+                       ir1 = i;
+               }
+
                if (dist > r) {
                        r = dist;
                        ir = i;
                }
        }
                
-       float r1 = 0;
-       unsigned ir1 = -1;
-       
-       for (int i = begin; i < end; i++) {
-               // distance point from the line (A = m2, B = -1, C = b2)
-               dist = fabs( (cartes[i].x*m2 - cartes[i].y + b2) / sqrt(m2*m2 + 1) );
-               if (dist > r1) {
-                       r1 = dist;
-                       ir1 = i;
-               }
-       }
-
-       if (r < r1)
-               max_diff_idx = ir;
-       else {
-               r = r1;
+       if (r < r1) {
                max_diff_idx = ir1;
+       } else {
+               r = r1;
+               max_diff_idx = ir;
        }
 
        return 0;
 }
 
 // line recursive fitting
-void line_fitting(int begin, int end) {
+void line_fitting(int begin, int end, vector<Point> &cartes, vector<Line> &lines) {
        int line_break_point;
-       cout << "begin: " << begin << " end: " << end << endl << flush;
+       //cout << "begin: " << begin << " end: " << end << endl << flush;
        
        if ((end - begin) < LINE_MIN_POINTS) return;
 
        float r;
-       if (perpendicular_regression(r, line_break_point, begin, end)) return; // r = 0
+       if (perpendicular_regression(r, line_break_point, begin, end, cartes)) return; // r = 0
 
        if (r < LINE_ERROR_THRESHOLD) {
-               lines.push_back(cartes[begin]);
-               lines.push_back(cartes[end]);
 
-               cout << endl << "begin X: " << cartes[begin].x << " Y: " << cartes[begin].y << endl << flush;
-               cout << "end X: " << cartes[end].x << " Y: " << cartes[end].y << endl << endl << flush;
+               Line line;
+
+               line.a = cartes[begin];
+               line.b = cartes[end];
+
+               lines.push_back(line);
+
+               //cout << endl << "begin X: " << cartes[begin].x << " Y: " << cartes[begin].y << endl << flush;
+               //cout << "end X: " << cartes[end].x << " Y: " << cartes[end].y << endl << endl << flush;
        } else {
+               // Ax+By+C=0
+               // normal vector: n[n_x, -n_y]
+               float n_x = cartes[begin].y - cartes[end].y;
+               float n_y = cartes[begin].x - cartes[end].x;
+
+               float A = n_x;
+               float B = -n_y;
+               float C = n_y*cartes[end].y - n_x*cartes[end].x;
+
+               int line_break_point = 0;
+               float dist, dist_max = 0;
+
+               for (int i = begin; i < end; i++) {
+                       // distance point from the line
+                       dist = fabs( (cartes[i].x*A + cartes[i].y*B + C) / sqrt(A*A + B*B));
+
+                       if (dist > dist_max) {
+                               dist_max = dist;
+                               line_break_point = i;
+                       }
+               }
+
+               if (dist_max > LINE_ERROR_THRESHOLD) {
+                       line_fitting(begin, line_break_point, cartes, lines);
+                       line_fitting(line_break_point, end, cartes, lines);
+               }
+               /*
                if (line_break_point == begin)
                        line_break_point++;
                else if (line_break_point == end)
                        line_break_point--;
-               line_fitting(begin, line_break_point);
-               line_fitting(line_break_point, end);
+
+               line_fitting(begin, line_break_point, cartes, lines);
+               line_fitting(line_break_point, end, cartes, lines);
+               */
        } // end if (r <= LINE_ERROR_THRESHOLD)
-       
-       return;
 
+       return;
 }
 
 // polar to cartesian coordinates
-void polar_to_cartes(const vector<int> &input_data) {
-  
+void polar_to_cartes(const vector<int> &input_data, vector<Point> &cartes) {
        Point point;
 
        float fi;
        int r;
   
-       for (int i = 0; i < (int) input_data.size()-1; i += 2) { 
-               r = (input_data[i+1] <= 19) ? 0 : input_data[i+1];
-               //fi = HOKUYO_INDEX_TO_RAD(RESOLUTION * input_data[i] - 45) * PI/180;
+       for (int i = 0; i < (int) input_data.size()-1; i++) { 
+               r = (input_data[i] <= 19) ? 0 : input_data[i];
+
                if (r > 0) {
-                       fi = HOKUYO_INDEX_TO_RAD(input_data[i]);
-        
+                       fi = HOKUYO_INDEX_TO_RAD(i);     
                        point.x = r * cos(fi);
                        point.y = r * sin(fi);
                        cartes.push_back(point);
@@ -150,24 +187,69 @@ void polar_to_cartes(const vector<int> &input_data) {
        }
 }
 
-void shape_detect(const vector<int> &input_data) {
+// save vector to file
+void file_save(const vector<Point> &data, string name) {
+       char * file_name;
+       file_name = new char[name.length() + 1];
+       strcpy(file_name, name.c_str());
+
+       FILE *file = fopen(file_name,"w");
+
+       for (int i = 0; i < (int) data.size(); i++)
+               fprintf(file, "%f, %f\n", data[i].x, data[i].y);
+
+       fclose(file);
+       delete file_name;
+}
+
+float point_distance(Point a, Point b) {
+       return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
+}
+
+void shape_detect(const vector<int> &input_data, vector<Line> &lines) {
        // polar coordinates to cartesian coordinates  
-       polar_to_cartes(input_data);
-       cout << "Cartes vector size: " << cartes.size() << endl << endl;
-
-       int start = 0;
-       while (..) {
-               i = start + 1;
-               while (distance(cartes[i-1], cartes[i]) < 50cm &&
-                      i < cartes.size())
-                       i++;
-               
-               // detection lines
-               line_fitting(start, i);
-               start = i+1;
+       vector<Point> cartes;
+       polar_to_cartes(input_data, cartes);
+
+       int cartes_size = cartes.size();
+
+       int end, start = 0;
+       while (start < cartes_size) {
+               end = start + 1;
+
+               while (point_distance(cartes[end-1], cartes[end]) < MAX_DISTANCE_POINT && end < cartes_size) 
+                       end++;
+
+               if(end == cartes_size) end--;
+
+               line_fitting(start, end, cartes, lines);
+               start = end + 1;
+       }
+
+       // cartes -> save file
+       file_save(cartes, "cartes_data");
+
+       // create pipe -> gnuplot
+       FILE *pipe = popen("gnuplot", "w");
+
+       fprintf(pipe, "set grid\n");
+       fprintf(pipe, "set nokey\n");
+       fprintf(pipe, "set style line 1 lt 2 lc rgb \"green\" lw 3\n");
+       fprintf(pipe, "plot \"cartes_data\" with points");
+
+       for (int i = 0; i < (int) lines.size(); i++) {
+               fprintf(pipe, ", \"< echo \'%f %f \\n %f %f\'\" ls 1 with linespoints",lines[i].a.x, lines[i].a.y, lines[i].b.x, lines[i].b.y);
        }
+
+       fprintf(pipe, "\n");
+       fflush(pipe);
+
+       getchar();
+       pclose(pipe);
 }
 
+//-----------------------------------------------
+/*
 struct robottype_orte_data orte;
 
 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
@@ -179,76 +261,80 @@ void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
        switch (info->status) {
                case NEW_DATA: {
                        scan = *instance;
-                       scan.data[i]
-                       shape_detect(scan);
-                       save_data(lines);
-                       system("gnuplot graph.dem"); // nebo pres pipe jako v barcam
+
+                       
+                       vector<int> input(velikost);
+
+                       for(int i = 0; i < velikost; i++)
+                               input[i] = (int) scan.data[i];
+
+                       
+
+                       vector<Line> output;
+                       shape_detect(input, output);
+                       
                        break;
                }
                case DEADLINE:
                        robot.status[COMPONENT_HOKUYO] = STATUS_FAILED;
                        //system("killall -9 hokuyo");
-                       DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
+                       //DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
                        break;
        }
 }
+
 int robot_init_orte()
 {
        int rv = 0;
-
        robot.orte.strength = 20;
 
        rv = robottype_roboorte_init(&orte);
-       if (rv)
-               return rv;
+       if (rv) return rv;
 
        robottype_subscriber_hokuyo_scan_create(&orte, rcv_hokuyo_scan_cb, &orte);
-
        return rv;
 }
-
+*/
+//-----------------------------------------------
 
 // MAIN
 int main(int argc, char** argv) {
   
-  if (argc < 2) {
-    cout << "Error: Invalid number of input parameters." << endl;
-    return 1;
-  }
-  vector<int> input_data;
-  
-  ifstream infile (argv[1], ios_base::in);
-  
-  string line; // line input file
-  int number;          // number from input file
-    
-  while (getline(infile, line, ',')) {
-    if (line != "\n") {
-      stringstream strStream(line);
-      strStream >> number;
-      input_data.push_back(number);
-    }
-  }
-       
-       // detect line
-       shape_detect(input_data);
-       
-  // save file
-  FILE *file = fopen("output_data","w");
+       if (argc < 2) {
+               cout << "Error: Invalid number of input parameters." << endl;
+               return 1;
+       }
 
-  for (int i = 0; i < (int) lines.size(); i++)
-    fprintf(file, "%f, %f\n", lines[i].x, lines[i].y);
+       vector<int> input_data;
+  
+       ifstream infile(argv[1], ios_base::in);
 
-  fclose(file);
+       // line input file
+       string line;
 
-  file = fopen("cartes_data","w");
+       // number from input file
+       int number;
 
-  for (int i = 0; i < (int) cartes.size(); i++)
-    fprintf(file, "%f, %f\n", cartes[i].x, cartes[i].y);
+       int tmp = 1;
+    
+       while (getline(infile, line, ',')) {
+               if (tmp) {
+                       tmp = 0;
+                       continue;
+               }
+               if (line != "\n") {
+                       stringstream strStream(line);
+                       strStream >> number;
+                       input_data.push_back(number);
+                       tmp = 1;
+               }
+       }
 
-  fclose(file);
-  
-  return 0;
+       vector<Line> output_data;
+       
+       // detect line
+       shape_detect(input_data, output_data);
+       
+       return 0;
 }