Making GPS as accurate as possible

In my app I’m getting the GPS location and save it to the cloud. I simultaneously measure distance between points and sum them. The problem is that however I’ve set accuracy to 10 meters it is still very inaccurate. Once I start  the location tracker I get 0.6 miles and than 0.1 adds up every second. Having looked on the coordinate themselves I have seen that while the iPhone is in one place it records different coordinates nearby the actual location. 
How I make it more accurate. Maybe recording only certain coordinates or recording coordinates every 10 seconds. 
What would you recommend?

I’m not sure I follow the problem here. Perhaps some code would help us understand.

Rob

Ok, maybe I miss something fundamental. here is what I have
I have the location listener which records coordinates and adds them to a table. later coordinates are summed up (see function distanceBetween below ) and the degrees are then turned to miles and displayed as text. The problem is that I obtain 0.6 a;most immediately after the launch of the location service
 

local locationEnabled = false system.setLocationAccuracy( 10 ) locationHandler = function( event ) if locationEnabled == true then -- Check for error (user may have turned off location services) if ( event.errorCode ) then native.showAlert( "GPS Location Error", event.errorMessage, {"OK"} ) print( "Location error: " .. tostring( event.errorMessage ) ) else startLat, startLon = event.latitude, event.longitude print(event.latitude, event.longitude) --- add coordinates to table counter = counter+1 movementTable[counter] = {} movementTable[counter].lat, movementTable[counter].lng = event.latitude, event.longitude local table = json.encode(movementTable) if counter\>1 then DD.distanceBetween( movementTable[counter-1], movementTable[counter], counter,"current") currentTotalDistance = currentTotalDistance+ currentDistance[counter] --turn degrees to miles local distancekm = currentTotalDistance \* ( 10000 / 90 ) local distanceFeet = distancekm \* 3280.84 local distancemi = distanceFeet/5280 --- display one digit after the dot distancemi = math.round(distancemi\*10)\*0.1 distanceText.text = distancemi.." mi" end end end end

Here is distanceBetween function I’m referring to.
 

DD.distanceBetween = function( point1, point2, count, typeD ) local dX = point2.lng - point1.lng local dY = point2.lat - point1.lat if typeD == "total" then distance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) --print("distance", distance[count] ) return distance[count] elseif typeD == "week" then weekDistance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) --print("distance", distance[count] ) return weekDistance[count] elseif typeD == "current" then currentDistance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) return currentDistance[count] end end 

Hope this clarifies the question.

It’s going to be real hard with out seeing the values of the print statements getting the lat and long to check the math in your distance calculation function.

I don’t know how much you’re moving between events, so its very likely your movement is working out to 0.1 per event. Remember lat and long are in degrees. There are 69 miles per degree so depending on your movement 0.1 might be very real.

Also, you do this:   local table = json.encode(movementTable)

while I don’t see an use of the variable table afterwards or anything that would use the table object, you temporarily trash the internal table.* API’s. Its not really safe to use “table” as a variable name.

As for the table, you’re completely right! I had used this json later on for a reason, but now I have no more need in it.

Here is what I’m geting(1 second of location handler sitting and not moving)
total distance(degrees): 5.2594401346301e-05
distancekm: 0.0058438223718227
distancefeet: 19.172646190371
distance miles(before rounding up): 0.0036311829906005

Does it make sense? If i continue using listener and up to moving it mounts up to 198 feet in 1 minute and then considerably slows down in adding distance. 2:30 and only 227 feet. 
 

The 0.6 miles I initially stated was a remark for my client. He told me that he got 0.6 miles without yet leaving the parking lot. 

I think it’s your rounding code.  There are 5280 feet in a mile. You’re rounding off to 10ths of a mile (528 feet). Even if you round off to 100ths, its 52.8 feet.

Rob

So my rounding code should look something like:
 

distancemi = math.round(distancemi)\*0.1

Sorry, I’m bad at math.

Hi.  I wanted to interject that you’re working too hard.  Don’t write the code to calculate delta distance yourself.  Let some else do it.

There is an equation called the “Haversine Distance”.  I’ve borrowed someone else’s code and you can now borrow it from me:

-- Calculate the distance from one decimal lat-long position to another. -- Distance is a multiple of R (either kilometers or miles) -- More accurate for short distances than long. function math.haversine\_dist( lat1, lng1, lat2, lng2, R ) --[[haversine formula dlon = lon2 - lon1 dlat = lat2 - lat1 a = (sin(dlat/2))^2 + cos(lat1) \* cos(lat2) \* (sin(dlon/2))^2 c = 2 \* atan2( sqrt(a), sqrt(1-a) ) d = R \* c (where R is the radius of the Earth; radius of the Earth: 3961 miles and 6373 km) --]] local mRad = math.rad local mCos = math.cos local mSin = math.sin local mSqrt = math.sqrt local mAtan2 = math.atan2 R = R or 6373 -- Default radius of earth in km local dlng = mRad(lng2 - lng1) local dlat = mRad(lat2 - lat1) lat1 = mRad(lat1) lat2 = mRad(lat2) local a = (mSin(dlat/2))^2 + mCos(lat1) \* mCos(lat2) \* (mSin(dlng/2))^2 local c = 2 \* mAtan2( mSqrt(a), mSqrt(1-a) ) local d = R \* c --(where R is the radius of the Earth) return d end

