0

Who among here have tried measuring the before and after distance traveled using gps? I'm going to use the code from TinyGPS library's distance_between command without constant value of latitude and longitude,

like this:

static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002

I want to see that the first GPS latitude and longitude results is used as reference point.

How will I apply it on my code so that I could be able to get the distance I traveled? Please help me.

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
 /*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
 */
 static const int RXPin = 4, TXPin = 3;
 static const uint32_t GPSBaud = 4800;

  // The TinyGPS++ object
TinyGPSPlus gps;

 // The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
 Serial.begin(115200);
 ss.begin(GPSBaud);

     Serial.println(F("FullExample.ino"));
     Serial.println(F("An extensive example of many interesting     TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. "));                    Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars     Sentences Checksum"));
     Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
           Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));
}

void loop()
{
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ?        TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

  unsigned long distanceKmToLondon =
   (unsigned long)TinyGPSPlus::distanceBetween(
     gps.location.lat(),
     gps.location.lng(),
     LONDON_LAT, 
     LONDON_LON) / 1000;
     printInt(distanceKmToLondon, gps.location.isValid(), 9);

     double courseToLondon =
    TinyGPSPlus::courseTo(
     gps.location.lat(),
     gps.location.lng(),
     LONDON_LAT, 
     LONDON_LON);

   printFloat(courseToLondon, gps.location.isValid(), 7, 2);

   const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

   printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

   printInt(gps.charsProcessed(), true, 6);
   printInt(gps.sentencesWithFix(), true, 10);
   printInt(gps.failedChecksum(), true, 9);
   Serial.println();

   smartDelay(1000);

   if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
   }

  // This custom version of delay() ensures that the gps object
  // is being "fed".
  static void smartDelay(unsigned long ms)
  {
  unsigned long start = millis();
  do 
  {
   while (ss.available())
    gps.encode(ss.read());
    } while (millis() - start < ms);
    }

    static void printFloat(float val, bool valid, int len, int prec)
     {
   if (!valid)
   {
    while (len-- > 1)
    Serial.print('*');
    Serial.print(' ');
    }
    else
    {
   Serial.print(val, prec);
   int vi = abs((int)val);
   int flen = prec + (val < 0.0 ? 2 : 1); // . and -
   flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
   for (int i=flen; i<len; ++i)
   Serial.print(' ');
   }
   smartDelay(0);
  }

 static void printInt(unsigned long val, bool valid, int len)
 {
  char sz[32] = "*****************";
  if (valid)
  sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
   sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
  }

  static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
  {
  if (!d.isValid())
   {
   Serial.print(F("********** "));
   }
   else
   {
   char sz[32];
   sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
   Serial.print(sz);
    }

    if (!t.isValid())
    {
    Serial.print(F("******** "));
    }
    else
    {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
    }

    printInt(d.age(), d.isValid(), 5);
    smartDelay(0);
    }

    static void printStr(const char *str, int len)
    {
    int slen = strlen(str);
    for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
    smartDelay(0);
    }

2 Answers 2

1

This is where those dreaded maths classes come in.

You know - the ones where no one paid attention because you thought "Where in the real world would I ever want to know this stuff?" Well, right here is were you would want to know this stuff.

The distance between two points on a 2D plane (i.e., a map) can be looked at as two vertices of a right-angled triangle.

enter image description here

Going from Start to Finish you travel X degrees across the globe and Y degrees up or down it. So you can calculate the number of degrees between the two points with simple pythagoras' theorem:

enter image description here

In C it's quite easy to do those calculations. You can find X and Y by subtracting the two longitudes and scaling it for the logitudinal circumference of the Earth where you are. You can do the latitudes in a similar way:

float X = ((long2 - long1) * 24901 * cos(lat1)) / 360.0
float Y = ((lat2 - lat1) * 24860) / 360.0

24901 is the circumference of the Earth at the equator, and 24860 is the circumference of the Earth going through both poles. Both are in miles, so the result will also be in miles. The numbers are different for the two directions because the Earth is not a perfect sphere. It is somewhat flattened at the poles, and is called an oblate sphere.

It doesn't matter which one you subtract from which since, when you square them, they will become positive anyway:

float X2 = X * X;
float Y2 = Y * Y;

Then you can get the square root:

float Distance = sqrt(X2 + Y2);

So now you know how to calculate it without relying on some function in some library. It only takes a couple of lines of C code and you don't have to then know just how to use this unknown function provided by a library, and the theory will stand you in good stead for future similar projects.

Oh, and the code in full, in case you want it:

float X = ((long2 - long1) * 24901 * cos(lat1)) / 360.0
float Y = ((lat2 - lat1) * 24860) / 360.0
float X2 = X * X;
float Y2 = Y * Y;
float Distance = sqrt(X2 + Y2);
6
  • This is good but along different lines of latitude, the distance isnt the same for a given angle, even for a perfect sphere. 15 degrees near the poles is shorter than 15 degrees near the equator. I think he should calculate arc length to get X using ((long2 - long1)*2*pi*Earth radius*cos (lat1)) / 360 and Y can be gotten similarly, except the cosine shouldnt be present Apr 15, 2016 at 1:09
  • @Majenko Thanks for sharing your brilliant idea, but I already tried doing it, and unfortunately that won't work since we knew Earth is not perfectly spherical. What I am trying to know is how can I find the distance following the technical form of the Earth. Please see stated above. Apr 15, 2016 at 1:25
  • D'oh, you're quite right. I had totally overlooked that. I will update the answer in the morning.
    – Majenko
    Apr 15, 2016 at 1:35
  • If you're going to use the circumference, then 2*pi shouldnt be present in the equation; its already a part of the circumference Apr 15, 2016 at 9:55
  • @TisteAndii It's early yet and I haven't had my first sip of coffee. Again, quite right.
    – Majenko
    Apr 15, 2016 at 9:58
0

I have been always frustrated from the missing double (64bit) type in Arduino world and hence the problem with properly calculating GPS distance, bearing and destination point.

The following library uses Float64 & Math64 libs and also adds some fast and very fast implementations of trigonometric functions and fast and regular versions of GPS GPS distance, bearing and destination point.

Feel free to use it - and any help in improving it is welcome !

https://github.com/vtomanov/Gps64

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.