CLLocation方法distanceFromLocation的问题:结果不准确 [英] Trouble with CLLocation method distanceFromLocation: Inaccurate results

查看:125
本文介绍了CLLocation方法distanceFromLocation的问题:结果不准确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use the distanceFromLocation: method to calculate the total distance that I am walking with my iPhone in my hand. So far, I have been searching all over to help remedy my confusing, inaccurate, and seemingly arbitrary results. In these code snippets, theLabel is just a label object that is present in my app's interface, distanceMoved is the variable that I am trying to store the total distance I walked in, and locMan is a location manager that is declared in my @interface file.

- (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];
}

任何有关修复我在这里做错的帮助都将不胜感激。谢谢!

Any help for fixing what I am doing wrong here would be greatly appreciated. Thank you!

推荐答案


  1. 过滤掉缓存(旧)位置数据,

  2. 过滤掉无效的位置结果(准确度< 0),

  3. 设置精度要求设置为 kCLLocationAccuracyBest

  4. 设置最小距离滤波器,最好至少10米,以滤除位置噪声。

  5. 编辑 oldLocation 为零时,请勿计算距离。

  1. Filter out cached (old) location data,
  2. Filter out invalid location results (accuracy < 0),
  3. Set accuracy requirement set to kCLLocationAccuracyBest,
  4. Set a minimum distance filter, preferably at least 10 meters to filter out position noise.
  5. EDIT: Don't compute distance when the oldLocation is nil.

你可以做的更多,但这应该有效,只要你获得足够好的水平准确度(<30m)。你可以过滤掉低精度的结果但是你必须自己跟踪oldLocation,这有点复杂。

There's more you could do but this should work provided you get a good enough horizonalAccuracy (<30m). You could filter out low accuracy results but then you'd have to keep track of the oldLocation yourself which is a bit more complicated.

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

Add an NSLog (see below) so you can find out what's happening. If you still don't get good results post the output of the NSLog so we can see what's going on and help more.

-(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

EDIT for iOS6 if you wanted to do the same using didUpdateLocations: (since the above method is now deprecated) the simplest solution is to simply save each location in a property so that on the next update you have the previous location. Declare an property in the class to hold the oldLocation:

@property (nonatomic, retain) CLLocation* oldLocation;

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

Then in the delegate method you save each newLocation for use as the oldLocation for the next time the delegate method is called:

-(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
}

这篇关于CLLocation方法distanceFromLocation的问题:结果不准确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