How to get the most accurate possible speed from GPS in Android - android

How can I get an accurate speed from GPS in Android?
Yes, I am aware of the location.getSpeed() method in the Location class. Problem is, the default implementation returns 0.0 as speed: apparently that is the default behavior.
What I'm currently doing, is as follows, consider location objects a and b, where a is taken first, b later:
a.distanceTo(b)/(b.getTime()-a.getTime());
(simplified for readability, original code deals with history ArrayList)
Problem is that this is somewhat inaccurate: under normal circumstances, the data points are so close to one another that the GPS inaccuracy really becomes an issue. Either I would need to reduce the update frequency or calculate the speed relative to a point further away. The former I don't want to do, as I want to get as high a frequency as possible, but perhaps I could filter the points to calculate speed against based on their distance to one another?
The optimal solution, which I assumed the getSpeed() method would do, would be to calculate the speed against the GPS satellites themselves, thus getting a more accurate result.
Am I using the getSpeed() wrong somehow?

Since your keeping a history why not...
Get the current location and time
Find the speed between current and last ~10
Take an average of your results

Use the formula you stated to determine average speed but makes sure your two points are in a straight line. You could see if the user is still traveling in the same direction by calling Location.getBearing(). If it is close enough you could assume they traveled in a straight line. If not just discard the result.
Keep in mind this speed will be affected by any stops such as stop signs or stop lights. Sample as often as possible and discard any obvious outliers.

The emulator apparently always answers 0 as speed, but the real device
should not. Do you have the same issue on the real device? – Stefan
Mar 20 at 8:21
Stefan's answer was actually correct. Apparently the emulator does not give the speed, as that's not contained in the GPX file input as the testing data. So if you want to show speed, test on a real device and go for a jog, it'll work (for most devices).
Below are some thoughts for other methods of detecting speed, but not strictly relevant, but might be interesting if you're working with GPS.
Due to the relative inaccuracy of GPS, particularly at slow speeds or curvy roads the speed is hard to calculate: either the distance between data points is so short GPS inaccuracy comes to play, or so long it becomes inaccurate when not moving straight. Also, if the minimum distance between data points to calculate speed is long, at slow speeds the update interval becomes a problem.
There are ways around this problem, such as using the getAccuracy() method to calculate minimum safe distance between data points and using it dynamically, filtering data points based on maximum acceleration and deceleration values, movement direction and so on. You can also calculate a rolling average to calm down the changes a little and get a pretty good idea of what's what.
The above methods may be useful also even if you don't calculate speed based on distance covered, as sometimes the GPS seems to return speed as 0, even when you're moving. I used acceleration/deceleration figures from F1 cars as filters :)

Related

How do I perform geolocation to get data as accurate and precise as possible?

