2012-01-08 28 views
16

Tôi đang cố gắng xây dựng một ứng dụng iOS hiển thị tổng khoảng cách đã đi khi chạy hoặc đi bộ. Tôi đã đọc và đọc lại tất cả các tài liệu tôi có thể tìm thấy, nhưng tôi đang gặp rắc rối với một thứ gì đó mang lại cho tôi tổng khoảng cách chính xác.Gặp sự cố khi tính tổng khoảng cách đi bộ/chạy chính xác bằng cách sử dụng CLLocationManager

Khi được so sánh với Nike + GPS hoặc RunKeeper, ứng dụng của tôi luôn báo cáo khoảng cách ngắn hơn. Họ sẽ báo cáo tương tự lúc đầu, nhưng khi tôi tiếp tục di chuyển, các giá trị của ứng dụng của tôi so với các ứng dụng đang chạy khác dần dần trôi đi.

Ví dụ: nếu tôi đi bộ .3 ki lô mét (được xác minh bằng đồng hồ đo của ô tô của tôi), Nike + GPS và RunKeeper đều báo cáo ~ .3 ki lô mét mỗi lần, nhưng ứng dụng của tôi sẽ báo cáo ~ .13 ki lô mét. newLocation.horizontalAccuracy luôn là 5.0 hoặc 10.0.

Đây là mã tôi đang sử dụng. Tôi có thiếu một cái gì đó hiển nhiên? Bất kỳ suy nghĩ về cách tôi có thể cải thiện điều này để có được một đọc chính xác hơn?

#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; 
     } 
    } 
} 

Trả lời

11

Khi nó quay ra, mã tôi đăng ở trên hoạt động rất tốt. Sự cố đã xảy ra ở một phần khác của ứng dụng của tôi. Tôi đã vô tình chuyển đổi khoảng cách từ mét để dặm, thay vì từ mét đến km. Rất tiếc!

Dù sao, hy vọng bài đăng của tôi vẫn sẽ có một số công đức, vì tôi cảm thấy đây là ví dụ khá vững chắc về cách theo dõi khoảng cách của người dùng với Vị trí cốt lõi.

+0

Đừng quên chấp nhận điều này làm câu trả lời của bạn để giữ cho nó không hiển thị như một câu hỏi mở. Ví dụ tốt đẹp bằng cách này. –

+0

Xin chào Daniel, tôi đang tìm nạp cùng một vấn đề từ hơn một tuần và vẫn không nhận được bất kỳ giải pháp nào. Vì vậy, bạn có thể giúp tôi? –

+0

@Daniel .... Hãy giúp tôi. –

0

Có thể bạn đã đặt kRequiredHorizontalAccuracy quá thấp. Nếu không có vị trí nào trong lịch sử có độ chính xác < kRequiredHorizontalAccuracy, thì bạn bỏ qua tất cả các điểm đó và thêm 0 vào khoảng cách.

+0

Thật không may là tôi không nghĩ điều đó sẽ thực hiện. Lý do đầu tiên là tôi đang ghi lại horizontalAccuracy, và nó vẫn khá ổn định ở mức 10.0 hoặc 5.0. Ngoài ra, mặc dù các điểm> kRequiredHorizontalAccuracy bị bỏ qua, ngay sau khi tôi nhận được một vị trí hợp lệ, tôi so sánh nó với vị trí hợp lệ cuối cùng để có khoảng cách, vì vậy tôi không vứt bỏ dữ liệu khoảng cách. – Daniel

+0

@Daniel ... và vị trí hợp lệ cuối cùng (lastRecordedLocation) là newLocation trong trường hợp không có độ chính xác tốt trong danh sách. Điều này có nghĩa là bạn đã đặt lại lastRecordedLocation mà không cần thêm khoảng cách. Nhân tiện, 10 và 5 khá thấp. Tôi nhận được độ chính xác 100-150 khá thường xuyên trong các bài kiểm tra của tôi. – fishinear

+0

Cảm ơn bạn đã xem qua. lastRecordedLocation chỉ nên là nil nếu một vị trí hợp lệ chưa được ghi lại, vì tôi đặt self.lastRecordedLocation = bestLocation ở phía dưới. Cảm ơn cũng cho đề xuất về độ chính xác 100-150. Tôi sẽ làm một số thử nghiệm khác ... có thể cần phải tăng kRequiredHorizontalAccuracy của tôi từ 40. – Daniel

Các vấn đề liên quan