2009-07-04 11 views
17

に高速なデータポイントを取得するためにCLLocationManager/CoreLocationを最適化私は現在、他の場所のN量に、ユーザーの現在位置を比較するためにCoreLocation + CLLocationManagerを使用しています。私が直面している問題は、私は場所がお互いに近い都市部を扱っているので、あまりにも多くの時間を犠牲にすることなく、デバイスが許す限り正確にユーザーの位置を特定する必要があります。私の計算は正確で、問題は10サンプルを集めるのに時間がかかりすぎるということです。私は以下のフィルタ/正確さのそれぞれのコードを貼り付けます。どのように私がこれをスピードアップすることができるか誰かがコメントできれば、それは素晴らしいだろう。私はそれをスピードアップするまで、私のアプリでは無駄です。現在、目標の人口統計で受け入れられない情報を収集するのに3〜4分かかります。これをスピードアップするために任意の最適化のためのトリックはiPhone

[self.locationManager setDistanceFilter:kCLDistanceFilterNone]; 
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    if (newLocation.horizontalAccuracy > 0.0f && 
     newLocation.horizontalAccuracy < 120.0f) { // roughly an accuracy of 120 meters, we can adjust this. 

    [myLocs addObject:newLocation]; 
} 

ありがとう:

コードは次のようになります。

答えて

48

私はまた、iPhoneにCLLocationManagerの問題の多くを持っていました。 さまざまなAppsや試行錯誤から、これは私が理解したものです。

1)の例を、以下、locationManagerのためにインスタンスを1つだけシングルトンクラスを使用します。

AppleのLocateMe例

Tweetero:私はあなただけのものを持つことができると思っていhttp://tweetero.googlecode.com/svn/trunk

ロケーションマネージャーを実行すると、iPhoneにはGPSチップが1つしかないため、複数のロケーションマネージャオブジェクトを起動すると競合し、GPSロケーションマネージャーから更新できないというエラーが表示されます。

[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet; 
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet; 

このアプローチは動作し、エラーが発生しません:

2)あなたがlocationManager.desiredAccuracylocationManager.distanceFilter

FlipsideViewControllerで、このAppleのコード例に従ってくださいを更新する方法は十分に注意してください。あなたがメインのデリゲートループにdesiredAccuracyまたは distanceFilterを更新した場合:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 

コア場所は、おそらくそれが値を更新することができないと文句を言うと、あなたにエラーを与えるだろう。 また、Appleによって提供されたdesiredAccuracyの定数のみを使用し、その他のものは です。

kCLLocationAccuracyBest、kCLLocationAccuracyNearestTenMeters、
kCLLocationAccuracyHundredMeters、kCLLocationAccuracyKilometer、他の値の
kCLLocationAccuracyThreeKilometers

使用すると、あなたのlocationManagerからのエラーを与えるかもしれません。 distanceFilterについては、任意の値を使用することができますが、人々には問題があることに気付いています。 デフォルト値の主な値は次のとおりです。-1 =ベスト、10.0を使用しました。

3)新しいアップデートを強制するには、TweeteroのようなstartUpdatesメソッドを呼び出します。これにより、 locationManagerが強制的に新しい値を取得します。

4)コアロケーションデリゲートルーチンは、正確なアップデートを取得するのが難しいです。 あなたのアプリケーションが最初に初期化されるとき、あなたは1000メートル以上の精度でオフになることができるので、 1つの試みはそれを行なわないでしょう。初期化後の3回の試行では通常、4735メートル以内にある が得られます。連続して試行するたびに精度を向上させるためには、 に時間がかかりますので、すぐに高価になります。 最新のものであれば新しい値をとるAND 新しい場所の精度がやや良い場合は、新しい場所を取る 新しい場所の精度が<の場合は新しい場所を取るOR 試行回数が3回または5回を超え、精度が<の場合150メートルAND の位置が変更されている場合、これは新しい場所であり、移動されたデバイスの精度は悪くてもこの の値になります。あなたはiPhone 3GSをお持ちの場合は、ここで上記と同じモジュール内のコードですが、見出しの更新を得ることは非常に簡単です

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation  *)newLocation  fromLocation:(CLLocation *)oldLocation 
{ 
    locationDenied = NO; 

    if(![[NSUserDefaults standardUserDefaults] boolForKey:@"UseLocations"]) 
    { 
     [self stopAllUpdates]; 
     return; 
    } 

    NSDate* eventDate = newLocation.timestamp; 
    NSTimeInterval howRecent = abs([eventDate timeIntervalSinceNow]); 
    attempts++; 

    if((newLocation.coordinate.latitude != oldLocation.coordinate.latitude) && (newLocation.coordinate.longitude != oldLocation.coordinate.longitude)) 
     locationChanged = YES; 
     else 
      locationChanged = NO; 

    #ifdef __i386__ 
      //Do this for the simulator since location always returns Cupertino 
      if (howRecent < 5.0) 
    #else 
       // Here's the theory of operation 
       // If the value is recent AND 
       // If the new location has slightly better accuracy take the new location OR 
       // If the new location has an accuracy < 50 meters take the new location OR 
       // If the attempts is maxed (3 -5) AND the accuracy < 150 AND the location has changed, then this must be a new location and the device moved 
       // so take this new value even though it's accuracy might be worse 
       if ((howRecent < 5.0) && ((newLocation.horizontalAccuracy < (oldLocation.horizontalAccuracy - 10.0)) || (newLocation.horizontalAccuracy < 50.0) 
              || ((attempts >= attempt) && (newLocation.horizontalAccuracy <= 150.0) && locationChanged))) 
    #endif 
       { 
        attempts = 0; 
        latitude = newLocation.coordinate.latitude; 
        longitude = newLocation.coordinate.longitude; 
        [currentLocation release]; 
        currentLocation = [newLocation retain]; 
        goodLocation = YES; 

        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateLocationNotification" object: nil]; 

        if (oldLocation != nil) { 
         distanceMoved = [newLocation getDistanceFrom:oldLocation]; 
         currentSpeed = newLocation.speed; 
         distanceTimeDelta = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp]; 
        } 
       } 
    // Send the update to our delegate 
    [self.delegate newLocationUpdate:currentLocation]; 
} 

