I'm experimenting with adding the GPS functionality to my iPhone app. It's a workout app that will be used while walking or running. So what I want to use GPS for is to show the speed that the person is moving in Mph and minute/mile.
How should I configure the CLLocationManager so I get the best possible results? What should I set desiredAccuracy and distanceFilter?
I've tried with:
distanceFilter = 10 and desiredAccuracy = kCLLocationAccuracyNearestTenMeters
and reading
CLLocation.speed property
Testing while driving around in my car the accuracy seems good compared to the car speedometer although it takes a while to update. I realize that the update delay may very well be the time it takes to query the GPS location, but I'm not sure if changing the above two parameters would give better results.
Should I use kCLLocationAccuracyBest and some other value for distanceFilter?
I'm interested to hear from others using CoreLocation to get speed. What are you doing to get more accurate results?
For best results, you should use kCLLocationAccuracyBest. What you put into your distance filter depends on up with which faults you're willing to put. Basically, you're going to have to make decisions based on accuracy vs availability. That is, during periods when a best-accuracy answer is not available, what will you display?
One approach is to let the phone deliver less-accurate answers and, using a projection of what was happening the last time you had best-accuracy information, see if what you have makes sense.
That is, suppose I'm jogging at 6mph to the North. You plot me along point-A, point-B, point-C... then you get a low-accuracy answer (maybe kCLLocationAccuracyNearest100Meters.) Look at the spot where it says I am and figure out "could I have gotten to that spot from point-C if I'd continued along my current path, making reasonable adjustments for possible changes in speed?" If so, then the new point is within the realm of possibility. (If not, then toss it out.) Then project from point-C at my last-known speed and figure out where you think I probably am, ballistically. Save that as ballistic-point-D.
Of course, you're using the accelerometer to get some sort of inertial sense of which way I went, right? So, you can't know direction (you don't know what way the phone is pointing), but you can make a reasonable stab at distance.
Using all this information, plot the most likely spot where you think I probably am.
NOTE: When testing, don't just drive in good-cell coverage areas. See how your app performs out in the hills, away from cell phones. A lot of people like to bike & jog those areas!
Disclaimer: I've only played with CoreLocation a bit, I've not tested the accuracy very closely.
I'd expect that you'd get the most accurate results by using the defaults for distanceFilter and desiredAccuracy. Less-frequent updates are only going to give you less data to work with.
One issue you're likely to run into is when the location fix is lost for a while, then comes back. The naive, connect-the-dots approach to figuring out distance traveled is going to tend to under-estimate the actual speed of the runner. Rather than using CLLocation.speed, you might get better results calculating speed based on some heuristic approximation to the line the runner is actually following.
Related
I am implementing an app which measures the how much distance it has moved .For example if my device felldown from my table to ground ,then I would like to calculate the distance.So Kindly help me to do this. Let me know if my question is not clear.
Thanks in advance.
Your question is very clear : you want to compute the second level integral of the acceleration, which theorically is possible, by supposing the speed null at some time, but I really doubt you could get something precise enough to make any sense (as in many integral computations).
This isn't done today because the error is too big. Done in hardware (for permanent integration of the acceleration) it could be a little more precise but probably not enough to really compute a distance in any acceptable sense of the word "accuracy".
If you want to try it by yourself, here's a document describing more in detail the approach : http://perso-etis.ensea.fr/~pierandr/cours/M1_SIC/AN3397.pdf
I have been testing the accuracy of various aspects of CoreLocation and have been surprised to find the accuracy value supplied on new and old locations passed to the CLLocationMangerDelegate method: (void)locationManager:didUpdateToLocation:fromLocation is wildly inaccurate itself.
Walking certain stretches of pavement(along a stretch of road with buildings along one side) I have found that whilst CLLocationManager claims the CLLocations it is supplying have a horizontal accuracy of 5 meters, in actual fact the position shown by the MKUserAnnotation is anything up to 30 meters away from the position I know I'm in (often showing as being the opposite side of a row of buildings). This suggests that the accuracy reading itself is not accurate. CLLocationManager is telling me its coordinates are accurate to within 5 meters but are actually as many as 30 meters out.
To clarify, this is not a caching/timestamp issue It is repeatable in certain areas, and not something that improves over time.
Has anyone else encountered this issue?
CoreLocation is not a human and does not know where you "really" are, is the essence of the answer to your question. It is using the sensors on your device and giving you the best answer it's got, and the problems with its ability to know the accuracy of its claimed answer, reflect that the problem of location is inherently very difficult.
To digress into the location data itself: CoreLocation draws from cell tower triangulation, nearby SSIDs, and finally GPS, to determine the device's location. These do have varying degrees of accuracy, but what they have in common is that if you let the device work for longer, you'll get a more accurate answer. However, because all of the tools that CoreLocation uses are expensive in terms of battery life, it will stop as soon as it has generated an answer that meets your criteria for "good enough."
This is why another answer told you to set your desiredAccuracy to kCLLocationAccuracyBestForNavigation - when you do that, you're basically telling CoreLocation "show me the best you've got," and you've also volunteered for the CPU load, time, and battery drain that come with that. You've also gone off the normal scale that CoreLocation uses to figure out what's "good enough" - instead of telling it ahead of time when it can stop, you've basically said "I'll tell you when it's good enough."
CoreLocation will thus keep on trying to give you better answers until you tell it you're done, and you need to carry out your responsibility for deciding what that point is. This is also where you need to bear in mind that there are limits to how accurate the tools in CoreLocation's repertoire can be - you can get lots of significant digits of latitude and longitude, but by venturing off the scale, you've volunteered for the task of figuring out how trustworthy those numbers are. The pre-defined scales of accuracy are 10 meters, 100 meters, 1 km, and 3km. The fact that the creators of CoreLocation chose those cut-off points should tell you something about the difficulty of the problem - if better accuracy were easy, it would probably already be in the framework.
So circling back around: CoreLocation is reporting the accuracy of its answers faithfully, it's just that the data underlying those answer is problematic, and if it knew more about the accuracy of its accuracy claims, it would reflect that in its accuracy claims. Consider the hypothetical situation where CoreLocation knows exactly how accurate its accuracy claims are, then the situation where CoreLocation knows nothing about how accurate its accuracy claims are, and consider how you'd design an API to account for the problem. CoreLocation is as sure as it can reasonably be about how sure it is, and if you can figure out a tractable-within-the-limits-of-the-hardware way to be more sure about how sure you are, App Store wealth awaits you.
the hardware takes some time to get the accuracy. the best accuracy is 65m in 2-3 seconds. else u have 1414m accuracy
I want to know about Core Location data which is generated by apple.My question is that up to which % is it correct.Whatever I have seen it is not GPS data.Most of time it is collected data from Wifi or cell tower.So data is not 100 % accurate.
If it is anything else then give me some idea as i make it 100 % accurate.
The framework will prefer the fastest, least battery-draining method to get you a location. But if you have a specific accuracy that you need, you just have to tell your CLLocationManager. Look for the desiredAccuracy property and set that.
Also, when you get locations back you should check the CLLocation's accuracy properties to see if that particular observation was accurate enough to do whatever it is you want to do.
Keep in mind that sometimes your users may in a place with good tower or WiFi but poor GPS visibility. So then you'll have to decide if the accuracy you get back is good enough or if you need to tell the user that the function is not possible.
Hope that helps.
It's not possible for it to be 100% accurate - the return from the API says so, even going so far as giving you the margin for error in every dataset you receive
I am developing an augmented reality application that (at the moment) wants to display a simple cube on top of a surface, and be able to move in space (both rotating and displacing) to look at the cube in all the different angles. The problem of calibrating the camera doesn't apply here since I ask the user to place the iPhone on the surface he wants to place the cube on and then press a button to reset the attitude.
To find out the camera rotation is very simple with the Gyroscope and Core Motion. I do it this way:
if (referenceAttitude != nil) {
[attitude multiplyByInverseOfAttitude:referenceAttitude];
}
CMRotationMatrix mat = attitude.rotationMatrix;
GLfloat rotMat[] = {
mat.m11, mat.m21, mat.m31, 0,
mat.m12, mat.m22, mat.m32, 0,
mat.m13, mat.m23, mat.m33, 0,
0, 0, 0, 1
};
glMultMatrixf(rotMat);
This works really well.
More problems arise anyway when I try to find the displacement in space during an acceleration.
The Apple Teapot example with Core Motion just adds the x, y and z values of the acceleration vector to the position vector. This (apart from having not much sense) has the result of returning the object to the original position after an acceleration. (Since the acceleration goes from positive to negative or vice versa).
They did it like this:
translation.x += userAcceleration.x;
translation.y += userAcceleration.y;
translation.z += userAcceleration.z;
What should I do to find out displacement from the acceleration in some istant? (with known time difference). Looking some other answers, it seems like I have to integrate twice to get velocity from acceleration and then position from velocity. But there is no example in code whatsoever, and I don't think that is really necessary. Also, there is the problem that when the iPhone is still on a plane, accelerometer values are not null (there is some noise I think). How much should I filter those values? Am I supposed to filter them at all?
Cool, there are people out there struggling with the same problem so it is worth to spent some time :-)
I agree with westsider's statement as I spent a few weeks of experimenting with different approaches and ended up with poor results. I am sure that there won't be an acceptable solution for either larger distances or slow motions lasting for more than 1 or 2 seconds. If you can live with some restrictions like small distances (< 10 cm) and a given minimum velocity for your motions, then I believe there might be the chance to find a solution - no guarantee at all. If so, it will take you a pretty hard time of research and a lot of frustration, but if you get it, it will be very very cool :-) Maybe you find these hints useful:
First of all to make things easy just look at one axis e.g x but consider both left (-x) and right (+x) to have a representable situation.
Yes you are right, you have to integrate twice to get the position as function of time. And for further processing you should store the first integration's result (== velocity), because you will need it in a later stage for optimisation. Do it very careful because every tiny bug will lead to huge errors after short period of time.
Always bear in mind that even a very small error (e.g. <0.1%) will grow rapidly after doing integration twice. Situation will become even worse after one second if you configure accelerometer with let's say 50 Hz, i.e. 50 ticks are processed and the tiny neglectable error will outrun the "true" value. I would strongly recommend to not rely on trapezoidal rule but to use at least Simpson or a higher degree Newton-Cotes formula.
If you managed this, you will have to keep an eye on setting up the right low pass filtering. I cannot give a general value but as a rule of thumb experimenting with filtering factors between 0.2 and 0.8 will be a good starting point. The right value depends on the business case you need, for instance what kind of game, how fast to react on events, ...
Now you will have a solution which is working pretty good under certain circumstances and within a short period of time. But than after a few seconds you will run into trouble because your object is drifting away. Now you will enter the difficult part of the solution which I failed to handle eventually within the given time scope :-(
One promising approach is to introduce something I call "synthectic forces" or "virtual forces". This is some strategy to react on several bad situations triggering the object to drift away although the device remains fixed (? no native speaker, I mean without moving) in your hands. The most troubling one is a velocity greater than 0 without any acceleration. This is an unavoidable result of error propagation and can be handled by slowing down artificially that means introducing a virtual deceleration even if there is no real counterpart. A very simplified example:
if (vX > 0 && lastAccelerationXTimeStamp > 0.3sec) {
vX *= 0.9;
}
`
You will need a combination of such conditions to tame the beast. A lot of try and error is required to get a feeling for the right way to go and this will be the hard part of the problem.
If you ever managed to crack the code, pleeeease let me know, I am very curious to see if it is possible in general or not :-)
Cheers Kay
When the iPhone 4 was very new, I spent many, many hours trying to get an accurate displacement using accelerometers and gyroscope. There shouldn't have been much concern about incremental drift as device needed only move a couple of meters at most and the data collection typically ran for a few minutes at most. We tried all sorts of approaches and even had help from several Apple engineers. Ultimately, it seemed that the gyroscope wasn't up to the task. It was good for 3D orientation but that was it ... again, according to very knowledgable engineers.
I would love to hear someone contradict this - because the app never really turned out as we had hoped, etc.
I am also trying to get displacement on the iPhone. Instead of using integration I used the basic physics formula of d = .5a * t^2 assuming an initial velocity of 0 (doesn't sound like you can assume initial velocity of 0). So far it seems to work quite well.
My problem is that I'm using the deviceMotion.and the values are not correct. deviceMotion.gravity read near 0. Any ideas? - OK Fixed, apparently deviceMotion.gravity has a x, y, and z values. If you don't specify which you want you get back x (which should be near 0).
Find this question two years later, I just find a AR project on iOS 6 docset named pARk, It provide a proximate displacement capture and calculation using Gyroscope, aka CoreMotion.Framework.
I'm just starting leaning the code.
to be continued...
I have some animations happening upon fine acceleration detections. But when the user sits in a car or is walking it may get annoying.
Basically, all that stuff has to be disabled automatically as soon as there is too much vibration or shaking. Conceptually, I think that it's very hard to filter those vibrations out , since the "vibration phase" changes permanently. I woul define "unwanted vibration or shocks" as acceleration values that change very fast by an large interval of values, or, an permanently changing accumulated value that does not exceed an specified treshold range in an specified minimum period of time.
I am looking for "proven" concepts, before I start reinventing the wheel for a couple of days.
I don't have any concrete answers for you, but you might want to Google band-pass filters or anti-aliasing filters for some ideas on how to approach this. Basically, if you can identify the frequency range of accelerations that you want to consider real, you can filter out frequencies that fall outside this range.
Before you start doing too much pre-optimization, I think you should implement a low pass filter and see if that does the job. Most iPhone apps effectively use a variation of an LPF to get rid of unwanted accelerometer noise.
You could also go the other way and use a high pass filter. Once you get a certain power level passing through the HPF, stop processing data.