Making a Boundary Using GPS

I would like to have the arduino keep track of it's current position with a GPS. Then have the user enter any shape based on Lat and Long to create a boundary, and then hopefully an exclusion zone within the boundary. How can I create vectors that connect to each other so the arduino knows when it compares the location to the boudary if it is in or out?

Thanks for you help.

This link has a code solution in just a few lines:

I would like to have the arduino keep track of it's current position with a GPS. Then have the user enter any shape based on Lat and Long to create a boundary, and then hopefully an exclusion zone within the boundary. How can I create vectors that connect to each other so the arduino knows when it compares the location to the boudary if it is in or out?

Over what size area? To what degree of accuracy? How far "in or out"?

gardner:
Point in polygon - Wikipedia

This link has a code solution in just a few lines:

c - Point in Polygon Algorithm - Stack Overflow

I am trying to understand this code, where would I put the customized Lat, Long Values?

I am trying to understand this code, where would I put the customized Lat, Long Values?

In the call arguments to pnpoly as testx, testy. vertx and verty define the boundary polygon.
The pnpoly procedure will work accurately only on a flat plane in a 2D orthogonal coordinate system.

jremington:

I am trying to understand this code, where would I put the customized Lat, Long Values?

In the call arguments to pnpoly as testx, testy. vertx and verty define the boundary polygon.
The pnpoly procedure will work accurately only on a flat plane in a 2D orthogonal coordinate system.

Ok, so with a 2D coordinate system I can not just feed the actual position of the GPS into the boundary. I have to convert the Lat and Long to an X,Y coordinate system based of a map file from google or something?

Yes, you need to convert everything to a local 2D orthogonal coordinate system. The "distance" between two longitude points depends on how close to the North or South pole you are and even becomes zero at the poles. Here is an overview of coordinate systems: http://www.colorado.edu/geography/gcraft/notes/coordsys/coordsys.html

There is lots of code on the web for converting between coordinate systems (which for latitude and longitude, also depends on which particular reference model is used to describe the Earth). Or, you can use code that gives distances in meters between (lat,lon) pairs by using the appropriate formula on the surface of a sphere or ellipsoid. For example, the TinyGPS library includes a function call (TinyGPS::distance_between() ) for that purpose, but even there, the authors caution that since they treat the Earth as a perfect sphere, errors of up to 0.5% can occur.

Finally, float variables don't work well for these calculations, because you need at least 8 digits of precision for the calculations to be accurate. Since variables of type 64 bit "double" aren't supported on the Arduino, most codes don't work properly.

jremington:
Yes, you need to convert everything to a local 2D orthogonal coordinate system.

I think you're over-complicating this. Plugging lat/long values directly into the point-in-polygon algorithm is likely going to be fine. This effectively treats the world like a giant Mercator map. The point-in-polygon solution will be correct so long as none of the points on the polygon is near the poles and the polygon doesn't straddle the date-line.

If the polygon is something like the size of a city and is located within +/- 60 degrees latitude and not at the date-line, I think the error in geometry will be along the lines of basic GPS positioning errors.

If you want to use this algorithm to determine if you are in/not-in the pacific ocean, then, obviously a lot more careful coordinate conversion is needed. But also more accurate math than you'll get on Arduino. Also, a boundary polygon specified accurately enough to make any of this matter is likely to take more than a few dozen points to specify and it's going to be a whole other problem to store that in a wimpy Arduino.

Yes, near the equator pretending that latitude and longitude are orthogonal coordinates will work. Anywhere else, at the very minimum, you must correct the longitude by the cosine of the latitude. Here is a useful on-line calculator to see the effect of latitude: Length Of A Degree Of Latitude And Longitude Calculator

We don't know the OP's requirements, though. If the OP requires any accuracy at all, then true double precision math is also required. With single precision floats, even in the case that "the polygon is something like the size of a city" you have a problem. One degree of latitude or longitude near the equator corresponds to about 110 km. If you want to preserve GPS-like accuracy to roughly 1 meter precision, that means you need at least 8 decimal digits (3 digits for whole degrees and 5 digits for fractions of a degree) of accuracy in all calculations. The Arduino, with 6-7 digits of floating point accuracy, will introduce errors of up to 100 meters at every step of the calculation.

As a general rule, I don't like to encourage sloppy work. There is plenty of elegant software to chose from, and the above-mentioned TinyGPS code is one place to start. Incidentally, to preserve accuracy, the TinyGPS software stores positions as long integers in steps of one millionth of a degree (as of Version 13).

jremington:
Incidentally, to preserve accuracy, the TinyGPS software stores positions as long integers in steps of one millionth of a degree

I see no reason that the point-in-poly algorithm couldn't be used on this representation of coordinates. Multiplication and division would require using long long and renormalization, but that's all doable.

I've been trying to get this working for far too long, Has anyone gotten the correct response from this. Here is my code and it seems like it should return a 1, but I always get 0's.

float gpsX[] = {1.2,1.2,2.5,20.8,20.8};
float gpsY[] = {1.8,1.4,2.6,20.9,20.9};

void setup(){
  
  
  Serial.begin(9600);
}

void loop(){
 
 Serial.println( pnpoly(5,gpsX,gpsY,2.9,2.9));

  
}



int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
{
  int i, j, c = 0;
  for (i = 0, j = nvert-1; i < nvert; j = i++) {
  
    if ( ((verty[i]>testy) != (verty[j]>testy)) &&
     (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
    
       c = !c;
  }
  return c;
}

Hello

It looks like you have the last two vertices of the polygon being the same point.

float gpsX[] = {1.2,1.2,2.5,20.8,20.8};
float gpsY[] = {1.8,1.4,2.6,20.9,20.9};

What happens if you remove one, or make them different co-ordinates?

Regards

Ray