::このことができます

//This is the Heading or Compass values 
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { 
    if (newHeading.headingAccuracy > 0) 
    { 
     [newHeading retain]; 
     // headingType = YES for True North or NO for Magnetic North 
     if(headingType) { 
      currentHeading = newHeading.trueHeading; 
     } else { 
      currentHeading = newHeading.magneticHeading; 
     } 

     goodHeading = YES; 
     [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateHeadingNotification" object: nil]; 

    } 
} 

ホープ はここでこれを行うには、私の場所のコードです人!

+0

グレートコード(おそらく他の更新ができなくなります)。しかし、以下の回答ノートでは、didUpdateToLocation:が起動するまでに時間がかかることがあります。私は試してみましたが、関係なく、私が内部にいるときには更新が遅くなっています。時には1分以上かかることもあります。しかし、Maps.appに切り替えると、すぐに自分の場所が見つかります。 MapKitと同じように、APIを使って同じ瞬時の精度を得ることができたらと思います。 – runmad

+0

私はユーザーのデフォルトで "UseLocations"をチェックする理由は?この値はOSによって自動的に設定されますか? – nonamelive

+1

グレートコード。 locationChanged = YESを設定すると、ifステートメントは||の代わりに &&。 latまたはlonのいずれかが変更された場合は、場所が変更されています。 –

4

didUpdateToLocationユーザが場所を移動させるだけアップデート。あなたが気づいたと確信しているので、これは散発的である可能性があります。 CCLocationManagerは定期的な更新を送信しませんが、ユーザが移動したときに更新を送信したり、正確さを増やしたりします。私が静止していて、アプリを始めると、私は通常約3回のアップデートを受け取り、しばらくは何もしません。 Googleマップでは同様のことが行われ、正確さが増すにつれてリング対ポイントが表示されます。必要な精度(< 120.0f)に達するまで待ってから、行動や計算を実行することをお勧めします。

あなたはアップデートが送信される「通常」GPS、に慣れているし、それはそれは精度だリファインし続けた場合、私はiPhoneがこれを行うために設計されていないんです。

はまた、あなたはMapKitのAPIを使用して、ユーザーにその場所で地図を表示し、彼らは場所が十分に正確であると感じたら、「受け入れる」する可能性があります。時々私はピンポイントを得て、そして30秒後に私が実際にどこに50メートルも移動するかもしれないことに気付く。

0

私はあなたが、結果の精度はacceptableAccuracyよりも優れている場合は、我々は我々がoccuracyのアップデートを取得する場合、我々は待って

  • を行っているhttps://github.com/xelvenone/M6GPSLocationManager

    • を使用して自由である、この上のGITレポを書きましたmaximumWaitTimeForBetterResultを使用すると、より良い結果を得ることができます。 - これが行われなければ、完了して最善を尽くす
    • maximumAttemptsを超えるアップデートを定期的に取得している場合は、最高のものを取得します(とにかく移動しています)
    • yの他の更新は30秒で、私たちが行っている

    コード

    - (void)scopeToCurrentLocationWithAcceptableAccuracy:(CLLocationAccuracy)acceptableAccuracy 
           maximumWaitTimeForBetterResult:(NSTimeInterval)maximumWaitTimeForBetterResult 
              maximumAttempts:(NSInteger)maximumAttempts 
               onCompletion:(M6GPSLocationManagerCompletion)completion;