2012-01-08 15 views
16

का उपयोग कर सटीक कुल पैदल चलने/चलने की दूरी की गणना करने में समस्या होने पर मैं एक आईओएस ऐप बनाने की कोशिश कर रहा हूं जो चलने या चलने पर यात्रा की गई कुल दूरी प्रदर्शित करता है। मैंने उन सभी दस्तावेज को पढ़ और पढ़ा है जिन्हें मैं पा सकता हूं, लेकिन मुझे कुछ ऐसी चीज आने में परेशानी हो रही है जो मुझे एक सटीक कुल दूरी प्रदान करे।CLLocationManager

नाइके + जीपीएस या रनकीपर के साथ तुलना में, मेरा ऐप लगातार एक छोटी दूरी की रिपोर्ट करता है। वे पहले इसकी रिपोर्ट करेंगे, लेकिन जैसे ही मैं आगे बढ़ता रहता हूं, मेरे ऐप के मूल्य अन्य चल रहे ऐप्स बनाम धीरे-धीरे बहते हैं।

उदाहरण के लिए, यदि मैं चलता हूं .3 किलोमीटर (मेरी कार के ओडोमीटर द्वारा सत्यापित), नाइकी + जीपीएस और रनकीपर दोनों रिपोर्ट ~ .3 किलोमीटर हर बार रिपोर्ट करते हैं, लेकिन मेरा ऐप ~ 13 किलोमीटर की रिपोर्ट करेगा। newLocation.horizontalAccuracy लगातार 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; 
     } 
    } 
} 

उत्तर

11

जैसा कि यह पता चला है, ऊपर पोस्ट किया गया कोड बहुत अच्छा काम करता है। समस्या मेरे ऐप के एक अलग हिस्से में हुई। मैं गलती से मीटर से किलोमीटर की दूरी पर मीटर से मील तक दूरी को परिवर्तित कर रहा था। ऊप्स!

वैसे भी, उम्मीद है कि मेरी पोस्ट में अभी भी कुछ योग्यता होगी, क्योंकि मुझे लगता है कि यह कोर स्थान के साथ उपयोगकर्ता की दूरी को ट्रैक करने का एक ठोस ठोस उदाहरण है।

+0

इसे एक खुला प्रश्न के रूप में दिखाने से रोकने के लिए इसे अपने उत्तर के रूप में स्वीकार करना न भूलें। रास्ते से अच्छा उदाहरण। –

+0

हैलो डैनियल, मैं एक सप्ताह से अधिक समय से एक ही समस्या ला रहा हूं और अभी भी कोई समाधान नहीं मिला है। तो, क्या आप मेरी मदद कर सकते हैं? –

+0

@ Daniel .... कृपया मेरी मदद करें। –

0

आपने शायद kRequiredHorizontalAccuracy बहुत कम सेट किया है। यदि इतिहास में कोई स्थान नहीं है जिसमें सटीकता < kRequiredHorizontalAccuracy है, तो आप उन सभी बिंदुओं को अनदेखा करते हैं और दूरी को 0 जोड़ते हैं।

+0

दुर्भाग्यवश मुझे नहीं लगता कि यह ऐसा करेगा। पहला कारण यह है कि मैं क्षैतिज सटीकता को लॉग कर रहा हूं, और यह लगातार 10.0 या 5.0 पर रहता है। इसके अलावा, भले ही अंक> kRequiredHorizontalAccuracy को अनदेखा किया जाता है, जैसे ही मुझे एक वैध स्थान मिलता है, मैं दूरी प्राप्त करने के लिए अंतिम मान्य स्थान के साथ इसकी तुलना करता हूं, इसलिए मैं दूरी डेटा को फेंक नहीं रहा हूं। – Daniel

+0

@Daniel ... और अंतिम वैध स्थान (अंतिम रिकॉर्ड किया गया स्थान) सूची में कोई अच्छी सटीकता नहीं होने पर नया स्थान है। जिसका मतलब है कि आप दूरी जोड़ने के बिना अंतिम रिकार्ड किए गए स्थान को फिर से सेट करते हैं। वैसे, 10 और 5 बहुत कम हैं। मुझे अपने परीक्षणों में नियमित रूप से 100-150 सटीकता मिलती है। – fishinear

+0

एक नज़र डालने के लिए धन्यवाद। आखिरी रिकॉर्ड किया गया स्थान केवल शून्य होना चाहिए यदि एक वैध स्थान अभी तक दर्ज नहीं किया गया है, क्योंकि मैंने self.lastRecordedLocation = नीचे सबसे अच्छा स्थान सेट किया है। 100-150 सटीकता के सुझाव के लिए भी धन्यवाद। मैं कुछ और परीक्षण करूँगा ... 40 से मेरे kRequiredHorizontalAccuracy को अपनाने की आवश्यकता हो सकती है। – Daniel

संबंधित मुद्दे