3

I have been working to implement route trace map for walking,biking and driving.

However, as you see in the following screenshot, my coordinate jumps all of a sudden from time to time even though I did not walk/bike or drive that location. The circle has been drawn on the image to point out the problem. My question is why all of a sudden coordinates jumps ?

enter image description here

Here is my implementation snapshot:

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation
{
    CoordinateModel *coord = [[CoordinateModel alloc] init];
    coord.latitude = newLocation.coordinate.latitude;
    coord.longitude = newLocation.coordinate.longitude;

    ActivityType currentActivityType = [DataManager sharedInstance].activityType;

        if (currentActivityType == 0) {
            // walking
            [appDelegate.walkingCoordinates addObject:coord];
        }
        else if(currentActivityType == 1) {
            [appDelegate.bikingCoordinates addObject:coord];
        }
        else if(currentActivityType == 2) {
            // driving
            [appDelegate.drivingCoordinates addObject:coord];
        }

     self.coordinate = newLocation.coordinate;
}
Ricky
  • 10,485
  • 6
  • 36
  • 49

2 Answers2

5

I suggest you not to use the delegate method locationManager:didUpdateToLocation:fromLocation: anymore and it has been deprecated.

You should use locationManager:didUpdateLocations instead.

About your question, the location "jumping" like you mention is due to the GPS that is unable to determine the accuracy of your location during a certain time. If you record down the coordinate and also the accuracy for all the time including when you are indoor, you will realize that the accuracy when you are staying indoor is not good, you might see the accuracy 1414 when you are connected to Wifi. GPS does not work well when you are indoor. So, your code has to be smart enough to only draw a path or send the coordinate to the server when only the coordinate is good enough.

The below code are some of the criteria that I use to filter out the bad coordinates.

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{

for(int i=0;i<locations.count;i++){
  CLLocation * newLocation = [locations objectAtIndex:i];
  CLLocationCoordinate2D theLocation = newLocation.coordinate;
  CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
  NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];

  if (locationAge > 30.0)
      continue;

  //Select only valid location and also location with good accuracy
  if(newLocation!=nil&&theAccuracy>0
     &&theAccuracy<2000
     &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){
      self.myLastLocation = theLocation;
      self.myLastLocationAccuracy= theAccuracy;
      NSMutableDictionary * dict = [[NSMutableDictionary alloc]init];
      [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"];
      [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"];
      [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"];
      //Add the valid location with good accuracy into an array
      //Every 1 minute, I will select the best location based on accuracy and send to server
      [self.shareModel.myLocationArray addObject:dict];
    }
   }
 }

After a certain period (eg: 3 minutes), I will again choose the best coordinate from self.shareModel.myLocationArray before drawing the coordinate on map and send the coordinate to the server.

You may see the full solution and sample project from here: Background Location Services not working in iOS 7

Don't forget to upvote if my answer is good enough. ;)

Community
  • 1
  • 1
Ricky
  • 10,485
  • 6
  • 36
  • 49
  • Hello Ricky, thanks a lot for detail explanation, I have just implemented my code the way that you have described. Please see my code below. Do you think it is the way that you suggested? By the way, it is only called once. and location array contains only one object. –  May 23 '14 at 04:09
  • No problem. I don't know the purpose/behavior/expectation/requirement of your app and other details, so, it is really hard to suggest anything. It is called once because you are not moving. When you are moving, you will get more coordinates. May be you want to put all the coordinates into an array (eg: every 5 minutes), then only choose the best coordinate. Remember to clear the array afterwards. – Ricky May 23 '14 at 04:17
  • Hello Ricky, Thanks a lot again.I have marked your answer as a correct solution. Could you please quickly review my posted code below. Is this correct ? –  May 23 '14 at 04:19
  • 1
    I think it looks good. But, I still think you should put the coordinates into an array and then use another method to draw the map after a certain period. That would be more accurate. – Ricky May 23 '14 at 04:22
  • Yes, that is exactly what I am doing in my code. In my code, I have just collecting array of objects to be drawn. –  May 23 '14 at 04:28
  • Ricky, please see my screenshot below. This problem still exist. –  May 23 '14 at 15:56
  • 1
    After you got the coordinates into an array eg. **appDelegate.walkingCoordinates** you need to filter again. May be you only choose the accuracy less than 50 to put onto the map. – Ricky May 24 '14 at 02:10
1

Same Problem has been still in the code.

enter image description here

  -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{


    iNEAT_o_GamesAppDelegate *appDelegate = (iNEAT_o_GamesAppDelegate *)[[UIApplication sharedApplication] delegate];

    CoordinateModel *coord = [[CoordinateModel alloc] init];

    ActivityType currentActivityType = [DataManager sharedInstance].activityType;

    for(int i=0;i<locations.count;i++){
        CLLocation * newLocation = [locations objectAtIndex:i];
        CLLocationCoordinate2D theLocation = newLocation.coordinate;
        CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
        NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];

        if (locationAge > 30.0)
            continue;

        //Select only valid location and also location with good accuracy
        if(newLocation!=nil&&theAccuracy>0
           &&theAccuracy<2000
           &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){
            coord.latitude = theLocation.latitude;
            coord.longitude = theLocation.longitude;

                   if (currentActivityType == 0) {
                        // walking
                        [appDelegate.walkingCoordinates addObject:coord];
                    }
                    else if(currentActivityType == 1) {
                        [appDelegate.bikingCoordinates addObject:coord];
                    }
                    else if(currentActivityType == 2) {
                        // driving
                        [appDelegate.drivingCoordinates addObject:coord];
                    }
        }
    }
}