Click here to Skip to main content
15,888,143 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm using Unity3D and I created simple distance, speed and acceleration calculator using latitude and longitude of last position. I'm calculating last distance, speed and acceleration in each GPS update (approximately once per second). But sometimes (2-3 second interval) latitude and longitude values changes rapidly (in clear weather and no obstacles). That's why speed and acceleration values gets unreal results. For example, at stable 40 km/h speed, speed value becomes 60 km/h and returns to 40 km/h within 2-3 second. I'm here to ask how can I avoid this inaccurate and rapid GPS data changes?

I'm using Nexus 5 device

Thanks for any help and tip
PS. Please edit my question if I made any grammar and logical mistake.

What I have tried:

There is my code:

C#
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class Manager : MonoBehaviour
{
public Text longitude, latitude, lonAText, latAText, lonBText, latBText;
public Text result, overallResult, speedText, lastTimeText, timerText, accelerationText, speed0Text;

float lonA, lonB, latA, latB, overallDistance, lastDistance, timer, lastTime, speed, speed0, acceleration;
bool firstTime, allowTimer;

public AudioSource audio;

void Awake()
{
overallDistance = 0;
lastDistance = 0;
timer = 0;
lastTime = 0;
speed = 0;
speed0 = 0;

firstTime = true;
allowTimer = true;
}

IEnumerator Start()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
    yield break;

// Start service before querying location
Input.location.Start(1, 1);

// Wait until service initializes
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
    yield return new WaitForSeconds(1);
    maxWait--;
}

// Service didn't initialize in 20 seconds
if (maxWait < 1)
{
    print("Timed out");
    yield break;
}

// Connection has failed
if (Input.location.status == LocationServiceStatus.Failed)
{
    print("Unable to determine device location");
    yield break;
}
else
{
    // Access granted and location value could be retrieved
    print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);

    longitude.text = Input.location.lastData.longitude.ToString();
    latitude.text = Input.location.lastData.latitude.ToString();

    lonA = Input.location.lastData.longitude;
    latA = Input.location.lastData.latitude;
}

// Stop service if there is no need to query location updates continuously
//Input.location.Stop();
}

void Update()
{
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();

timer += Time.deltaTime;
timerText.text = timer.ToString();


if (lonA != Input.location.lastData.longitude || latA != Input.location.lastData.latitude)
{
    audio.Play();

    CalculateDistances(lonA, latA, Input.location.lastData.longitude, Input.location.lastData.latitude);  // last distance and overall distanceS            
    lonA = Input.location.lastData.longitude;
    latA = Input.location.lastData.latitude;

    lastTime = timer;
    lastTimeText.text = lastTime.ToString();
    timer = 0;


    speed0 = speed;
    speed0Text.text = speed0.ToString();

    CalculateSpeed();

    CalculateAcceleration();
}            
}   

public static float Radians(float x)
{
return x * Mathf.PI / 180;
}

public void CalculateDistances(float firstLon, float firstLat, float secondLon, float secondLat)
{
lonAText.text = firstLon.ToString();
latAText.text = firstLat.ToString();

lonBText.text = secondLon.ToString();
latBText.text = secondLat.ToString();

float dlon = Radians(secondLon - firstLon);
float dlat = Radians(secondLat - firstLat);

float distance = Mathf.Pow(Mathf.Sin(dlat / 2), 2) + Mathf.Cos(Radians(firstLat)) * Mathf.Cos(Radians(secondLat)) * Mathf.Pow(Mathf.Sin(dlon / 2), 2);

float c = 2 * Mathf.Atan2(Mathf.Sqrt(distance), Mathf.Sqrt(1 - distance));

lastDistance = 6371 * c * 1000; 

result.text = lastDistance.ToString() + " meters";

overallDistance += lastDistance;  // bu 1 anliq 6.000.000-dan         boyuk qiymet ala biler

StartCoroutine(Overall());
}

IEnumerator Overall()
{
if (firstTime)
{
    firstTime = false;

    yield return new WaitForSeconds(2);

    if (overallDistance > 6000000)
    {
        overallDistance = 0;
        lastDistance = 0;
    }
}

overallDistance += lastDistance;
overallResult.text = overallDistance.ToString() + " meters";
}

void CalculateSpeed()
{
speed = lastDistance / lastTime * 3.6f;

speedText.text = speed.ToString();
}

void CalculateAcceleration()
{
acceleration = (speed - speed0) / lastTime;
accelerationText.text = acceleration.ToString();
}
}
Posted
Updated 10-May-16 9:29am
v2

Google for "GPS location smoothing". You're going to get a less accurate location and slower response to your speed changes but you wont' get the jumping around nearly as much.

Consumer GPS isn't dead on accurate to begin with because the military owns the system, there are restrictions on the accuracy. I think it's currently receiver-limited to 4 meter horizontal accuracy and worse for vertical. A number of factors affect the accuracy of the signal from the satellites, including the number of satellites the phone can "see", how much atmosphere the signal has to go through, how far away the satellite is, ... and more. All of this affects the accuracy.

Your location will jump around from one frame to another in real time. There's nothing you can do to get a solid real-time dead on accurate location. You have to do filtering on the location to get an "average" location that's more stable. The downside to this is slower response to actual changes in location.
 
Share this answer
 
You need to take into account the problems liked with GPS.

First is accuracy or lack of. Any difference between real location and GPS location have impact on apparent speed.

Ideally, you must read position and time of calculation from GPS in order to get best data.
Otherwise, you are cumulating inaccuracies.
second best is to have the GPS triggering events when new location is available. This way you maintain a link between new location and and time.

Then worst case, you read the GPS at regular timing which don't march the timing of measure. Read a little too fast and you get the same measure more than once (which can mean you don't move. Read a little too slow a,d the speed shift depending of how old is the measure. reading real slow will reduce shifting problem, but your app will be less responsive.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900