we are developing a multiplatform (android and ios) application in react-native, which mainly deals with geolocation data, thus it higly depends on accuracy and precision of the data. For instance, the application accumulates - reads and saves - the user's geolocation data every 5 seconds for ie 10 minutes (lets call it a track). So, during the track, there are about 200 measurements saved. Later on, we perform different computations based on the data accumulated during the track and visualise results to the user.
While on iphone the altitude graph of data measured at physically (nearly) identical alltitude has rather linear/smooth characteristics, on android there tend to be +-5 meters peaks. Lets say we want to measure total meters elevated during the track, thus to compute the sum of differences between succeeding measurements. Now imagine, how much the mentioned imprecision influences the result - there might be 5 meters altitude change every 5 seconds. Although physically your total elevation is +-0 meters, the total elevation computed may differ drastically.
So, to eliminate the errors, for us, there are basically two ways:
to make the measurements more accurate and precise (this is natural)
to perform some sort of approximation and adjust the measurements accordingly (this is hacky)
The first way sounds much better, but we are aware of the specific device's hardware limitation - we simply cannot fix inaccurate hardware with our software. The problem is, even on the same device, other commercial apps (ie Runtastic) perform the measurement "better" (even offline). That makes me think about the second (approximation) way. This way is rather hacky, and although it can lead to good-looking result in many cases, we think (but cannot prove) there is not such a prefrect approximation that will never corrupt the data "too much".
So, our questions are:
What are the techniques to make every altitude measurement as accurate and precise as possible on android? Which tools can be useful to accomplish that and how should we use them to get the best experience? We can think of:
gps altitude
nmea altitude
barometer
online API to get altitude based on latitude and longitude
Is it worth to apply some sort of approximation on the accumulated data? If so, what aspects (or even better ideas) should we take into account? Is this technique common?
Is there any different solution we did not mention?
Thanks in advance!
GPS altitude is the best one. but it depend on the gps chip. There are some with high accurate(High Cost). Most Phone GPS use online to get data also(For get good Hot start)
To Smooth GPS data(Or any other) ,You can use Kalman Filter. It complex and heavy but. it can guarantee the result and avoid misleading data very well.
OR
you can omit misleading packets base on pervious ones (Mean Filter) - Simple, But should be coded preciously
NOTE : I haven't use barometer. I gave my answer without it. Good luck
If you have a barometer then it's accuracy can be a lot better for altitude than you get with a phone quality gps. It's why high end bike computers and gps tracking watches have barometers in them. This is especially true if your interested in relative altitude differences rather than the actual real altitude. To get a good actual altitude with the barometer you need some sensible calibration scheme and be aware of the effects of the weather over time.
Whatever your source of altitude data you should expect to do some form of post processing on the data to get something sensible. What the processing will need to be will depend on your situation and what what you consider important.
For getting the total climb over a track you have 3 cases to consider. The easy case is simple going up or down a single consistent hill, you want to get the correct altitude difference value which is easy to check with a good map. At the other end going along a totally flat route you want to get zero climb again nice and easy to check but not so easy to achieve with typical hardware. In the middle going over undulating terrain is far harder to check although possibly the far more interesting case for the user. Getting this accurate is some form of trade off against the totally flat situation. I have code doing this in my app and with the filtering I have I know that the totally flat will over read a bit clocking up 20-30m climb in an hour. The undulating case will under count by about 1m for each undulation. The single big hill is generally pretty accurate given the known limitation of a barometric type system. Gps only based is nothing like as good. Typically going back to an online lookup approach is more consistent for a gps based system but it depends on the quality of the lookup data and the type of terrain.

Accurate distance with GPS?

I'm developing iOS/Android app that tracks mileage user has driven in his car.
Even though the task seems pretty trivial, there are 2 problems:
1) Mileage is not accurate comparing to car's odometer. (OD-10mi, App-8.5mi)
2) When user stays still outside the car, mileage keeps accumulating (it can add up like 4mi within 30 minutes.)
Is there any "easy" fix for that without adding complicated filtering, etc?
There are two small but significant things you can do:
For each GPS sample, check its accuracy. If it's over some threshold (say 20 meters) - ignore it.
Add a method that detects if the mobile is static or not. You can do it by reading the device's accelerometer - if the delta between two readings is bigger than some threshold - the car is moving. If it's too small - ignore the GPS. You'll have to try some values until you find the right threshold/
For question 1, vehicle odometer, in the US, are only required to be within 5mph of the actual speed at 50mph. My experience shows most vehicles are more erroneous than the law requires. That 10% difference could easily become the 1.5 miles you saw.
Vehicles odometers are allowed to over estimate in europe by 7%.
My car has about 3% over estimate.
There are simple solutions, that work for cars, that have been posted here on Stackoverflow multiple times, including by myself.
There is no simple solution for pedestrians.
Answer to question 2: problem certainly comes from the accurary of the GPS location.
Android Location object comes with an estimated accuracy for the given coordinates.
Suppose you stay in absolute position (0,0) without moving. The android device GPS could produce the following Locations stream:
(1,1) with an accuracy of 2m
(-2,3) with an accuracy of 5m
(0,0) with an accuracy of 1m
etc...
If you just keep adding the distances between the successive Locations, the sum will indefinitely increase, although you don't move.
One solution could be that you take into account new Locations from the stream only if their accuracy is small enough compared to the distance to the last location.

