2012-03-17 11 views
12

मेरे पास एक ऐसा ऐप है जो डिवाइस के जीपीएस और उस जानकारी से आता है जो इसके बारे में आता है। यह महत्वपूर्ण है कि स्थान डेटा सटीक और अद्यतित हो। मुझे पता है कि डिवाइस अपने जीपीएस और जीपीएस की सीमाओं से सीमित है, लेकिन मैं सोच रहा था कि आईफोन जीपीएस के प्रदर्शन को विशेष रूप से गति क्षेत्र में बदलने या सुधारने के लिए मैं कुछ भी कर सकता हूं। चूंकि स्थान अपडेट डिवाइस के रीयल-टाइम स्थान के पीछे लगभग 3-5 सेकंड पीछे रहता है, इसलिए स्थान प्रबंधक द्वारा रिपोर्ट की गई वेग भी वास्तविक समय मान के पीछे है। मेरे मामले में, यह बस बहुत लंबा है। मैं समझता हूं कि ऐसा कुछ भी नहीं हो सकता है जो मैं कर सकता हूं, लेकिन क्या किसी को आईफोन जीपीएस की प्रतिक्रिया में सुधार करने में कोई सफलता मिली है? हर छोटी बिट एक फर्क पड़ता है।CLLocationManager उत्तरदायित्व

संपादित करें 1:

मेरे स्थान प्रबंधक, एक सिंगलटन वर्ग के अंदर है के रूप में एप्पल सिफारिश की।

अंदर SingletonDataController.m:

static CLLocationManager* locationManager; 
locationManager = [CLLocationManager new]; 
locationManager.distanceFilter = kCLDistanceFilterNone; 
locationManager.headingFilter = kCLHeadingFilterNone; 

if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) { 
    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 
} else { 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
} 

[sharedSingleton setLocationManager:locationManager]; 
[locationManager release]; 

अंदर MapView.m (जहां स्थान प्रबंधक वास्तव में प्रयोग किया जाता है):

- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { 
    //setup 
    [SingletonDataController sharedSingleton].locationManager.delegate = self; 
    //more setup 
} 