Now, if you have start lat-lng and current lat-lng you can get the delta distance like this:

print( "Delta Dist in kilometers: ", math.haversine\_dist( startLat, startLng, curLat, curLng, 6373 ) ) print( "Delta Dist in miles: ", math.haversine\_dist( startLat, startLng, curLat, curLng, 3961 ) )

Thanks roaminggamer! output seems to be more accurate but again how do I round it up to one digit after dot correctly?

 

I don’t think you should. 0.1 is 568 feet. It sounds like you need more resolution to this. 0.01 is 56.8 feet and 0.001 is 5.68 feet. You can’t measure small movements without enough resolution.

Now what I would do is not round at all while you’re doing your math, but output the visual like this:

distanceText.text = string.format("%0.1f", distancemi)

Rob

-- == -- round(val, n) - Rounds a number to the nearest decimal places. (http://lua-users.org/wiki/FormattingNumbers) -- val - The value to round. -- n - Number of decimal places to round to. -- == function math.round2(val, n) if (n) then return math.floor( (val \* 10^n) + 0.5) / (10^n) else return math.floor(val+0.5) end end

 Or use format as suggested by rob to get a string formatted number.

Thanks guys for your help!

Any tips on how to reduce or eliminate this “garbage” location collecting (even if still, the phone receives different location coordinates)?
 

Not sure I follow. Can you explain better what is happening and what you want to do?

Thanks

Rob

I’m not sure I follow the problem here. Perhaps some code would help us understand.

Rob

Ok, maybe I miss something fundamental. here is what I have
I have the location listener which records coordinates and adds them to a table. later coordinates are summed up (see function distanceBetween below ) and the degrees are then turned to miles and displayed as text. The problem is that I obtain 0.6 a;most immediately after the launch of the location service
 

local locationEnabled = false system.setLocationAccuracy( 10 ) locationHandler = function( event ) if locationEnabled == true then -- Check for error (user may have turned off location services) if ( event.errorCode ) then native.showAlert( "GPS Location Error", event.errorMessage, {"OK"} ) print( "Location error: " .. tostring( event.errorMessage ) ) else startLat, startLon = event.latitude, event.longitude print(event.latitude, event.longitude) --- add coordinates to table counter = counter+1 movementTable[counter] = {} movementTable[counter].lat, movementTable[counter].lng = event.latitude, event.longitude local table = json.encode(movementTable) if counter\>1 then DD.distanceBetween( movementTable[counter-1], movementTable[counter], counter,"current") currentTotalDistance = currentTotalDistance+ currentDistance[counter] --turn degrees to miles local distancekm = currentTotalDistance \* ( 10000 / 90 ) local distanceFeet = distancekm \* 3280.84 local distancemi = distanceFeet/5280 --- display one digit after the dot distancemi = math.round(distancemi\*10)\*0.1 distanceText.text = distancemi.." mi" end end end end

Here is distanceBetween function I’m referring to.
 

DD.distanceBetween = function( point1, point2, count, typeD ) local dX = point2.lng - point1.lng local dY = point2.lat - point1.lat if typeD == "total" then distance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) --print("distance", distance[count] ) return distance[count] elseif typeD == "week" then weekDistance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) --print("distance", distance[count] ) return weekDistance[count] elseif typeD == "current" then currentDistance[count] = math.sqrt( ( dX^2 ) + ( dY^2 ) ) return currentDistance[count] end end 

Hope this clarifies the question.

It’s going to be real hard with out seeing the values of the print statements getting the lat and long to check the math in your distance calculation function.

I don’t know how much you’re moving between events, so its very likely your movement is working out to 0.1 per event. Remember lat and long are in degrees. There are 69 miles per degree so depending on your movement 0.1 might be very real.

Also, you do this:   local table = json.encode(movementTable)

while I don’t see an use of the variable table afterwards or anything that would use the table object, you temporarily trash the internal table.* API’s. Its not really safe to use “table” as a variable name.

As for the table, you’re completely right! I had used this json later on for a reason, but now I have no more need in it.

Here is what I’m geting(1 second of location handler sitting and not moving)
total distance(degrees): 5.2594401346301e-05
distancekm: 0.0058438223718227
distancefeet: 19.172646190371
distance miles(before rounding up): 0.0036311829906005

Does it make sense? If i continue using listener and up to moving it mounts up to 198 feet in 1 minute and then considerably slows down in adding distance. 2:30 and only 227 feet. 
 

The 0.6 miles I initially stated was a remark for my client. He told me that he got 0.6 miles without yet leaving the parking lot. 

I think it’s your rounding code.  There are 5280 feet in a mile. You’re rounding off to 10ths of a mile (528 feet). Even if you round off to 100ths, its 52.8 feet.

Rob