Gun Shot Locator Using SoundBrute Force C code |
It started several years ago, while watching a documentary on World War I. There was a segment on the Brits locating artillery with sound alone.
Then again last year, in a youtube documentary on World War II, there was another segment on the Yanks locating artillery with sound alone.
Neither documentary discussed the math, hence the absolute need for this webpage.
My Starting Assumptions:
|
The Pythagorean theorem is utilized to calculate the distance between 2 points.
A2 + B2 = C2
C = SQRT(A2 + B2)
In this example, the distance between Gun "J" and Microphone "A" is computed.
X Y J [120, 420] - A [100, 200] ---------- = [ 20, 220] Distance = SQRT ( 20*20 + 220*220 ) Distance = SQRT( 400 + 48400 ) Distance = 220.9072
dx = mic[i].x - gun[j].x; dy = mic[i].y - gun[j].y; absolute[i][j] = sqrt(dx*dx+dy*dy);
ABSOLUTE TIME DISTANCE ZERO --- -------- --------- A J 220.9072 0.0000 <- Reaches this microphone first B J 281.6026 60.6953 C J 284.2534 63.3462
If a shot is fired from gun "J":
The Brute Force Algorithm
// ---------------------------------------------------------------------------
struct POINT mic[]=
{
{"A",100,200},
{"B",200,150},
{"C",300,200}
};
int miccnt = 3;
struct POINT gun[]=
{
{"J",120,420},
{"K",210,400},
{"L",280,420},
{"M",220,280},
};
int guncnt = 4;
// ---------------------------------------------------------------------------
int dumpmic()
{
int i;
printf("MIC COORDINATES\n");
for(i=0;i<miccnt;i++)
printf("%d. %s [%3.0f,%3.0f]\n",i,mic[i].name,mic[i].x,mic[i].y);
printf("\n");
return 0;
}
// ---------------------------------------------------------------------------
int dumpgun()
{
int j;
// GUN COORDINATES
printf("GUN COORDINATES\n");
for(j=0;j<guncnt;j++)
printf("%d. %s [%3.0f,%3.0f]\n",j,gun[j].name,gun[j].x,gun[j].y);
printf("\n");
return 0;
}
// ---------------------------------------------------------------------------
// CREATE TEST DATA FROM GUN AND MIC LOCATIONS
int createtestdata()
{
int i,j;
double dx,dy;
double lowest;
printf("TEST Absolute Zero\n");
printf("DATA Distance Time\n");
for(j=0;j<guncnt;j++)
{
lowest=1000000;
for(i=0;i<miccnt;i++)
{
// CALCULATE ABSOLUTE DISTANCE BETWEEN MIC AND GUN
dx = mic[i].x - gun[j].x;
dy = mic[i].y - gun[j].y;
absolute[i][j] = sqrt(dx*dx+dy*dy);
// FIND CLOSEST DISTANCE
if (absolute[i][j] < lowest)
lowest = absolute[i][j];
}
// SUBTRACT CLOSEST DISTANCE FROM ALL DISTANCES
for(i=0;i<miccnt;i++)
{
zero[i][j] = absolute[i][j] - lowest;
printf("[%2d,%2d] %s %s %9.4f %9.4f\n",i,j,mic[i].name,gun[j].name,absolute[i][j],zero[i][j]);
}
printf("\n");
}
printf("\n");
return 0;
}
// ---------------------------------------------------------------------------
// SOLVE
int brute(int j)
{
int i,x,y;
double dx,dy;
double bruteabs[MAXMIC];
double brutezero[MAXMIC];
double lowest;
double error,errormin;
int bestx,besty;
// INSIST UPON EXPLICIT CONVERSION FROM INTEGER TO DOUBLE
double doublex,doubley;
// INITIALIZE BEST ANSWER VARIABLES
errormin = 1000000.0;
bestx=-1;
besty=-1;
// SCAN ENTIRE SEARCH SPACE IN 1 UNIT INCREMENTS
for(x=0;x<400;x++)
{
doublex = x;
for(y=0;y<500;y++)
{
doubley = y;
// USED TO FIND CLOSEST MIC
lowest = 1000000.0;
for(i=0;i<miccnt;i++)
{
// ABSOLUTE DISTANCE FROM EVENT AT THIS X,Y TO EACH MIC
dx = mic[i].x - doublex;
dy = mic[i].y - doubley;
bruteabs[i] = sqrt(dx*dx+dy*dy);
// KEEP TRACK OF CLOSEST DISTANCE
if (bruteabs[i] < lowest)
lowest = bruteabs[i];
}
// CONVERT "ABSOLUTE DISTANCE" TO "ZERO TIME"
for(i=0;i<miccnt;i++)
brutezero[i] = bruteabs[i] - lowest;
// COMPARE GENERATED WITH ACTUAL
// ACCUMULATE TOTAL ABSOLUTE ERROR FROM ALL MICS
error = 0;
for(i=0;i<miccnt;i++)
error += fabs( zero[i][j] - brutezero[i] );
// SAVE THIS X,Y AS BEST IF IT HAS THE LEAST ERROR
if (error < errormin)
{
errormin = error;
bestx = x;
besty = y;
}
}
}
// PRINT BEST ANSWER
printf("%s: %9.4f %9d %9d",gun[j].name,errormin,bestx,besty);
if (bestx == -1)
printf(" FUBAR");
printf("\n");
return 0;
}
// ---------------------------------------------------------------------------
int main()
{
int j;
printf("GUN SHOT LOCATOR\n");
dumpmic();
dumpgun();
createtestdata();
// RUN BRUTE FORCE LOCATOR
printf("******* PROGRAM RUN *******\n\n");
printf(" -- LOCATION --\n");
printf("GUN ERROR X Y\n");
for(j=0;j<guncnt;j++)
brute(j);
printf("\n");
return 0;
}