- (void)batteryChanged { 
    if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) { 
     [SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 
    } else { 
     [SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
    } 
} 

- (void)viewDidLoad { 
    //setup 
    [[NSNotificationCenter defaultCenter] 
     addObserver:self 
     selector:@selector(batteryChanged) 
      name:UIDeviceBatteryStateDidChangeNotification 
      object:nil]; 
    //other setup 
} 

डेटा से निपटने locationManager:didUpdateToLocation:fromLocation: अंदर होता है। मुझे विश्वास नहीं है कि यहां अक्षमता अंतराल का कारण है।

locationManager:didUpdateToLocation:fromLocation: कॉल यूआई अद्यतन करने के लिए इस विधि:

- (void)setLabels:(CLLocation*)newLocation fromOldLocation:(CLLocation*)oldLocation { 
    //set speed label 
    if(iterations > 0) { 
     if(currentSpeed > keyStopSpeedFilter) { 
      if(isFollowing) { 
       [mapViewGlobal setRegion:MKCoordinateRegionMake([newLocation coordinate], mapViewGlobal.region.span)]; 
      } 

      NSString* currentSpeedString; 
      if(isCustomary) { 
       currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (currentSpeed * 2.23693629f)]; 
      } else { 
       currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (currentSpeed * 3.6f)]; 
      } 

      [speedLabel setText:currentSpeedString]; 
      [currentSpeedString release]; 
     } else { 
      speedLabel.text = @"Not moving"; 
     } 
    } 

    //set average speed label 
    if(iterations > 4 && movementIterations > 2) { 
     NSString* averageSpeedString; 
     if(isCustomary) { 
      averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (float)((speedAverages/(long double)movementIterations) * 2.23693629f)]; 
     } else { 
      averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (float)((speedAverages/(long double)movementIterations) * 3.6f)]; 
     } 
     [averageSpeedLabel setText:averageSpeedString]; 
     [averageSpeedString release]; 
    } 

    //set elapsed time label 
    NSInteger seconds = [[NSDate date] timeIntervalSinceDate:dataObject.locationManagerStartDate]; 
    NSInteger minutes = seconds/60; 
    NSInteger hours = minutes/60; 

    //get remainder 
    seconds %= 60; 

    NSString* timeString; 
    NSString* secondsString; 
    NSString* minutesString; 
    NSString* hoursString; 

    if((seconds % 60) < 10) { 
     secondsString = [[NSString alloc] initWithFormat:@"0%i", seconds]; 
    } else { 
     secondsString = [[NSString alloc] initWithFormat:@"%i", seconds]; 
    } 

    if((minutes % 60) < 10) { 
     minutesString = [[NSString alloc] initWithFormat:@"0%i", minutes]; 
    } else { 
     minutesString = [[NSString alloc] initWithFormat:@"%i", minutes]; 
    } 

    if((hours % 60) < 10) { 
     hoursString = [[NSString alloc] initWithFormat:@"0%i", hours]; 
    } else { 
     hoursString = [[NSString alloc] initWithFormat:@"%i", hours]; 
    } 

    timeString = [[NSString alloc] initWithFormat:@"%@:%@:%@", hoursString, minutesString, secondsString]; 

    [elapsedTimeLabel setText:timeString]; 

    [timeString release], timeString = nil; 
    [secondsString release], secondsString = nil; 
    [minutesString release], minutesString = nil; 
    [hoursString release], hoursString = nil; 

    NSString* totalDistanceString; 
    if(isCustomary) { 
     totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f mi", (float)distance * 0.000621371192f]; 
    } else { 
     totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f km", (float)distance/1000.0f]; 
    } 
    [customTopBar setTitle:totalDistanceString]; 
    [totalDistanceString release]; 
} 

NSDates और NSLogs के एक जोड़े के साथ मैं ने पाया है कि पूरे locationManager:didUpdateToLocation:fromLocation: (न केवल लेबल को अपडेट करने में विधि) के निष्पादन कभी नहीं के बारे में अधिक से अधिक लेता है मेरे आईफोन 4 पर 8 एमएमएस; दूसरे शब्दों में, डेटा हैंडलिंग समस्या नहीं है।

+0

हमें दिखाएं कि आपको स्थान डेटा कैसे प्राप्त हो रहा है। वह अंतराल सामान्य नहीं है। – sosborn

+0

जोड़ा गया कोड। यदि आवश्यक हो तो मैं और अधिक पोस्ट कर सकता हूं। –

+0

3-5 सेकंड एक असाधारण का थोड़ा सा हो सकता है; देर हो चुकी है और सीमा 3-5 बस किसी कारण से मेरे सिर में चली गई। कल मैं सटीक संख्या प्राप्त करने के लिए कुछ परीक्षण चलाऊंगा। –

उत्तर

27

ठीक है, कुछ चीजें आपके अंतराल में सुधार कर सकती हैं। सबसे पहले, हमेशा केसीएलएलोकेशनएक्वायरिएस्टबेस्टफॉरनेविगेशन का उपयोग करें। उस और केसीएलएलोकेशनएक्करसीबेस्ट के बीच कोई वास्तविक बैटरी उपयोग अंतर नहीं है, वे दोनों शीर्ष गति पर जीपीएस का उपयोग करते हैं। मुख्य अंतर पोस्ट-प्रोसेसिंग में है जो ऐप्पल करता है।

