22 #define AUTHOR                  "Vincent Pierlot"    23 #define EMAIL                   "vpierlot@gmail.com"    25 #define DEFAULT_PROGNAME        "triangulation"    34            int m, 
tfloat sigmaAngle, 
tfloat sigmaBeacon, 
unsigned int n, 
int O);
    35 int test5 (
tfloat x1, 
tfloat y1, 
tfloat x2, 
tfloat y2, 
tfloat x3, 
tfloat y3, 
int m, 
tfloat sigmaAngle, 
tfloat sigmaBeacon, 
unsigned int n,
    38 void usage(
const char *progName);
    49 void usage( 
const char *progName )
    52           DEFAULT_PROGNAME 
" " VERSION 
" by " AUTHOR 
" [" EMAIL 
"]\n"    53           "Three Object Triangulation algorithms implementation, simulation and benchmarking.\n"    54           "http://www2.ulg.ac.be/telecom/triangulation/\n"    55           "http://hdl.handle.net/2268/89435\n"    56           "Usage: %s [options]\n"    58           "  -t  int    Test to execute (default=5):\n"    59           "             0: gets angles from robot pose (x;y;o). Displays angles (a;b;c).\n"    60           "             1: triangulates from measured angles (a;b;c). Displays robot pose (x;y;o).\n"    61           "             2: gets angles from robot pose (x;y;o) and triangulates with measured angles. Displays angles and pose.\n"    62           "             3: runs triangulation method n times from random positions in the grid [-x,X]*[y,Y]. Displays execution time.\n"    63           "             4: runs triangulation sensitivity analysis from robot position (x;y). (see -O for output).\n"    64           "             5: runs triangulation sensitivity analysis for each point in the grid [-x,X]*[y,Y]. (see -O for output).\n"    65           "                Writes PGM images \"map.pgm\" and \"scale.pgm\" in current directory. Displays step, min and max values.\n"    66           "  -m  int    Triangulation method to use (default=1). For all tests.\n"    67           "              1: Pierlot (ToTal)  2: Esteves          3: FontLlagunes (T)  4: Zalama\n"    68           "              5: McGillem (T)     6: McGillem (G)     7: Easton            8: Hmam\n"    69           "              9: Cohen (T)       10: Cohen (G)       11: Cohen (G)*       12: Tsukiyama\n"    70           "             13: Tsukiyama*      14: Madsen          15: Lukic            16: Lukic*\n"    71           "             17: Tienstra        18: Ligas           19: FontLlagunes (G) 20: Kaestner\n"    72           "             21: Collins         22: Cassini\n"    73           "             (*) original method from the paper (typically slower than my implementation)\n"    74           "             (G) Geometric solution\n"    75           "             (T) Trigonometric solution\n"    76           "  -x  float  X robot position. For tests 0, 2, 4. (default=0.0)\n"    77           "             X min value of test grid. For tests 3, 5. (default=-2.0)\n"    78           "  -y  float  Y robot position. For tests 0, 2, 4. (default=0.0)\n"    79           "             Y min value of test grid. For tests 3, 5. (default=-2.0)\n"    80           "  -o  float  Robot orientation relative to X axis [deg]. For tests 0, 2, 4. (default=0.0)\n"    81           "  -a  float  alpha1 angle [deg]. For test 1. (default=+90)\n"    82           "  -b  float  alpha2 angle [deg]. For test 1. (default=-150)\n"    83           "  -c  float  alpha3 angle [deg]. For test 1. (default=-30)\n"    84           "  -1  float  X1 beacon1 position. For all tests. (default=0.0)\n"    85           "  -2  float  Y1 beacon1 position. For all tests. (default=+1.0)\n"    86           "  -3  float  X2 beacon2 position. For all tests. (default=-0.866)\n"    87           "  -4  float  Y2 beacon2 position. For all tests. (default=-0.5)\n"    88           "  -5  float  X3 beacon3 position. For all tests. (default=+0.866)\n"    89           "  -6  float  Y3 beacon3 position. For all tests. (default=-0.5)\n"    90           "  -O  int    Output of the sensitivity analysis. For tests 4, 5. (default=1)\n"    91           "             1: std deviation of position error, 2: std deviation of orientation error, 3: return value of method.\n"    92           "  -X  float  X max value of test grid. For tests 3, 5. (default=+2.0)\n"    93           "  -Y  float  Y max value of test grid. For tests 3, 5. (default=+2.0)\n"    94           "  -p  float  Discretization step of the test grid. For test 5. (default=0.02)\n"    95           "  -A  float  Standard deviation of the gaussian noise applied to angles in [deg]. For tests 4, 5. (default=0.1)\n"    96           "  -B  float  Standard deviation of the gaussian noise applied to beacons coordinates. For tests 4, 5. (default=0.0)\n"    97           "  -n  int    Number of tests for the execution time and the sensitivity analysis. For tests 3, 4, 5. (default=100)\n"    98           "  -M  int    Map used to display results from the sensitivity analysis. For test 5. (default=2)\n"   101           "             2: Histogram equalized.\n"   102           "             3: Linear after removing outliers (1 percent of the highest values).\n"   103           "             4: Logarithmic after removing outliers (1 percent of the highest values).\n"   104           "  -T  float  Threshold for the sensitivity analysis output (must be >= 0 to be active). For test 5. (default=-1)\n"   105           "  -h         Displays this help and exit.\n"   112 int main ( 
int argc , 
char *argv[] )
   126     tfloat a1 =   90.0 * DEG2RAD ;
   127     tfloat a2 = -150.0 * DEG2RAD ;
   128     tfloat a3 =  -30.0 * DEG2RAD ;
   133     tfloat x2 = -sqrt(3.0)/2 ;
   135     tfloat x3 = +sqrt(3.0)/2 ;
   139     tfloat sigmaAngle  = 0.1 * DEG2RAD ;
   140     tfloat sigmaBeacon = 0.0 ;
   149   unsigned int n = 100 ;
   152   unsigned int map = 2 ;
   158   char optString[] = 
"t:m:x:y:o:A:B:a:b:c:p:n:O:1:2:3:4:5:6:X:Y:M:T:h" ;
   161   while( ( optionChar = getopt(argc, argv, optString) ) != -1 )
   165         case '?' : 
return -1 ; break ; 
   166         case 't' : t = atoi( optarg ) ; break ;
   167         case 'm' : m = atoi( optarg ) ; break ;
   168         case 'x' : xr = atof( optarg ) ; xstart = xr ; break ;
   169         case 'y' : yr = atof( optarg ) ; ystart = yr ; break ;
   170         case 'o' : or = atof( optarg )*DEG2RAD ; break ;
   171         case 'A' : sigmaAngle = atof( optarg )*DEG2RAD ; break ;
   172         case 'B' : sigmaBeacon = atof( optarg ) ; break ;
   173         case 'a' : a1 = atof( optarg )*DEG2RAD ; break ;
   174         case 'b' : a2 = atof( optarg )*DEG2RAD ; break ;
   175         case 'c' : a3 = atof( optarg )*DEG2RAD ; break ;
   176         case 'p' : step = atof( optarg ) ; break ;
   177         case 'n' : n = atoi( optarg ) ; break ;
   178         case 'O' : O = atoi( optarg ) ; break ;
   179         case '1' : x1 = atof( optarg ) ; break ;
   180         case '2' : y1 = atof( optarg ) ; break ;
   181         case '3' : x2 = atof( optarg ) ; break ;
   182         case '4' : y2 = atof( optarg ) ; break ;
   183         case '5' : x3 = atof( optarg ) ; break ;
   184         case '6' : y3 = atof( optarg ) ; break ;
   185         case 'X' : xend = atof( optarg ) ; break ;
   186         case 'Y' : yend = atof( optarg ) ; break ;
   187         case 'M' : map = atoi( optarg ) ; break ;
   188         case 'T' : thresh = atof( optarg ) ; break ;
   189         case 'h' : 
usage( argv[0] ) ; 
return 0 ;
   196     case 0: 
return test0( xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 ) ;
   197     case 1: 
return test1( a1 , a2 , a3 , x1 , y1 , x2 , y2 , x3 , y3 , m ) ;
   198     case 2: 
return test2( xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 , m ) ;
   199     case 3: 
return test3( x1 , y1 , x2 , y2 , x3 , y3 , m , xstart , xend , ystart , yend , n ) ;
   200     case 4: 
return test4( xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 , m , sigmaAngle , sigmaBeacon , n , O ) ;
   201     case 5: 
return test5( x1 , y1 , x2 , y2 , x3 , y3 , m , sigmaAngle , sigmaBeacon , n , xstart , xend , ystart , yend , step , map , O , thresh ) ;
   202     default: fprintf( stderr , 
"main(): Bad test number!\n" ) ; 
return -1 ;
   217     get_angles( &alpha1 , &alpha2 , &alpha3 , xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 ) ;
   219     printf( 
"\nMeasured angles:\n" ) ;
   220     printf( 
"a = %f [deg]\n"   , alpha1*RAD2DEG ) ;
   221     printf( 
"b = %f [deg]\n"   , alpha2*RAD2DEG ) ;
   222     printf( 
"c = %f [deg]\n\n" , alpha3*RAD2DEG ) ;
   239     Q = 
triangulationMethod( &x , &y , alpha1 , alpha2 , alpha3 , x1 , y1 , x2 , y2 , x3 , y3 , m ) ;
   240     o = atan2( (y1-y) , (x1-x) ) - alpha1 ;
   242     printf( 
"\nComputed position:\n" ) ;
   243     printf( 
"x = %f\n", x ) ;
   244     printf( 
"y = %f\n", y ) ;
   245     printf( 
"o = %f [deg]\n\n" , o*RAD2DEG ) ;
   246     printf( 
"Error measure = %f\n\n" , Q) ;
   267     get_angles( &alpha1 , &alpha2 , &alpha3 , xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 ) ;
   269     Q = 
triangulationMethod( &x , &y , alpha1 , alpha2 , alpha3 , x1 , y1 , x2 , y2 , x3 , y3 , m ) ;
   270     o = atan2( (y1-y) , (x1-x) ) - alpha1 ;
   272     printf( 
"\nMeasured angles:\n" ) ;
   273     printf( 
"a = %f [deg]\n" , alpha1*RAD2DEG ) ;
   274     printf( 
"b = %f [deg]\n" , alpha2*RAD2DEG ) ;
   275     printf( 
"c = %f [deg]\n" , alpha3*RAD2DEG ) ;
   276     printf( 
"\nComputed position:\n") ;
   277     printf( 
"x = %f\n" , x ) ;
   278     printf( 
"y = %f\n" , y ) ;
   279     printf( 
"o = %f [deg]\n\n" , o*RAD2DEG ) ;
   280     printf( 
"Error measure = %f\n\n" , Q ) ;
   295     tfloat *alpha1M = ( 
tfloat * ) malloc( n * 
sizeof(
tfloat) ) ; 
if( alpha1M == NULL ) 
return -1 ;
   296     tfloat *alpha2M = ( 
tfloat * ) malloc( n * 
sizeof(
tfloat) ) ; 
if( alpha2M == NULL ) 
return -1 ;
   297     tfloat *alpha3M = ( 
tfloat * ) malloc( n * 
sizeof(
tfloat) ) ; 
if( alpha3M == NULL ) 
return -1 ;
   300     double t , tmin = 0.0 ;
   305     for( i = 0 ; i < n ; ++i )
   307     xi = ( ( (
tfloat) random() / (
tfloat) RAND_MAX ) * ( xend - xstart ) ) + xstart ;
   308     yi = ( ( (
tfloat) random() / (
tfloat) RAND_MAX ) * ( yend - ystart ) ) + ystart ;
   309     get_angles( &alpha1M[i] , &alpha2M[i] , &alpha3M[i] , xi , yi , 0.0 , x1 , y1 , x2 , y2 , x3 , y3 ) ;
   312     for( j = 0 ; j < 10 ; ++j )
   316     clock_t startClock = clock() ;
   318       struct timespec startTime , endTime ;
   319       clock_gettime( CLOCK_PROCESS_CPUTIME_ID , &startTime ) ;
   322     for( i = 0 ; i < n ; ++i )
   324       triangulationMethod( &xi , &yi , alpha1M[i] , alpha2M[i] , alpha3M[i] , x1 , y1 , x2 , y2 , x3 , y3 , m ) ;
   328       clock_t endClock = clock() ;  
   329       t = ( (double) (endClock - startClock) ) / CLOCKS_PER_SEC ;
   331       clock_gettime( CLOCK_PROCESS_CPUTIME_ID , &endTime ) ;
   332       t = ( (double) ((endTime.tv_sec-startTime.tv_sec)+(endTime.tv_nsec-startTime.tv_nsec)/1000000000.0)) ;
   336       if ( j == 0 ) tmin = t ;
   337       if ( t < tmin ) tmin = t ;
   340     printf( 
"Duration = %10.5f [s]\n" , tmin ) ;
   354            int m, 
tfloat sigmaAngle, 
tfloat sigmaBeacon, 
unsigned int n, 
int O)
   362     get_angles( &alpha1 , &alpha2 , &alpha3 , xr , yr , or , x1 , y1 , x2 , y2 , x3 , y3 ) ;
   364     s = 
