I have an application in which user track his/her route when jogging or cycling, So i need perfect location, so user's routes will be perfect.
But, I have one problem in this,
locManager = [[CLLocationManager alloc] init];
[locManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[locManager setDelegate:self];
[locManager startUpdatingLocation];
In viewDidLoad. Using this didUpdateToLocation method called multiple times when I just dont move device a little and on map very strange route draw.
I just cant understand why this happen, if I am doing some wrong or missing something.
Thanks.......
I use locationManager.distanceFilter = 500; (or so) // meters
to prevent multiple calls from happening. just remember to call this BEFORE you start updating your location
You can set the distancefilter of the location manager hope this may help you
locationManager=[[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter=10.0;
[locationManager startUpdatingLocation];
When you first start location services, you'll generally see multiple location updates come whether you're moving or not. If you examine the horizontalAccuracy of the locations as they come in, you'll see that while it's "warming" up it will show a series of locations with greater and greater accuracy (i.e. smaller and smaller horizontalAccuracy values) until it reaches quiescence.
You could disregard those initial locations until horizontalAccuracy falls below a certain value. Or, better, during start up, you could disregard the previous location if (a) the distance between a new location and the old location is less than the horizontalAccuracy of the old location and (b) if the horizontalAccuracy of the new location is less than that of the prior location.
For example, let's assume you're maintaining an array of CLLocation objects, as well as a reference to the last drawn path:
#property (nonatomic, strong) NSMutableArray *locations;
#property (nonatomic, weak) id<MKOverlay> pathOverlay;
Furthermore, let's assume your location update routine is just adding to the array of locations and then indicating that the path should be redrawn:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%s", __FUNCTION__);
CLLocation* location = [locations lastObject];
[self.locations addObject:location];
[self addPathToMapView:self.mapView];
}
Then the addPathToMapView can therefore remove the second from last location if it's less accurate than the last one and if the distance between them is less than the most recent location's accuracy.
- (void)addPathToMapView:(MKMapView *)mapView
{
NSInteger count = [self.locations count];
// let's see if we should remove the penultimate location
if (count > 2)
{
CLLocation *lastLocation = [self.locations lastObject];
CLLocation *previousLocation = self.locations[count - 2];
// if the very last location is more accurate than the previous one
// and if distance between the two of them is less than the accuracy,
// then remove that `previousLocation` (and update our count, appropriately)
if (lastLocation.horizontalAccuracy < previousLocation.horizontalAccuracy &&
[lastLocation distanceFromLocation:previousLocation] < lastLocation.horizontalAccuracy)
{
[self.locations removeObjectAtIndex:(count - 2)];
count--;
}
}
// now let's build our array of coordinates for our MKPolyline
CLLocationCoordinate2D coordinates[count];
NSInteger numberOfCoordinates = 0;
for (CLLocation *location in self.locations)
{
coordinates[numberOfCoordinates++] = location.coordinate;
}
// if there is a path to add to our map, do so
MKPolyline *polyLine = nil;
if (numberOfCoordinates > 1)
{
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
[mapView addOverlay:polyLine];
}
// if there was a previous path drawn, remove it
if (self.pathOverlay)
[mapView removeOverlay:self.pathOverlay];
// save the current path
self.pathOverlay = polyLine;
}
Bottom line, just get rid of locations that are less accurate than the next one you have. You could get even more aggressive in the pruning process if you want, but there are tradeoffs there, but hopefully this illustrates the idea.
startUpdatingLocation
Will continuously update a user's location even when the location does not change. You just need to structure your app to handle these continuous updates according to your needs.
Try reading Apple's documentation on this subject. It is confusing at first but try anyway.
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW1
I think this is what you need.startMonitoringForRegion:desiredAccuracy
for Example see the following github link.
Try this Bread Crumb sample code provided by Apple..
http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html
Add this,
[locManager stopUpdatingLocation];
into your updateUserLocation delegate method.
Review the following code snippet:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[_locationManager stopUpdatingLocation];
}
locationManager.startUpdatingLocation() fetch location continuously and didUpdateLocations method calls several times,
Just set the value for locationManager.distanceFilter value before calling locationManager.startUpdatingLocation().
As I set 200 working fine
locationManager.distanceFilter = 200
locationManager.startUpdatingLocation()
Related
I'm trying a lot of things to stop the location update of my app but nothing seems work…
What I do (regard of the post : StopUpdatingLocation method not working for iOS5) :
// Initialise my locationManager and start monitoring :
locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
// .. Some code to use the coordinates that locationManager gives me.
// To stop monitoring :
locationManager = nil;
You have to know I placed [locationManager stopUpdatingLocation]; in the method :
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
So the location is updated only 1 time (btw tell me if it's a good idea…).
I also tried to place [locationManager stopUpdatingLocation]; just before locationManager = nil; in the main code, but the blue dot that gives me my location is still moving on my map in both cases…
I also set a timer which print the locationManager object in the console, and it gives me (null) meanwhile the blue dot is still moving on my iPhone 5 so I don't understand that…
Or maybe the dot is still moving because of another thing, but not because of locationManager update ?
I'm certainly missing something but I don't get what :/.
Thanks for ideas and help.
One possibility: The blue dot moving on your map is because you set the MKMapView's showsUserLocation to YES. It will track until you set it to NO.
Another possibility: This line is wrong:
locationManager = nil;
That does not stop monitoring, but it does cause you to be unable to refer to the location manager, so now you can't stop monitoring! Cut that line.
I faced the same problem that even after I placed the code
[locationManager stopUpdatingLocation];
locationManager=nil;
my application was using GPS service which was un-necessarily consuming battery power. the solution for this problem is to turn off the showUserLocation property of MKMapView .
[self.mapView setShowsUserLocation:NO];
Since the MKMapView keeps on using your GPS service even if the LocationManager is nil.
Hope it will help you
Use this lines of code
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
self.locationManager = nil;
Thanks!
Some one help me out please I am stuck on it from last few days...
My task is here.
In my app i need to integrate the map, as it open it should shows the current user position, as i pressed start button while walking it starts tracing path from the position where i pressed start button till the position i pressed stop.the distance covered in this interval should be traced turn by turn navigation and also wann to collect start and stop position coordinates to calculate distance.
i have added map kit framework, core location frame work, also added map view,and also implemented method to show current user position . now
here is my code
-(void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == self.locatioManager)
{
self.locatioManager = [[CLLocationManager alloc] init];
self.locatioManager.delegate = self;
[self.locatioManager startMonitoringSignificantLocationChanges];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// If it's a relatively recent event, turn off updates to save power
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(#"latitude %+.6f, longitude %+.6f\n",location.coordinate.latitude,location.coordinate.longitude);
}
MKCoordinateRegion ref=MKCoordinateRegionMakeWithDistance([location coordinate], 250,250);
[self.myMapView setRegion:ref animated:YES];
}
Please guide me from here to trace path, and can collect coordinates also .
I have a MKMapView whereby I drop an annotation everytime the view loads, or when showLocation custom class method is called.
I need the accuracy to be the best
-(void)viewDidLoad {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[locationManager startUpdatingLocation];
}
-(IBAction) showLocation:(id) sender{
[locationManager startUpdatingLocation];
}
- (void) locationManager:(CLLocationManager *) manager
didUpdateToLocation:(CLLocation *) newLocation
fromLocation:(CLLocation *) oldLocation {
// start geocoding with newLocation coordinate which will automatically set annotation.
SVGeocoder *geocodeRequest = [[SVGeocoder alloc]
initWithCoordinate:CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude)];
[geocodeRequest setDelegate:self];
[geocodeRequest startAsynchronous];
[geocodeRequest release];
[locationManager stopUpdatingLocation];
}
My question is when will the didUpdateToLocation method be called? Only after a new location is found when I perform [locationManager startUpdatingLocation]?
I am facing some weird issue when the user is travelling and on stationary.
Say the user is travelling from point A->B->C->D with 1 min intervals between points. When I call my method at point C, sometime it returns the coordinates of point A, sometimes point B and sometimes C. It's just random.
It's even more weird when I am on stationary. I get different coordinates when I calls showLocation method even though I am hooked up on my house WiFi.
I was thinking of implementing the didUpdateToLocation to get the best result it can within 5secs. If within the 5secs, it finds a particular location of an accuracy I had defined, then use the coordinate. If not, use the best it has found within the 5sec time frame. But as I am new I am not sure how to code something like that. I read up NSTimer and it seems like it might work.
Any advices guys?
Thanks a lot in advance!
One of the reasons you are receiving the location from point A is that CoreLocation is returning the last valid location it had first until it can obtain a more accurate location. When you call [locationManager startUpdatingLocation]; it will return the -didUpdateToLocation over and over until you are statisfied and finally call -stopUpdatingLocation.
I think you just need to allow a bit of time for it to get a better location fix before you stop updating your location. I would consider moving the stop updating location from your -didUpdateToLocation to a different method.
Remove [locationManager stopUpdatingLocation]; from your code and try .
I'm beginning to mess around with the CLLocationManager and I am trying to use the callback method below. I went outside to test it on my iPhone, and with the first few updates, I seem to be getting gibberish values, like all of a sudden my distance is 39meters even though I haven't moved anywhere. Or sometimes it will start at 5, and then jump to 20 meters, again without me moving anywhere. I went outside and walked, and the updates from the initial starting point seemed 'ok,' and then when I walked back, I got back to the original 39 meters starting point. I was wondering if what I am doing below is correct. I also included my viewDidLoad method where I initialize my CLLocationManager object.
Is there a way to ensure that my first values are accurate? Thanks in advance.
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if (startingPoint == nil) {
NSLog(#"NIL starting point");
self.startingPoint = newLocation;
}
CLLocationDistance distance = [newLocation distanceFromLocation:startingPoint];
NSString *distanceString = [[NSString alloc] initWithFormat:#"%g m", distance];
distanceLabel.text = distanceString;
[distanceString release];
numberOfUpdates++;
NSString *countString = [[NSString alloc] initWithFormat:#"%d", numberOfUpdates];
countLabel.text = countString;
[countString release];
}
GPS is an imperfect technology. Atmospheric conditions, sattelite availability (and position), sky visibility, signals bouncing off nearby objects (buildings) all contribute to it's inherent inaccuracy. Though there is even an "accuracy" value (which is usually pretty good) - even this is not completely reliable.
Airplanes are not allowed to use GPS for precision approaches - even their receivers aren't accurate enough, and they require other technologies (which have their own issues).
Try running the standard "Maps" application and use it as a comparison. I think your code is good - it's jut GPS.
Of course I am saying this because I am working on my own maritime navigation application, an running into all these issues myself.
Though this is an old question I still like to answer. The first call to "didUpdateToLocation" usually is some old value and you should always check the timestamp. From the Apple documentation:
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0)
{
// use the value
}
In your didUpdate method, you can test newLocation's .horizontalAccuracy property for an acceptable value and toss any values that are impossible (or even unlikely!).
I am developing an application that computes the distance travelled by the person. I am testing it on a iPad (Device-3.2). My iPad is using WiFi to get the current location. The results are highly inaccurate even though i have filtered the values. I don't know if GPS will give me accurate results. I am pasting the entire code below. Please verify the code and in case of errors please let me know. It would b very helpful if some one test the code on iPhone(3g) or iPad(3g). If not possible then just check the logic.....also i want to compute the calories burnt ..is there any formula to do so..? I have made simple view based project.....and used a distance label in nib file to set distance value but distance is updating at a very rapid rate....please correct it.
// iPacometerViewController.h
#interface iPacometerViewController : UIViewController {
CLLocationManager *locationManager;
CLLocation *oldLocat;
CLLocation *newLocat;
IBOutlet UILabel *distanceLabel;
}
#property(nonatomic,assign)IBOutlet UILabel *distanceLabel;
#property(nonatomic,retain)CLLocationManager *locationManager;
#property(nonatomic,retain)CLLocation *oldLocat;
#property(nonatomic,retain)CLLocation *newLocat;
-(void)computeDistanceFrom:(CLLocation *)oldL tO:(CLLocation *)newL;
#end
// iPacometerViewController.m
#import "iPacometerviewController.h"
#implementation iPacometerViewController
static double distance = 0.0;
#synthesize locationManager;
#synthesize oldLocat;
#synthesize newLocat;
#synthesize distanceLabel;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
//initializing location manager
locationManager =[[CLLocationManager alloc]init];
locationManager.delegate = self;
locationManager.distanceFilter = 150.0f;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
oldLocat = [[CLLocation alloc]init];
newLocat = [[CLLocation alloc]init];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (newLocation.horizontalAccuracy 60.0) return; // data is too long ago, don't use it
NSLog(#"oldd %#",oldLocation);
self.oldLocat = oldLocation;
self.newLocat = newLocation;
if(oldLocat!=nil)
{
[self computeDistanceFrom:oldLocat tO:newLocat];
}
}
-(void)computeDistanceFrom:(CLLocation *)oldL tO:(CLLocation *)newL
{
NSLog(#"oldd %#",oldL);
NSLog(#"new %#",newL);
CLLocationDistance currentDistance = [oldL distanceFromLocation:newL];
NSLog(#"you have travel=%f",currentDistance);
distance = distance + currentDistance;
double distanceInKm = distance/1000;
NSString *distanceLabelValue = [NSString stringWithFormat:#"%1.2f Kms",distanceInKm];
distanceLabel.text = distanceLabelValue;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)dealloc {
//[mapView release];
[oldloct release];
[newLocat release];
[locationManager release];
[super dealloc];
}
#end
your logic is fine. Its the iPhone's logic that is bad.
There are two main issues that I see when writing this sort of code.
1) What I call poisoned points. These are cached points that the iPhone reports erroneously. You can check for them by dropping any points where the timestamp is the same as or earlier than the latest point. It may also be worth recording a frequency of visits to a point. The poisoned points tend to be visited time and time again (maybe 5 times) each time as a jump from your real track. If you can spot them, you can rule them out.
2) Accuracy - especially height changes. Look at the horizontal and vertical accuracy figures returned with each point. And look at the height. If they are inaccurate, then the velocity and therefore distance traveled will be too. One cause of bad distances is if one end of your pair has an altitude, and the other does not: the "not" gets classed as zero - so if you are 200m above the sea level at the time you have just travelled 200m without moving!
To improve accuracy, you may be better off writing your own great circle distance algorithm (or even simple Pythagoras given the distances are small) which ignores height, or just doing some better filtering on the points you use.
I'm struggling to find a reliable way of measuring location, distance & speed with the iPhone (3GS). and iPad or Touch is just going to be worse I guess.
If you can drop me a mail at andrew dot hawken at fiftyeggs dot co dot uk I will send you my raw iPhone logging software. It would be great if you can run it for a couple of trips and let me have the results - I'm trying to solve the same problem, but only have GPS datasets to work on.