दूसरा, गति == 0. के लिए फ़िल्टर करने की कोई आवश्यकता नहीं है। ऐप्पल पहले से ही फ़िल्टरिंग करता है: यदि जीपीएस से आपकी गति एक निश्चित दहलीज (लगभग 4 किमी/घंटा) से नीचे गिरती है, तो ओएस मानता है कि आप अभी भी खड़े हैं , और यह सभी बाद के नमूने के लिए एक ही स्थान मूल्य को प्रतिस्थापित करता है। ऐसा तब तक होता है जब तक ऐसा लगता है कि आप फिर से आगे बढ़ रहे हैं। मुझे लगता है कि वे अभी भी खड़े होने पर मानचित्र पर "झटके" से बचने के लिए ऐसा करते हैं। वास्तव में, गति "स्थायी-अभी भी" मानों के अनुक्रम के अंतिम वास्तविक मूल्य के लिए 0 से पहले तक गिर जाती है, इसलिए यदि आप गति == 0 पर फ़िल्टर करते हैं तो आप एक वास्तविक जीपीएस नमूना खो रहे हैं।

दुर्भाग्यवश, वे फ़िल्टरिंग से बचने और वास्तविक जीपीएस नमूने प्राप्त करने का कोई तरीका नहीं है। मैंने ऐप्पल से इसके बारे में बात की, और उनकी प्रतिक्रिया यह थी कि वे व्यवहार को बदलने वाले नहीं हैं। kCLLocationAccuracyBestForNavigation kCLLocationAccuracyBest की तुलना में कम आक्रामक फ़िल्टरिंग करता है, इसलिए इसका उपयोग करना सबसे अच्छा है।

तीसरा, आप शायद पहले ही ऐसा कर रहे हैं, लेकिन यह सुनिश्चित करने के लिए कि "नक्शा वास्तव में फिर से खींचा गया है," सुनिश्चित करने के लिए आप "didUpdateFromLocation:" से अपने दृश्य पर "setNeedsDisplay" को कॉल करते हैं।

यदि आप यह सब करते हैं, तो आपको लगभग 1 सेकंड का अंतराल होना चाहिए। यदि आप भविष्यवाणी तकनीकों का उपयोग करने की कोशिश कर सकते हैं तो 1 सेकंड पर सुधार करना चाहते हैं। पिछले दो स्थानों और दी गई गति से, आप गणना कर सकते हैं कि अगला स्थान कहां होने की संभावना है, और पहले से ही उस स्थान को प्रदर्शित कर सकता है। मेरे पास मिश्रित परिणाम हैं। यह तेजी से आंदोलन के लिए अच्छी तरह से काम करता है जो एक कार चलाते समय अचानक गति नहीं बदलता है।यह चलने या बाइकिंग जैसे धीमी गति से चलने के लिए कम अच्छी तरह से काम करता है।

+0

धन्यवाद बहुत '' 'केसीएल लोकेशनएक्वेरिएस्टबेस्टफॉरनविगेशन 'वास्तव में मेरी मदद की। स्थान प्रतिनिधि विधियां अब इतनी तेज दौड़ती हैं :) – Supertecnoboff

6

iPhone में हम दो तरीकों से स्थान सेवाओं को कॉन्फ़िगर कर सकते हैं -

  1. Standard Location Services का उपयोग करके, कि उपग्रह जीपीएस जो आपको और अधिक सटीक डेटा प्रदान करना है।
  2. Significant Location Changes का उपयोग करके जो ए-जीपीएस का उपयोग करता है या वाई-फाई के माध्यम से स्थान प्राप्त करता है जो कम सटीक डेटा प्रदान करता है।

हम इन दो विधियों में से किसी भी स्थान से स्थान सेवाएं कॉन्फ़िगर कर सकते हैं लेकिन यह ऐप की आवश्यकता पर निर्भर करता है। यदि ऐप navigation app या location tracking app है तो हमें Standard Location Services का उपयोग करना चाहिए, लेकिन मानक सेवाओं का उपयोग करने से पहले हमें यह ध्यान में रखना होगा कि यदि आप अधिक सटीक डेटा चाहते हैं तो आपको battery consume more quickly से पीड़ित होना होगा। यदि ऐप को स्थान अपडेट की आवश्यकता नहीं होती है और accuracy doesn't matter बहुत कुछ तो हमें Significant Location Changes चाहिए क्योंकि यह save a lot of battery मानक स्थान सेवा की तुलना में उपभोग करेगा।