triangulationSensitivity( xr , yr , x1 , y1 , x2 , y2 , x3 , y3 , m , sigmaAngle , sigmaBeacon , n , O , -1 ) ;
   366     printf( 
"\nMeasured angles:\n" ) ;
   367     printf( 
"a = %f [deg]\n" , alpha1*RAD2DEG ) ;
   368     printf( 
"b = %f [deg]\n" , alpha2*RAD2DEG ) ;
   369     printf( 
"c = %f [deg]\n" , alpha3*RAD2DEG ) ;
   373     case 1: printf( 
"\nPosition error standard deviation: %f\n" , s ) ; break ;
   374     case 2: printf( 
"\nOrientation error standard deviation: %f [deg]\n" , s ) ; break ; 
   375     case 3: printf( 
"\nMean error measure: %f\n" , s ) ; break ;
   376     default: fprintf( stderr , 
"test4(): Bad output type!\n" ) ; 
return -1 ;
   386 int test5 ( 
tfloat x1 , 
tfloat y1 , 
tfloat x2 , 
tfloat y2 , 
tfloat x3 , 
tfloat y3 , 
int m , 
tfloat sigmaAngle , 
tfloat sigmaBeacon , 
unsigned int n ,
   389     tfloat xi = 0.0 , yi = 0.0 ;
   391     unsigned int p = round( ( xend - xstart ) / step ) + 1 ;
   392     unsigned int q = round( ( yend - ystart ) / step ) + 1 ;
   394     tfloat *errorPM = ( 
tfloat * ) malloc( p * q * 
sizeof(
tfloat) ) ; 
if( errorPM == NULL ) 
return -1 ;
   398     printf( 
"Angles standard deviation  = %f [deg]\n" , sigmaAngle*RAD2DEG ) ;
   399     printf( 
"Beacons standard deviation  = %f\n" , sigmaBeacon ) ;
   400     printf( 
"grid X limits = %f to %f\n" , xstart , xend ) ;
   401     printf( 
"grid Y limits = %f to %f\n" , ystart , yend ) ;
   402     printf( 
"grid step = %f\n" , step ) ;
   404     for( yi = ystart, j = 0 ; j < q ; j++ )
   406       for( xi = xstart, i = 0 ; i < p ; i++ )
   411             errorPM[j*p + i] = 
triangulationSensitivity( xi , yi , x1 , y1 , x2 , y2 , x3 , y3 , m , sigmaAngle , sigmaBeacon , n , O , thresh ) ;
 
void usage(const char *progName)
Print usage informations. 
 
double tfloat
Defines the type for float/double.