塩竃神社


Date/Time: 2020:01:06 14:33:55
Camera: RICOH
Model: GR DIGITAL 4
Exporsure Time: 1/125
FNumber: 1.9
Aperture Value: 1.9
Focal Length: 6.0

Close

y2blog » iPhone用GPSナビに挑戦 #3

12

09

2011

iPhone用GPSナビに挑戦 #3

Core Location frameworkを使用してみる


Core Location frameworkはAppleが提供している位置情報や方位などの情報を GPSやWi-Fiアクセスポイント、3G回線基地局などの情報をベースに取り出すためのフレームワークです.iPhoneのユーザであれば Google Mapsを利用した位置情報アプリの”Maps”やサードパーティー製のアプリなどでこのフレームワークのお世話になっているはずです.


Core Location frameworkはシンプルなAPIの呼び出しだけで面倒な手続きを経なくても位置情報や方位情報が取り出せるので、一般的な用途には便利なのですが、iPhoneをGPSロガーやGPSナビとして使いたい場合には細かな条件設定ができないので使いづらいかもしれません.iPhoneのGPS受信機能は一般的なGPSロガーに較べると受信感度や測位誤差などの面で分が悪いようです.


iPhoneが本格的なGPSナビとして使えるかどうかは微妙な所ですが、とりあえずCore Location frameworkを用いて位置情報を取得する簡単なアプリを作成してみました.Core Location frameworkの使い方を調べるためのどーでも良いようなアプリですので実用性は全くありません.このアプリでは現在地情報を取得してその緯度・経度、高度を画面に表示し、ついでにGoogle Maps上に現在地を表示するだけです.勿論実際のGPSナビアプリではネットワークが使えない状況でも地図情報を何らかの形でiPhoneの内部に記憶させておかなければなりませんので、常時ネットワーク接続が要求される通常のGoogle Mapsでは全く役に立ちません.

Core Location frameworkの概要


Core Location frameworkの概要を知るには、Appleのデベロッパ向けのページから情報を得るのが一番正確で手っ取り早い方法です.Core Location frameworkやGoogle Mapsのフレームワークである MapKit の概要を知るには “Making Your Application Location-Aware“に目を通しておくと良いでしょう. (日本語版PDFドキュメント『位置情報対応プログラミングガイド』)
Core Location frameworkのクラスに関するドキュメント CLLocationManager Class Reference
現在位置を取得するサービスとして、”standard location service”〔標準位置情報サービス)と”significant-change location service”(大幅変更位置情報サービス)の2種類が用意されており、用途によって使い分けるようになっています.


任意の精度で細かに位置情報を取得する場合は”standard location service”〔標準位置情報サービス)を用い、大まかな位置情報の把握だけで良い場合には”significant-change location service”(大幅変更位置情報サービス)を使うように推奨されています.”standard location service”は主にGPSを主体とした位置情報取得で、”significant-change location service”は携帯電話の無線基地局が単位の位置情報取得のようです.


“standard location service”〔標準位置情報サービス)の利用手続きとしては次の様な流れになります

・location Managerのインスタンスを作成し初期化

・位置情報サービスの利用が可能かどうかを調べる

・要求精度やイベントの距離によるフィルタリング等の設定

・測位開始
[sourcecode language=”objc”] // Allocate a location manager instance and initialize it. locationManager = [[CLLocationManager alloc] init]; // check to see if location service is available or not. // クラスメソッド locationServicesEnabled を用いて位置情報サービスが利用可能かどうかチェック if ([CLLocationManager locationServicesEnabled]) { // accessing the delegate (自分自身をデリゲートに設定) locationManager.delegate = self; // set accuracy and event filtering parameters locationManager.desiredAccuracy = kCLLocationAccuracyBest; // 要求する精度を指定 locationManager.distanceFilter = kCLDistanceFilterNone; // 距離の閾値を設定(この場合は設定無し) // start location service [locationManager startUpdatingLocation]; // 位置情報の取得開始 } else { // Error Handling 〔エラー処理) } [/sourcecode]

CoreLocation Managerオブジェクトに対してユーザが用意しておくデリゲートプロトコルについては、”CLLocationManagerDelegate Protocol Reference” を参照して下さい.
位置情報の取得では、
[sourcecode language=”objc”] – (void) locationManager: (CLLocationManager *) manager didUpdateToLocation: (CLLocation *) newLocation fromLocation:(CLLocation *) oldLocation – (void) locationManager: (CLLocationManager *) manager monitoringDidFailForRegion: (CLRegion *) region withError:(NSError *) error [/sourcecode]
の2つのメッソドを用意しておく必要があります.”didUpdateToLocation:fromLocation:” メソッドは、位置情報取得イベントが発生する度に呼び出されます.”didFailWithError:” メソッドには何らかの原因で位置情報の取得に失敗した場合の処理を記述しておきます.


newLocation は新しく発生した位置イベントに対する位置情報が、oldLocationには 直前のイベントでの位置情報が渡されます.
[sourcecode language=”objc”] – (void) locationManager: (CLLocationManager *) manager didUpdateToLocation: (CLLocation *) newLocation fromLocation: (CLLocation *) oldLocation { NSString *latitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.coordinate.latitude]; NSString *longitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.coordinate.longitude]; NSString *altitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.altitude]; NSLog( @"Current Location latitude=%@, longitude=%@, altitude=%@", latitude, longitude, altitude ); } [/sourcecode]


iPhone3GSのGPS受信精度