मानक स्थान सेवा desiredAccuracy और distanceFilter मान का उपयोग यह निर्धारित करने के लिए करती है कि ईवेंट कब और कब वितरित किया जाए।

desiredAccuracy वह पैरामीटर है जहां आप परिभाषित कर सकते हैं कि आप जीपीएस हार्डवेयर से कितनी सटीकता चाहते हैं। यह के रूप में कुछ पूर्व निर्धारित स्थिरांक का उपयोग करता है -

kCLLocationAccuracyBestForNavigation 
kCLLocationAccuracyBest 
kCLLocationAccuracyNearestTenMeters 
kCLLocationAccuracyHundredMeters 
kCLLocationAccuracyKilometer 
kCLLocationAccuracyThreeKilometers 

distanceFilter पैरामीटर जहां दूरियां को परिभाषित करने के लिए है है, कितना दूरी की खाई को आप किसी स्थान अपडेट भेजने का जीपीएस हार्डवेयर पूछना चाहता हूँ के लिए मायने रखता है।

आपके मामले में आप गति पैरामीटर से निपट रहे हैं, इसलिए मुझे लगता है कि यह नेविगेशन से संबंधित कुछ है। तो आपको Standard Location Services का उपयोग करना चाहिए। मुझे लगता है कि आप यह भी कर रहे हैं लेकिन आप जिस मुद्दे का सामना कर रहे हैं वह स्थान अपडेट के बीच अंतराल है। यहां मैं आपको अपने desiredAccuracy और distanceFilter को संशोधित करने के लिए सुझाव देता हूं -

[स्थान प्रबंधक सेटडिस्डएक्वायरसी: केसीएल लोकेशनएक्वायरीएरेस्टटेनमीटर]; [स्थान प्रबंधक सेटडिस्टेंसफिल्टर: 10.0 एफ];

इससे मूल्य निर्धारित करके आपको स्थानांतरित होने पर कम से कम 1 सेकंड में स्थान अपडेट प्राप्त होगा।

एक और चीज आपको अपने दिमाग में रखना है कि जब आपको स्थान अपडेट मिलता है तो आपको पुराने स्थान अपडेटों को अनदेखा करने के लिए timestamp मान देखना चाहिए। इसकी वजह यह है कि जब आप पर कॉल करके locationManager प्रारंभ करते हैं तो आपको प्राप्त होने वाला पहला स्थान आपका पुराना स्थान हो सकता है। इसके अलावा आपको horizontalAccuracy मान की जांच करनी होगी क्योंकि आपको पहले कुछ स्थान अपडेट प्राप्त होने पर सटीक नहीं है और 1000 या उससे अधिक में सटीकता हो सकती है जिसे आप ढूंढ नहीं रहे हैं। तो आपको गलत स्थान अपडेट को अनदेखा करने के लिए अपना मान देखना होगा।

Note: If you try with different accuracy and different distance filter value then you will be more clear about it how accurate data iPhone GPS hardware return. 
1

कोर स्थान का उपयोग कैसे करें के अन्य अच्छे उदाहरण के अलावा, यह भी ध्यान में सामान्य तकनीक Kalman Filtering की (जैसे स्मार्टफोन स्थान सेवाओं) एक नहीं तो महान सेंसर से अच्छा कीनेमेटीक्स परिणाम प्राप्त करने के लिए रहते हैं।

यह गणित और परीक्षण और tweaking के बहुत सारे है, लेकिन यह आपको सेंसर प्रदान करने से सरल डेटा की तुलना में बेहतर परिणाम पर विचार करने के लिए अनुमति देता है।

यह एवियनिक्स और रडार प्रोसेसिंग सिस्टम जैसी चीजों में उपयोग किया जाता है।

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