OLYMPUS AIRにスマホの現在地を設定する方法
自作アプリにてスマホの現在地をカメラ(OLYMPUS AIR)にOLYCameraのsetGeolocation:error:
を使って設定しようとしています。
カメラSDKのAPIリファレンスによるとメソッド引数の位置情報はNMEA0183形式の文字列で指定しなければなりません。iOSでの現在地はCLLocationで表されるため、引数値にするにはこの形式の文字列に変換する必要があります。
CLLocationインスタンスをNMEA0183形式の文字列に試行錯誤して変換してみましたが、意図した座標からなぜか数百メートル南にずれたりするなどして、OA.ModeDialのように現在地を的確な精度の緯度経度で写真のタグに設定できませんでした。
NMEA0183のGPGGAセンテンスとGPRMCセンテンスには沢山のフィールドがありますが、CLLocationインスタンスをどのようにこれらのフィールドに設定すると良いのでしょうか?
教えてください。
追加情報
試行錯誤している作成中のソースコードは以下のようなものです。
@interface Camera : OLYCamera
/// Core Locationから得た位置情報をカメラに登録します。
- (BOOL)setGeolocationWithCoreLocation:(CLLocation *)location error:(NSError **)error;
@end
@implementation Camera
- (BOOL)setGeolocationWithCoreLocation:(CLLocation *)location error:(NSError **)error {
// 10進数の緯度経度を60進数の緯度経度に変換します。
CLLocationDegrees latitude = [self convertCLLocationDegreesToNmea:location.coordinate.latitude];
CLLocationDegrees longitude = [self convertCLLocationDegreesToNmea:location.coordinate.longitude];
// GPGGAレコード
NSMutableString *nmea0183GPGGA = [[NSMutableString alloc] init];
NSDateFormatter *nmea0183GPGGATimestampFormatter = [[NSDateFormatter alloc] init];
[nmea0183GPGGATimestampFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[nmea0183GPGGATimestampFormatter setDateFormat:@"HHmmss.SSS"];
[nmea0183GPGGA appendString:@"GPGGA,"];
[nmea0183GPGGA appendFormat:@"%@,", [nmea0183GPGGATimestampFormatter stringFromDate:location.timestamp]]; // 測位時刻
[nmea0183GPGGA appendFormat:@"%08.4f,", latitude]; // 緯度
[nmea0183GPGGA appendFormat:@"%@,", (latitude > 0.0 ? @"N" : @"S")]; // 北緯、南緯
[nmea0183GPGGA appendFormat:@"%08.4f,", longitude]; // 経度
[nmea0183GPGGA appendFormat:@"%@,", (longitude > 0.0 ? @"E" : @"W")]; // 東経、西経
[nmea0183GPGGA appendString:@"1,"]; // 位置特定品質: 単独測位
[nmea0183GPGGA appendString:@"08,"]; // 受信衛星数: 8?
[nmea0183GPGGA appendString:@"1.0,"]; // 水平精度低下率: 1.0?
[nmea0183GPGGA appendFormat:@"%1.1f,", location.altitude]; // アンテナの海抜高さ
[nmea0183GPGGA appendString:@"M,"]; // アンテナの海抜高さ単位: メートル
[nmea0183GPGGA appendFormat:@"%1.1f,", location.altitude]; // ジオイド高さ
[nmea0183GPGGA appendString:@"M,"]; // ジオイド高さ: メートル
[nmea0183GPGGA appendString:@","]; // DGPSデータの寿命: 不使用
[nmea0183GPGGA appendString:@","]; // 差動基準地点ID: 不使用
unichar nmea0183GPGGAChecksum = 0;
for (NSInteger index = 0; index < nmea0183GPGGA.length; index++) {
nmea0183GPGGAChecksum ^= [nmea0183GPGGA characterAtIndex:index];
}
nmea0183GPGGAChecksum &= 0x0ff;
[nmea0183GPGGA insertString:@"$" atIndex:0];
[nmea0183GPGGA appendString:@"*"];
[nmea0183GPGGA appendFormat:@"%02lX", (long)nmea0183GPGGAChecksum]; // チェックサム
// GPRMCレコード
NSMutableString *nmea0183GPRMC = [[NSMutableString alloc] init];
NSDateFormatter *nmea0183GPRMCTimestampFormatter = [[NSDateFormatter alloc] init];
[nmea0183GPRMCTimestampFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[nmea0183GPRMCTimestampFormatter setDateFormat:@"HHmmss.SSS"];
NSDateFormatter *nmea0183GPRMCDateFormatter = [[NSDateFormatter alloc] init];
[nmea0183GPRMCDateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[nmea0183GPRMCDateFormatter setDateFormat:@"ddMMyy"];
[nmea0183GPRMC appendString:@"GPRMC,"];
[nmea0183GPRMC appendString:@"A,"]; // ステータス: 有効
[nmea0183GPRMC appendFormat:@"%@,", [nmea0183GPRMCTimestampFormatter stringFromDate:location.timestamp]]; // 測位時刻
[nmea0183GPRMC appendFormat:@"%08.4f,", latitude]; // 緯度
[nmea0183GPRMC appendFormat:@"%@,", (latitude > 0.0 ? @"N" : @"S")]; // 北緯、南緯
[nmea0183GPRMC appendFormat:@"%08.4f,", longitude]; // 経度
[nmea0183GPRMC appendFormat:@"%@,", (longitude > 0.0 ? @"E" : @"W")]; // 東経、西経
[nmea0183GPRMC appendFormat:@"%04.1f,", (location.course > 0.0 ? location.speed * 3600.0 / 1000.0 * 0.54 : 0.0)]; // 移動速度(ノット毎時)
[nmea0183GPRMC appendFormat:@"%04.1f,", (location.course > 0.0 ? location.course : 0.0)]; // 移動方向
[nmea0183GPRMC appendFormat:@"%@,", [nmea0183GPRMCDateFormatter stringFromDate:location.timestamp]]; // 測位日付
[nmea0183GPRMC appendString:@","]; // 地磁気の偏角: 不使用
[nmea0183GPRMC appendString:@","]; // 地磁気の偏角の方向: 不使用
[nmea0183GPRMC appendString:@"A"]; // モード: 単独測位
unichar nmea0183GPRMCChecksum = 0;
for (NSInteger index = 0; index < nmea0183GPRMC.length; index++) {
nmea0183GPRMCChecksum ^= [nmea0183GPRMC characterAtIndex:index];
}
nmea0183GPRMCChecksum &= 0x0ff;
[nmea0183GPRMC insertString:@"$" atIndex:0];
[nmea0183GPRMC appendString:@"*"];
[nmea0183GPRMC appendFormat:@"%02lX", (long)nmea0183GPRMCChecksum]; // チェックサム
// カメラに位置情報を設定します。
NSString *nmea0183 = [NSString stringWithFormat:@"%@\n%@\n", nmea0183GPGGA, nmea0183GPRMC];
return [self setGeolocation:nmea0183 error:error];
}
- (double)convertCLLocationDegreesToNmea:(CLLocationDegrees)degrees {
double degreeSign = ((degrees > 0.0) ? +1 : ((degrees < 0.0) ? -1 : 0));
double degree = ABS(degrees);
double degreeDecimal = floor(degree);
double degreeFraction = degree - degreeDecimal;
double minutes = degreeFraction * 60.0;
double minutesDecimal = floor(minutes);
double minutesFraction = minutes - minutesDecimal;
double seconds = minutesFraction * 60.0;
double nmea = degreeSign * (degreeDecimal * 100.0 + minutesDecimal + seconds / 100.0);
return nmea;
}
@end
よろしくお願いいたします。