12
17
2011
iPhone用GPSナビに挑戦 #5
iPhoneのGPS取得精度を高める工夫について
GPSの位置取得精度を改善したバージョン
iPhoneとiOSのCore Location フレームワークの組み合わせを用いて、自分の思い通りの位置精度で現在位置の場所を取り出すのは難しいですが、プログラムの工夫で多少は位置情報の取得精度を高めることができそうです.(『@yuumi3のお仕事日記』の記事を参考にさせてもらいました)
精度を高める方法としては、位置情報の取得を開始してから有る一定時間の間位置情報イベントを全てピックアップし、その中から一番精度の良い情報だけを選択して位置情報を返すようにすれば良さそうです.また、測定開始時にキャッシュされていた古い位置情報が返される場合があるので、タイムスタンプを見て有る一定時刻より前の古い情報は破棄するようにしてみました.
Google Mapsを用いた現在位置表示サンプルプログラムに改良を加えるとこんな感じでしょうか.
“ViewController.m” [sourcecode language=”objc”] #import "ViewController.h" @implementation ViewController @synthesize locationManager; @synthesize locationText, accuracyText, statusText; @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]; myBestLocation = nil; // 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]; // set aquiring duration [self performSelector: @selector ( stopUpdatingLocation: ) withObject: (id) nil afterDelay: GCL_Measure_Duration ]; // set GPS status statusText.text = @"Acquiring GPS Location…"; } 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]; } } – (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 { //NSLog( @"Obtained Location : %@", newLocation.description ); // dispose low accuracy data if ( newLocation.horizontalAccuracy > GCL_Threshold_Accuracy ) return; // dispose old data if ( -[newLocation.timestamp timeIntervalSinceNow] > GCL_Measure_Duration ) return; // keep the best accuracy data if ( myBestLocation == nil || myBestLocation.horizontalAccuracy > newLocation.horizontalAccuracy ) { myBestLocation = newLocation; } NSString *latitude = [[NSString alloc] initWithFormat:@"%.6f", myBestLocation.coordinate.latitude]; NSString *longitude = [[NSString alloc] initWithFormat:@"%.6f", myBestLocation.coordinate.longitude]; NSString *altitude = [[NSString alloc] initWithFormat:@"%.1f", myBestLocation.altitude]; NSString *hAccuracy = [[NSString alloc] initWithFormat:@"%.0fm", myBestLocation.horizontalAccuracy]; NSString *vAccuracy = [[NSString alloc] initWithFormat:@"%.0fm", myBestLocation.verticalAccuracy]; NSString *location = [[NSString alloc] initWithFormat:@"Location:(%@,%@), %@m", latitude, longitude, altitude]; NSString *accuracy = [[NSString alloc] initWithFormat:@"Accuracy: H:%@, V:%@", hAccuracy, vAccuracy]; locationText.text = location; accuracyText.text = accuracy; // show the place on Google Maps MKCoordinateRegion region = MKCoordinateRegionMake( newLocation.coordinate, MKCoordinateSpanMake(0.005, 0.005) ); [googleMapView setCenterCoordinate: myBestLocation.coordinate]; [googleMapView setRegion: region animated: TRUE]; } -(void) stopUpdatingLocation: (NSObject *) args { [locationManager stopUpdatingLocation]; if ( myBestLocation == nil ) { statusText.text = @"GPS Data Acquisition Failed."; return; } NSDateFormatter *timeformat = [ [NSDateFormatter alloc ] init ]; [ timeformat setDateFormat: @"HH:mm:ss" ]; NSString *status = [[NSString alloc] initWithFormat:@"GPS Data Acquisition Succeeded. (%@)", [timeformat stringFromDate: myBestLocation.timestamp]]; statusText.text = status; [googleMapView setCenterCoordinate: myBestLocation.coordinate]; } – (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]; } @end [/sourcecode]