iPhoneをGPSナビとして使用する場合やはりその位置情報取得精度が気になります.GPSナビ専用機には遠く及ばなくても誤差としては緯度・経度で20m、高度で30m以内であって欲しいところです.まだ山の中で試した訳ではありませんがiPhone3GSのGPS精度はちょっと期待はずれと言ったところでしょうか.


Core Location framework を用いて位置情報を取得する際には予め要求される精度の設定を行う必要がありますが、指定できるのは

kCLLocationAccuracyBest :         出来る限り高精度の位置情報を出力する

kCLLocationAccuracyNearestTenMeters :  10m程度の精度

kCLLocationAccuracyHundredMeters :    100m程度

kCLLocationAccuracyKilometer :       1km程度

kCLLocationAccuracyThreeKilometers :   3km程度
しかないようです.この要求精度の設定が小さいと測位値のふらつき(誤差)の影響を受けて、1秒おきくらいに絶えずイベントを発生させてしまいます.要求値を100m位に設定すれば測位値のふらつきの影響は殆ど受けなくなりますが、逆に分解能が悪くなりすぎて実用的ではなくなってしまいます.


要求する精度意外にも距離によるフィルタリング(閾値)設定が行えるようですが、この値を適切に設定しておけば測位値のふらつきがあったとしても不要なイベントの発生を抑止できるようです.この辺の設定は試行錯誤するしかないようですね.


GPSロガーとして使用する場合には距離だけではなく、ある一定時間毎に位置を取得する時間軸ベースの測位もできないと不便です.


iPhoneでGPS測位情報を利用する際にはこの要求精度の設定が鍵になりそうですね.やはりCore Location frameworkでは痒いところに手が届かないようですので、もう少し低レベルのフレームワークが欲しいところです.できればGPSチップのパラメータに直接アクセスできるような仕組みがあれば都合が良いのですが...


現在地情報取得簡易アプリ”GetLocation” の作成


xcodesetting 01 addframework xcodesetting 02 mainstoryboard 01 mainstoryboard 02 GetLocation on simulator screenshot


“ViewController.h” [sourcecode language=”objc”] // // ViewController.h // GetLocation // // Created by y2 on 12/9/11. // Copyright (c) 2011 y2lab.org. All rights reserved. // #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> #import <MapKit/MapKit.h> @interface ViewController : UIViewController <CLLocationManagerDelegate> { CLLocationManager *locationManager; IBOutlet UITextField *latTextField; IBOutlet UITextField *lonTextField; IBOutlet UITextField *altTextField; IBOutlet MKMapView *googleMapView; } @property (nonatomic, retain) CLLocationManager *locationManager; @property (retain, nonatomic) UITextField *latTextField; @property (retain, nonatomic) UITextField *lonTextField; @property (retain, nonatomic) UITextField *altTextField; @property (nonatomic, retain) IBOutlet MKMapView *googleMapView; @end [/sourcecode] “ViewController.m” [sourcecode language=”objc”] // // ViewController.m // GetLocation // // Created by y2 on 12/9/11. // Copyright (c) 2011 y2lab.org. All rights reserved. // #import "ViewController.h" @implementation ViewController @synthesize locationManager; @synthesize latTextField, lonTextField, altTextField; @synthesize googleMapView; – (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren’t in use. } #pragma mark – View lifecycle – (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // Allocate a location manager instance and initialize it. locationManager = [[CLLocationManager alloc] init]; // check to see if location service is available or not. if ([CLLocationManager locationServicesEnabled]) { locationManager.delegate = self; // set accuracy and event filtering parameters locationManager.desiredAccuracy = kCLLocationAccuracyBest; //locationManager.distanceFilter = kCLDistanceFilterNone; locationManager.distanceFilter = 50.0f; // 50m // start location service [locationManager startUpdatingLocation]; } else { NSString *msg = [[NSString alloc] initWithString:@"Error : Location service is not available."]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg delegate:nil cancelButtonTitle: @"Done" otherButtonTitles:nil]; [alert show]; // [msg release]; // use Xcode4.2 ARC // [alert release]; } } – (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } – (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } – (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } – (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } – (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } //================= Core Location Service Delegates ====================== – (void) locationManager: (CLLocationManager *) manager didUpdateToLocation: (CLLocation *) newLocation fromLocation: (CLLocation *) oldLocation { NSString *latitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.coordinate.latitude]; NSString *longitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.coordinate.longitude]; NSString *altitude = [[NSString alloc] initWithFormat:@"%.6f", newLocation.altitude]; //NSLog( @"Current Location latitude=%@, longitude=%@, altitude=%@", latitude, longitude, altitude ); latTextField.text = latitude; lonTextField.text = longitude; altTextField.text = altitude; // show the place on Google Maps MKCoordinateRegion region = MKCoordinateRegionMake( newLocation.coordinate, MKCoordinateSpanMake(0.05, 0.05)); [googleMapView setCenterCoordinate: newLocation.coordinate]; [googleMapView setRegion: region animated: TRUE]; } – (void) locationManager: (CLLocationManager *) manager didFailWithError: (NSError *) error { NSString *msg = [[NSString alloc] initWithString:@"Error obtaining location"]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg delegate:nil cancelButtonTitle: @"Done" otherButtonTitles:nil]; [alert show]; // [msg release]; // [alert release]; } @end [/sourcecode]

Calendar

April 2024
S M T W T F S
1234567
891011121314
15161718192021
22232425262728
293031  
  • Blogroll

  • Meta