【问题标题】:Having trouble calculating accurate total walking/running distance using CLLocationManager使用 CLLocationManager 计算准确的总步行/跑步距离时遇到问题
【发布时间】:2012-02-05 10:28:05
【问题描述】:

我正在尝试构建一个 iOS 应用程序,以显示跑步或步行时的总行驶距离。我已经阅读并重新阅读了所有我能找到的文档,但我无法想出一些能提供准确总距离的东西。

与 Nike+ GPS 或 RunKeeper 相比,我的应用始终报告更短的距离。他们一开始会报告相同的情况,但随着我不断前进,我的应用程序与其他正在运行的应用程序的价值会逐渐漂移。

例如,如果我步行 0.3 公里(通过我的汽车里程表验证),Nike+ GPS 和 RunKeeper 每次都会报告 ~.3 公里,但我的应用程序会报告 ~.13 公里。 newLocation.horizo​​ntalAccuracy 始终为 5.0 或 10.0。

这是我正在使用的代码。我错过了一些明显的东西吗?关于如何改进这一点以获得更准确的读数的任何想法?

#define kDistanceCalculationInterval 10 // the interval (seconds) at which we calculate the user's distance
#define kNumLocationHistoriesToKeep 5 // the number of locations to store in history so that we can look back at them and determine which is most accurate
#define kValidLocationHistoryDeltaInterval 3 // the maximum valid age in seconds of a location stored in the location history
#define kMinLocationsNeededToUpdateDistance 3 // the number of locations needed in history before we will even update the current distance
#define kRequiredHorizontalAccuracy 40.0f // the required accuracy in meters for a location.  anything above this number will be discarded

- (id)init {
    if ((self = [super init])) {
        if ([CLLocationManager locationServicesEnabled]) {
            self.locationManager = [[CLLocationManager alloc] init];
            self.locationManager.delegate = self;
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
            self.locationManager.distanceFilter = 5; // specified in meters
        }

        self.locationHistory = [NSMutableArray arrayWithCapacity:kNumLocationHistoriesToKeep];
    }

    return self;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // since the oldLocation might be from some previous use of core location, we need to make sure we're getting data from this run
    if (oldLocation == nil) return;
    BOOL isStaleLocation = [oldLocation.timestamp compare:self.startTimestamp] == NSOrderedAscending;

    [self.delegate locationManagerDebugText:[NSString stringWithFormat:@"accuracy: %.2f", newLocation.horizontalAccuracy]];

    if (!isStaleLocation && newLocation.horizontalAccuracy >= 0.0f && newLocation.horizontalAccuracy < kRequiredHorizontalAccuracy) {

        [self.locationHistory addObject:newLocation];
        if ([self.locationHistory count] > kNumLocationHistoriesToKeep) {
            [self.locationHistory removeObjectAtIndex:0];
        }

        BOOL canUpdateDistance = NO;
        if ([self.locationHistory count] >= kMinLocationsNeededToUpdateDistance) {
            canUpdateDistance = YES;
        }

        if ([NSDate timeIntervalSinceReferenceDate] - self.lastDistanceCalculation > kDistanceCalculationInterval) {
            self.lastDistanceCalculation = [NSDate timeIntervalSinceReferenceDate];

            CLLocation *lastLocation = (self.lastRecordedLocation != nil) ? self.lastRecordedLocation : oldLocation;

            CLLocation *bestLocation = nil;
            CGFloat bestAccuracy = kRequiredHorizontalAccuracy;
            for (CLLocation *location in self.locationHistory) {
                if ([NSDate timeIntervalSinceReferenceDate] - [location.timestamp timeIntervalSinceReferenceDate] <= kValidLocationHistoryDeltaInterval) {
                    if (location.horizontalAccuracy < bestAccuracy && location != lastLocation) {
                        bestAccuracy = location.horizontalAccuracy;
                        bestLocation = location;
                    }
                }
            }
            if (bestLocation == nil) bestLocation = newLocation;

            CLLocationDistance distance = [bestLocation distanceFromLocation:lastLocation];
            if (canUpdateDistance) self.totalDistance += distance;
            self.lastRecordedLocation = bestLocation;
        }
    }
}

【问题讨论】:

    标签: objective-c ios core-location cllocationmanager cllocation


    【解决方案1】:

    事实证明,我在上面发布的代码效果很好。问题恰好出在我的应用程序的不同部分。我不小心将距离从米转换为英里,而不是从米转换为公里。糟糕!

    无论如何,希望我的帖子仍然有一些优点,因为我觉得这是一个非常可靠的示例,说明如何使用核心位置跟踪用户的距离。

    【讨论】:

    • 不要忘记接受这个作为你的答案,以防止它显示为一个开放的问题。顺便说一句,很好的例子。
    • 您好 Daniel,我在一个多星期以来一直在获取相同的问题,但仍然没有得到任何解决方案。那么,你能帮帮我吗?
    • @Daniel 我会检查这个 PSLocationManager。我在路上跑步后没有人改变仪表标签。这个项目有什么问题。
    【解决方案2】:

    您可能将 kRequiredHorizo​​ntalAccuracy 设置得太低。如果历史记录中没有准确度

    【讨论】:

    • 不幸的是,我认为这不会成功。第一个原因是我正在记录水平精度,它始终保持在 10.0 或 5.0。此外,即使点 > kRequiredHorizo​​ntalAccuracy 被忽略,一旦我得到一个有效位置,我就会将它与最后一个有效位置进行比较以获得距离,所以我不会丢弃距离数据。
    • @Daniel ... 最后一个有效位置 (lastRecordedLocation) 是 newLocation,以防列表中没有很好的准确性。这意味着您在不增加距离的情况下重新设置 lastRecordedLocation。顺便说一句,10 和 5 相当低。我在测试中经常获得 100-150 的准确度。
    • 感谢您的浏览。仅当尚未记录有效位置时,lastRecordedLocation 才应为 nil,因为我在底部设置了 self.lastRecordedLocation = bestLocation。也感谢关于 100-150 精度的建议。我会做更多测试...可能需要将我的 kRequiredHorizo​​ntalAccuracy 从 40 提高。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多