CLLocation方法遇到问题distanceFromLocation:结果不准确

时间:2012-04-17 03:50:42

标签: iphone objective-c core-location cllocation

我正在尝试使用distanceFromLocation:方法来计算我手里拿着iPhone走的总距离。到目前为止,我一直在寻找帮助解决我混乱,不准确和看似随意的结果。在这些代码片段中,theLabel只是我的应用程序界面中的标签对象,distanceMoved是我试图存储我走进的总距离的变量,locMan是在我的@interface文件中声明的位置管理器。

- (void)viewDidLoad
{
   locMan = [[CLLocationManager alloc] init];
   locMan.delegate = self;
   [locMan startUpdatingLocation];
   isInitial = true;
   distanceMoved = 0.0;
   [super viewDidLoad];
}

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
   distanceMoved += [newLocation distanceFromLocation: oldLocation];
   theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}

任何有助于解决我在这里做错事的帮助将不胜感激。谢谢!

4 个答案:

答案 0 :(得分:14)

  1. 过滤掉缓存(旧)位置数据
  2. 过滤掉无效的位置结果(准确度< 0),
  3. 将准确度要求设置为kCLLocationAccuracyBest
  4. 设置最小距离滤波器,最好至少10米,以滤除位置噪声。
  5. 编辑oldLocation为零时,请勿计算距离。
  6. 你可以做的更多但是如果你获得了足够好的水平准确度(<30m),这应该可行。你可以过滤出低精度的结果,但是你必须自己跟踪oldLocation,这有点复杂。

    添加NSLog(见下文),以便了解正在发生的事情。如果你仍然没有在NSLog的输出后得到好的结果,那么我们可以看到正在发生的事情并提供更多帮助。

    -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 
    
        if (age > 120) return;    // ignore old (cached) updates
    
        if (newLocation.horizontalAccuracy < 0) return;   // ignore invalid udpates
    
        // EDIT: need a valid oldLocation to be able to compute distance
        if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return; 
    
        CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation];
    
        NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
            oldLocation.coordinate.latitude,
            oldLocation.coordinate.longitude,
            newLocation.coordinate.latitude,
            newLocation.coordinate.longitude, 
            distance,
            newLocation.horizontalAccuracy);
    
        distanceMoved += distance;
        theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
    }
    
    - (void)viewDidLoad
    {
       locMan = [[CLLocationManager alloc] init];
       locMan.delegate = self;
       locMan.desiredAccuracy = kCLLocationAccuracyBest;
       locMan.distanceFilter = 10;
    
       [locMan startUpdatingLocation];
       isInitial = true;
       distanceMoved = 0.0;
       [super viewDidLoad];
    }
    

    针对iOS6的编辑如果您想使用didUpdateLocations:执行相同操作(因为上述方法现已弃用),最简单的解决方案是将每个位置保存在属性中,以便在下一次更新您有以前的位置。在类中声明一个属性来保存oldLocation

    @property (nonatomic, retain) CLLocation* oldLocation;
    

    然后在委托方法中保存每个newLocation,以便在下次调用委托方法时用作oldLocation

    -(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations
    {
        CLLocation* newLocation = [locations lastObject];
    
        NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 
    
        if (age > 120) return;    // ignore old (cached) updates
    
        if (newLocation.horizontalAccuracy < 0) return;   // ignore invalid udpates
    
        // EDIT: need a valid oldLocation to be able to compute distance
        if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) {
            self.oldLocation = newLocation;
            return; 
        }
    
        CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation];
    
        NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
            self.oldLocation.coordinate.latitude,
            self.oldLocation.coordinate.longitude,
            newLocation.coordinate.latitude,
            newLocation.coordinate.longitude, 
            distance,
            newLocation.horizontalAccuracy);
    
        distanceMoved += distance;
        theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
    
        self.oldLocation = newLocation;    // save newLocation for next time
    }
    

答案 1 :(得分:0)

您没有设置位置管理员的准确性。通过苹果文档,它就像准确性= bestfornavigation。或者其他的东西。这应该像地狱一样耗尽电池,但是出于这种目的。

编辑:记得我手边有它。

// Create the Location Manager
locationManager = [[CLLocationManager alloc] init];

// Configure the Location Manager
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;

答案 2 :(得分:0)

CLLocationDistance distance = [secondLocation distanceFromLocation:firstLocation];  // distance is expressed in meters

CLLocationDistance kilometers = distance / 1000.0;
// or you can also use this..
CLLocationDistance meters = distance;

NSString *distanceString = [[NSString alloc] initWithFormat: @"%f", kilometers];

flot totaldistancecovered = [distanceString floatValue];

//Now,you can use this float value for addition...
// distanceMoved  should be float type variable which is declare in .h file...

 distanceMoved = distanceMoved + totaldistancecovered ;
 theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];

希望这会对你有帮助..

答案 3 :(得分:0)

您应该做的第一件事是通过检查从位置管理器收到的第一个更新的时间戳来解除第一个更新,它通常会缓存最后一个已知位置。第二,记住准确性,你得到的初始值总是在很大范围内。