Averaging gps data

Best all,

I want to get more accurate measurements from my GPS modules.

I've read that using a Kalman filter works well, and an averaging technique will enhance it as well.

First of all, there are lots of libraries on Arduino for Kalman filters, which one would work the best? I'm using the TinyGPS++ library to decode all of the parameters of the GPS modules.

Secondly, I think using an averaging technique will be more simple, but how can I average the positions if my program only keeps printing out data? Could anyone share some examples?

Putting the GPS modules on a non-moving object will be easier to average, but what do I need to do if the GPS modules are on a moving object, e.g. ship or car, because the position will change continiuously.

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

TinyGPSPlus gps1;
TinyGPSPlus gps2;

double  lat1;
double  lat2;
double  lon1;
double  lon2;


TinyGPSCustom pdop(gps1, "GPGSA", 15);
TinyGPSCustom pdop2(gps2, "GPGSA", 15);
TinyGPSCustom vdop(gps1, "GPGSA", 17);
TinyGPSCustom vdop2(gps2, "GPGSA", 17);

void setup() {
   Serial.begin(4800);
   Serial2.begin(4800);
   Serial3.begin(4800);
  }

void loop() {

  while (Serial2.available() > 0)
    if (gps1.encode(Serial2.read())){
      displayInfo1(); 
      afstand_koers();
    }
    
  if (millis() > 5000 && gps1.charsProcessed() < 10)
  {
    Serial.println(F("GPS1 niet gevonden: check bedrading."));
    while(true);
  }

  while (Serial3.available() > 0)
    if (gps2.encode(Serial3.read())){
      displayInfo2();
      afstand_koers();
    }
    
  if (millis() > 5000 && gps2.charsProcessed() < 10)
  {
    Serial.println(F("GPS2 niet gevonden: check bedrading."));
    while(true);
  }

}

void displayInfo1()
{
  Serial.print(F("GPS1: "));
  if (gps1.location.isValid())
  {
    lat1 = gps1.location.lat();
    Serial.print(lat1, 6);
    Serial.print(F(","));
    lon1 = gps1.location.lng();
    Serial.print(lon1, 6);
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  if (gps1.speed.isValid())
  {
    Serial.print(gps1.speed.knots());
    Serial.print(F(" "));
    Serial.print(gps1.speed.kmph());
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  if (gps1.course.isValid())
  {
    Serial.print(gps1.course.deg());
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  if (gps1.time.isValid())
  {
    if (gps1.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps1.time.hour());
    Serial.print(F(":"));
    if (gps1.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps1.time.minute());
    Serial.print(F(":"));
    if (gps1.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps1.time.second());
    Serial.print(" ");
  }
  else
  {
    Serial.print(F("INVALID"));
  }

    if (gps1.altitude.isValid() && gps1.satellites.isValid() &&
    gps1.hdop.isValid())
  {
    Serial.print(F("ALT= "));  Serial.print(gps1.altitude.meters()); 
    Serial.print(" PDOP= ");    Serial.print(pdop.value());
    Serial.print("|");
    Serial.print(F(" HDOP= ")); 
    double h_dop = gps1.hdop.value();
    Serial.print(h_dop / 100);
    Serial.print(" ");
    Serial.print("VDOP= "); Serial.print(vdop.value());
    Serial.print("|");
    Serial.print(F(" SATS= ")); Serial.print(gps1.satellites.value());
  }
  
}

void displayInfo2()
{
  Serial.print(F("GPS2: "));
  if (gps2.location.isValid()) //Laat locatie zien
  {
    lat2 = gps2.location.lat();
    Serial.print(lat2, 6);
    Serial.print(F(","));
    lon2 = gps2.location.lng();
    Serial.print(lon2, 6);
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  if (gps2.speed.isValid())
  {
    Serial.print(gps2.speed.knots());
    Serial.print(F(" "));
    Serial.print(gps2.speed.kmph());
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  if (gps2.course.isValid())
  {
    Serial.print(gps2.course.deg());
    Serial.print(F(" "));
  }
  else
  {
    Serial.print(F("INVALID "));
  }
  
  if (gps2.time.isValid())
  {
    if (gps2.time.hour() < 10) Serial.print("0");
    Serial.print(gps2.time.hour());
    Serial.print(":");
    if (gps2.time.minute() < 10) Serial.print("0");
    Serial.print(gps2.time.minute());
    Serial.print(":");
    if (gps2.time.second() < 10) Serial.print("0");
    Serial.print(gps2.time.second());
    Serial.print(" ");
  }
  else
  {
    Serial.print(F("INVALID"));
  }

    if (gps2.altitude.isValid() && gps2.satellites.isValid() &&
    gps2.hdop.isValid())
  {
    Serial.print(F("ALT= "));  Serial.print(gps2.altitude.meters()); 
    Serial.print(" PDOP= "); Serial.print(pdop2.value());
    Serial.print("|");
    Serial.print(F(" HDOP= "));
    double h_dop_2 = gps2.hdop.value(); 
    Serial.print(h_dop_2 / 100);
    Serial.print(" ");
    Serial.print("VDOP= "); Serial.print(vdop2.value());
    Serial.print("|");
    Serial.print(F(" SATS= ")); Serial.print(gps2.satellites.value());
  }
  
}
}

Thank you all very much for taking the time to read this topic!

If I wrote down 10 latitude values as they arrived and gave you the pencil and paper then how would you calculate the average ?

I would of course add them all together and divide it by how many latitude values I got, but my code doesn't really stop after a certain amount of values, it keeps printing data until I stop the program myself.

Your code does not need to stop

At its most basic, when the first reading arrives save it. When the next reading arrives add it to the first reading and so on. When 10 readings have arrived and been added to the total divide it by 10 to get the average, set the total to zero and do it all over again

NOTE : there are better ways to do this but this way is very easy to understand and matches the simple pencil and paper method

That's pretty understandable, I appreciate the help. However, my programming skills are not the best. What can I do to save the values?

It doesn't help much to average GPS location values over a few readings, because positional errors (due to signal path distortions, poor satellite coverage, etc.) persist for some time.

This plot shows 15 minutes of typical GPS data, illustrating the problem. The reported position wanders over 20 meters, and the positional errors are clearly NOT random.

For some improvement in positional accuracy, plan on collecting and averaging data for many hours.

I used latitude as an example, but what value or values in your current sketch do you want to average ?

If averaging\filtering of a GPS position over the short term improves accuracy, you would expect it to be a very common techique indeed, given how long micros and GPSs have been around.

Can you point to any working code that demonstrates accuracy is improved short term ?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.