/* * Copyright (c) 2000 -- Wayne C. Gramlich * All rights reserved. * * Permission to use, copy, modify, distribute, and sell this software * for any purpose is hereby granted without fee provided that the above * copyright notice and this permission are retained. The author makes * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * This program computes the position P at (Px, Py) of a robot, given * fixed beacon locations A at (Ax, Ay), B at (Bx, By), and C at (Cx, Cy) * given aAPB and aBPC, the angle measured between A and B (at P) and the * angle measured between B and C (at P) respectively. * * Please note that the computed position becomes most sensitive to * small errors in measured angles when P is near the circle formed * by points A, B, and C. When possible, you should position the * beacons so that they do not form a circle that will intersect * position that the robot may attempt to navigate from. * * This algorithm was published in "A Beacon Navigation Method for * Autonomous Vehicles" by Clare D. McGillem and Theodore S. Rappaport * published in IEEE Transactions on Vehicular Technology Vol. 38 No. 3 * August 1989, pages 132-139. The algorithm proper can be found in * equations (7) through (16). The derivation of the algorithm can * be found in the appendix. * * The program uses the math library. It can be compiled with: * * cc -o locate -g locate.c -lm */ #include #include #include int main( int argc, char *argv[]) { double Ax, Ay; /* Location of beacon A (given) */ double Bx, By; /* Location of beacon B (given) */ double Cx, Cy; /* Location of beacon C (given) */ double aAPB; /* Angle between A and B at P in degrees (given) */ double aBPC; /* Angle between B and C at P in degrees (given) */ /* * The algorithm computes the point N=(Nx, Ny) which is the center * of a circle of radius rABP that goes through points A, B, and P. * Similarly, the algorithm computes the point M=(Mx, My) which is * the center of the a circle of radius rBCP that goes through * points B, C, and P. */ double pi; /* 3.14159 (given) */ double dAB; /* Distance between A and B (computed) */ double dBC; /* Distance between B and C (computed) */ double dABx, dABy; /* Temporary results */ double dBCx, dBCy; /* Temporary results */ double rABP, rBCP; /* Radius of circles ABP and BCP (computed) */ double Mx, My; /* Center of circle BCP (computed) */ double Nx, Ny; /* Center of circle ABP (computed) */ double Px, Py; /* Position of robot (computed) */ double aXAB; /* Beacon B bearing from virtual X axis through A */ double aXBC; /* Beacon C bearing from virtual X axis through B */ double m, n; /* Magic intermediate results (computed) */ /* Grab the input arguments from the command line: */ argc--; argv++; if (argc < 8) { (void)printf("Usage: compute Ax Ay Bx By Cx Cy aAPB aBPC\n"); (void)printf("aAPB and aBPC are in degrees\n"); return 0; } Ax = atof(argv[0]); Ay = atof(argv[1]); Bx = atof(argv[2]); By = atof(argv[3]); Cx = atof(argv[4]); Cy = atof(argv[5]); aAPB = atof(argv[6]); aBPC = atof(argv[7]); (void)printf("A=%.3f:%.3f B=%.3f:%.3f C=%.3f:%.3f ABP=%.3f aBPC=%.3f\n", Ax, Ay, Bx, By, Cx, Cy, aAPB, aBPC); /* Convert angles ABP and aBPC to radians: */ pi = 3.14159; aAPB *= pi/180.; aBPC *= pi/180.; /* Compute distances between AB and BC: */ dABx = Ax - Bx; dABy = Ay - By; dAB = sqrt(dABx*dABx + dABy*dABy); dBCx = Bx - Cx; dBCy = By - Cy; dBC = sqrt(dBCx*dBCx + dBCy*dBCy); (void)printf("dAB=%.3f dBC=%.3f\n", dAB, dBC); /* Compute rABP and rBCP, the radius of each circle: */ rABP = dAB / (2. * sin(aAPB)); rBCP = dBC / (2. * sin(aBPC)); (void)printf("rABP=%.3f rBCP=%.3f\n", rABP, rBCP); /* Compute bearings between beacons A, B, and C: */ aXAB = atan((By - Ay) / (Bx - Ax)); aXBC = atan((Cy - By) / (Cx - Bx)); (void)printf("aXAB=%.3f aXBC=%.3f\n", aXAB*180./pi, aXBC*180./pi); /* N and M are the centers of the circles for ABP and BCP respectively: */ Nx = Ax - rABP * sin(aXAB - aAPB); Ny = Ay - rABP * cos(aXAB - aAPB); Mx = Bx - rBCP * sin(aXBC - aBPC); My = By - rBCP * cos(aXBC - aBPC); (void)printf("M=(%.3f:%.3f) N=(%.3f:%.3f)\n", Nx, Ny, Mx, My); /* Compute n and m, two magic intermediate results: */ m = (My - Ny) / (Nx - Mx); n = (rBCP*rBCP - rABP*rABP - Mx*Mx + Nx*Nx - My*My + Ny*Ny) / (2. * (Nx - Mx)); (void)printf("m=%.5f n=%.5f\n", m, n); /* Compute position Px and Py: */ Py = 2.0 * (m * Nx + Ny + m * n) / (1.0 + m * m) - By; Px = m * Py + n; (void)printf("P=(%.3f,%.3f)\n", Px, Py); return 0; }