For my Android app I need to determine when the user increases its speed and when it decreases it, I don't need to find the exact speed value, only know if it has increased, decreased or it's the same.
The first solution I came up with was to register a listener for GPS and in the onLocationChanged() method calculate the speed and then check to see if it was greater or equal, but it didn't worked, beacuase the speed was very inaccurate.
Another solution I tried was to use the accelerometer to measure the steps in two seconds, and compare that measure to the previous one, to see what was greater, but I didn't found an exact algorithm. I found some approximation from Android pedometer Github code sample: https://github.com/bagilevi/android-pedometer , but it wasn't too accurate.
So, what solution should I use? What's the most effective way of counting steps with accelerometer?
Thank you.
Related
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.
I am trying to make a very simple Android pedometer, but so far it's failing pretty badly. I got some advice here and there on the internet, but nothing seems to be working.
I basically set an acceleration sensor and get the values of the x, y and z axis. After that I calculate their distance from the origin, which is basically:
d = sqrt(x²+y²+z²) followed by the calculation of their moving average. My idea was whenever I find a local peak I should count as a step. The issue is, I have no idea how to find the local peak right away in order to count the step. I am sorry if this seems like a simple problem, but I really have no idea how to go on from here.
Thank you very much.
I tried to implement this and the approach you take is subject to substantial measurement errors. You should just accept it. The reasons are:
a phone can be in any location, not only the trousers' pocket
phone accelerators are not medically precise, and they can deviate and "flow" given exactly the same position in space
moving average is not the best known technique to do this, a better one would use some sort of waves and wavelet analysis
One step has two local maximums and two local minimums (if I remember correctly)
There is no strict definition of a "step" globally accepted, this is due to physiology, measurements and various techniques used in the research field
Now to your question:
Plot the signal from the three axis you have, this will dramatically help you (signal vs time)
Define a window of a fixed (or slightly moving) size, moving window is required to detect people who walk slower, run or have disability
Every time you have a new measurement (usual frequency is about 20-30 Hz), put one to the tail of the window (your signal measurement's queue) and pop one from the head. In this way you will always have a queue with the last N measurements
Again for every mesurements recalculate your stuff and decide if the window contains one (or two!) minimums and count it as a step
good luck!
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 :)
I am working on an application where I would like to track the position of a mobile user inside a building where GPS is unavailable. The user starts at a well known fixed location (accurate to within 5 centimeters), at which point the accelerometer in the phone is to be activated to track any further movements with respect to that fixed location. My question is, in current generation smart phones (iphones, android phones, etc), how accurately can one expect to be able to track somebodies position based on the accelerometer these phones generally come equip with?
Specific examples would be good, such as "If I move 50 meters X from the starting point, 35 meters Y from the starting point and 5 meters Z from the starting point, I can expect my location to be approximated to within +/- 80 centimeters on most current smart phones", or whatever.
I have only a superficial understanding of techniques like Kalman filters to correct for drift, though if such techniques are relevant to my application and someone wants to describe the quality of the corrections I might get from such techniques, that would be a plus.
If you integrate the accelerometer values twice you get position but the error is horrible. It is useless in practice.
Here is an explanation why (Google Tech Talk) at 23:20.
I answered a similar question.
I don't know if this thread is still open or even if you are still attempting this approach, but I could at least give an input into this, considering I tried the same thing.
As Ali said.... it's horrible! the smallest measurement error in accelerometers turn out to be rediculess after double integration. And due to constant increase and decrease in acceleration while walking (with each foot step in fact), this error quickly accumulates over time.
Sorry for the bad news. I also didn't want to believe it, till trying it self... filtering out unwanted measurements also doesn't work.
I have another approach possibly plausible, if you're interested in proceeding with your project. (approach which I followed for my thesis for my computer engineering degree)... through image processing!
You basically follow the theory for optical mice. Optical flow, or as called by a view, Ego-Motion. The image processing algorithms implemented in Androids NDK. Even implemented OpenCV through the NDK to simplify algorithms. You convert images to grayscale (compensating for different light entensities), then implement thresholding, image enhancement, on the images (to compensate for images getting blurred while walking), then corner detection (increase accuracy for total result estimations), then template matching which does the actual comparing between image frames and estimates actual displacement in amount of pixels.
You then go through trial and error to estimate which amount of pixels represents which distance, and multiply with that value to convert pixel displacement into actual displacement. This works up till a certain movement speed though, the real problem being camera images still getting too blurred for accurate comparisons due to walking. This can be improved by setting camera shutterspeeds, or ISO (I'm still playing around with this).
So hope this helps... otherwise google for Egomotion for real-time applications. Eventually you'll get the right stuff and figure out the jibberish I just explained to you.
enjoy :)
The optical approach is good, but OpenCV provides a few feature transforms. You then feature match (OpenCV provides this).
Without having a second point of reference (2 cameras) you can't reconstruct where you are directly because of depth. At best you can estimate a depth per point, assume a motion, score the assumption based on a few frames and re-guess at each depth and motion till it makes sense. Which isn't that hard to code but it isn't stable, small motions of things in the scene screw it up. I tried :)
With a second camera though, it's not that hard at all. But cell phones don't have them.
Typical phone accelerometer chips resolve +/- 2g # 12 bits providing 1024 bits over full range or 0.0643 ft/sec^2 lsb. The rate of sampling depends on clock speeds and overall configuration. Typical rates enable between one and 400 samples per second, with faster rates offering lower accuracy. Unless you mount the phone on a snail, displacement measurement likely will not work for you. You might consider using optical distance measurement instead of a phone accelerometer. Check out Panasonic device EKMB1191111.
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()).