what would be a good way to calculate the current speed of an android?

I am writing an android program that is a speedometer. the way it works wright now is it takes 2 GPS locations over time, and divides the distance by time to get speed. the problem with this is that it only refreshes when the gps moves, so when I stop moving it would stay at the last speed that I had. is there a better way of doing this?
You could keep track of how long it is since you've had the last update, and adjust the speed after a certain amount of time has past. (You could use a Handler to schedule the check).
In general gps is only going to give you a rough estimation of the speed though.
You can also use the Location object's speed estimate directly (check that it has one by calling hasSpeed(), then get it by calling getSpeed()).

tracking a subway map

let's say i want to build a smartphone app that tells a user when/where to get off a subway station. i can think of two ways of doing this:
1) using GPS and map of the subway routes, track the location of the user and notifies him when the destination is reached
2) have him press start when he gets on a train as the train starts (which may not be realistic because the user could simply forget to do this), use the known travel time from starting station to end station, and simply notifies him when the time is up.
can someone tell me if there are any other good approaches? thanks.
You may have to go with 'dead reckoning'. Basically, dead reckoning is a navigation technique that uses a confirmed starting location plus accurate velocity and time to calculate a new location. Keep in mind that velocity is itself a combination of heading and speed and that the heading must be a true heading. In an airplane, compass heading would have to be combined with wind speed and direction to get a true heading. I don't think you have to account for drift on a subway, but you will have to account for varying device orientation as the user moves around or uses the device itself. Also, just because heading is normally a compass bearing doesn't mean that it has to be. You may be able to get the job done using only the accelerometers and a timer.
Proper use of dead-reckoning also requires frequent 'resets' to known locations as you reach them so that errors can't add up too badly. For this application, I would argue that curve- and stop-detection can be used as resets. You may get false positives for 'service' stops that are too close to real stops, but those may be rare enough to ignore. In fact, if it wasn't the exit stop, it might not matter because you might still be accurate enough for the next-stop warning and if was the exit stop, it won't matter because the ride is over.
To summarize: you need to be sure that you have a good initial starting point; you need to compensate for device reorientation to get true heading; you need to know your average speed between heading changes and the time-on-heading to calculate distance-on-heading. You can improve overall accuracy by resetting at known landmarks.
Edit: I don't know if this gets you any closer to the answer, but Chris Stratton raised an interesting point about summing the accelerometer vectors. Is it possible to track the orientation of the device accurately enough to have a reliable orientation-independent gravity vector? Can you keep that out of your vector sum? Can that provide a useful acceleration along a useful orientation-independent vector? If so, then tracking the duration of the acceleration will get you an average speed for that duration and a final speed for the end of acceleration. Absent acceleration, the speed will remain constant. Putting that all together might pile inaccuracy on top of inaccuracy to the point of uselessness.
If the subway line has cellular service (some that were going to had it turned off on security concerns) you might be able to do something with network location.
You could use the accelerometer to try to detect and count station stops - but trains stop in between stations from time to time due to delays ahead. Also battery life would be reduced. EDIT: realized you won't be able to tell acceleration from deceleration as you have no idea of orientation (unless you find the compass sensor workable in that environment) - you could only see that the vector sum of the three accelerometers was greater than gravity for a period of seconds.
You could try to use the microphone to detect the sounds of train motors and brakes (some are extremely characteristic) but that has the same problem with battery life and unscheduled stops between stations. Not to mention scheduled stations bypassed for repair work.
Perhaps you should give the user a scrollable list of stations marking the journey and let them keep track.
Both of those sound like poor solutions. You almost certainly won't get a GPS trace in a subway. And the 2nd way sounds like it will be inaccurate enough to make the app useless.
Read carefully Falmarri's answer. He's completely right, although he didn't give you an answer. Let me try then...
If the routes have no many curves, it will be easier: you just have to hardcode the latitude and longitude of each station, and then, calculating the position of the user will be straightforward (just a little of math and that's it). If the routes have curves, then you have more work to do but it's basically the same.
You will probably want to use a way to know the distance between the current location and the station location. You could use some of the existing algorithms, for instance the Haversine formula.

Best practice to calculate the average speed from GPS coordinates

I have here a device which can give me GPS coordinates. The time interval I can define. I want to use it to calculate the average speed during driving or travelling by car. Actually I used a orthodrome formula to calculate the distance between two points and then divided it by the given time interval. By the implementation I followed this term. Unfortunately I could only find a German link, but I think the formula should be understandable in any language ;)
Unfortunately, using this formula and a time interval of 1 second gives very unprecise results. The speed while walking is between 1 km/h and 20 km/h.
So I wonder if there is a general reference on how to implement distance calculation between two GPS coordinates (I found something similar on SO) and particulary, which is the best time interval to update the GPS coordinates?
I assume that you're testing this by walking at a constant speed (I think ~5 kph is a normal walking speed) while measuring your GPS position once per second.
The variation that you're seeing in instantaneous speed (the distance between each measured point divided by 1 second) is either due to random variation in the measured GPS position or else you aren't taking your measurements exactly one second apart (or it could be both of these things).
I'm going to assume your measurements are being taken precisely one second apart. Hand-held GPS devices are much less accurate than advertised. While it's often claimed that the devices are accurate to within 10 ft. of the true position, this simply isn't so.
The best way to measure and report the accuracy of a GPS device is to leave it in a place where it can see the satellites and not be rained on, and record a few day's worth of data. You can then use Google Maps to plot the points - I've done this around my house and around the office, which is a good way to give you a sense of scale.
Obviously, if the devices were perfectly accurate, you would see all your measured points in one spot. Or, if the 10 ft. accuracy thing were true, you would see all the points in a little cluster inside a 20 ft. diameter circle.
What you see instead (with every GPS-enabled device I've ever tested) is a combination of relatively small positional scattering (on the order of a few tens of feet) occurring on a scale of a few seconds, and a longer-term "random walk" of the average position which might move 200 or 300 ft. in the course of a day or two. When plotted over your own house, for example, it might look like your PDA wandered over to the neighbor's house, then across the street, then down the street two houses, back towards you etc., all while jittering around 5 or 10 feet here or there like it drank too much coffee.
GPS can be more accurate than this. Surveyors use devices with much more powerful receiver sets (so they get a much more accurate read on the satellite signals), and they leave them in place for days at a time to average successive measurements. Handheld devices have cheap receiver chips and cheap antennas and have to deal with all kinds of signal interference anyway.
Your best bet is to do a running average to calculate your instantaneous speed. Instead of dividing the distance between the current point and the previous point by 1 second, take the last 5 distances between points and divide by 5 seconds (or whatever number of seconds you use). It's important not to just take the difference between the current point and the point 5 seconds ago and divide this distance by 5, as that would miss any non-linear movement.
Update: I noticed in a comment that you're using an Android device. Do you know if it has a built-in GPS receiver? Many (most?) Android devices don't, which means their GPS is not the triangulate-on-the-satellites version of GPS, but the guess-where-I-am-based-on-the-signal-from-the-cell-towers version. This is much less accurate positionally, as I'm sure you could tell from the snarkiness of my description. :)
GPS systems can yield instantaneous velocity directly, without interpolating positions. I read somewhere that the velocity reading is actually more accurate than the position reading. What device/system/OS are you using?
On Android, try the android.location.Location.getSpeed() method (along with hasSpeed()) in your LocationListener implementation.
Search on google for GPS SPEED ACCURACY, and you will find reports stating that speed calculated out of position-vs-time is ten times worse than just using the speed parameter coming right out from the GPS receiver. The speed parameter is not depending on position accuracy, but is calculated out of doppler (speed/frequency difference) from the satellite signals.
Good luck

Categories

Resources