9936


自作アプリにてスマホの現在地をカメラ(OLYMPUS
AIR)にOLYCameraの`setGeolocation:error:`を使って設定しようとしています。

カメラSDKの[APIリファレンス](https://opc.olympus-
imaging.com/sdkdocs/data/apirefiOS/category_o_l_y_camera_07_camera_system_08.html#a6aa602aa95ed563e6b3db5811263c213)によるとメソッド引数の位置情報はNMEA0183形式の文字列で指定しなければなりません。iOSでの現在地はCLLocationで表されるため、引数値にするにはこの形式の文字列に変換する必要があります。

CLLocationインスタンスをNMEA0183形式の文字列に試行錯誤して変換してみましたが、意図した座標からなぜか数百メートル南にずれたりするなどして、OA.ModeDialのように現在地を的確な精度の緯度経度で写真のタグに設定できませんでした。

NMEA0183のGPGGAセンテンスとGPRMCセンテンスには沢山のフィールドがありますが、CLLocationインスタンスをどのようにこれらのフィールドに設定すると良いのでしょうか?  
教えてください。

## 追加情報

試行錯誤している作成中のソースコードは以下のようなものです。

[code]

    @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
    
[/code]

よろしくお願いいたします。


CC BY-SA 3.0
2015-05-05T09:06:06.287
9838
2016-03-22T13:25:12.467
2015-05-07T10:24:22.870
7283
7283
question
ios objective-c olympus-camerakit gps
OLYMPUS AIRにスマホの現在地を設定する方法


OPCサポートです。  
コードを確認させていただきました。2点問題がございます。

  1. GPRMCレコードでステータスと測位時刻の順番が逆です。
  2. 緯度経度変換（10進数から60進数）で秒の変換は不要です。（下記コード参照願います。）
[code]     - (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 nmea = degreeSign * (degreeDecimal * 100.0 + minutes);
        return nmea;
    }
    
[/code]

以上ご確認いただけますか。よろしくお願いします。


CC BY-SA 3.0
2015-05-08T04:36:09.673
9936
2015-05-11T06:48:02.783
2015-05-11T06:48:02.783
8370
8370
9838
answer


I can't comment with my Japanese account, I just want to point out that

GPRMC is bad formed, it should starts with the timestamp not 'A'

[code]

    [nmea0183GPRMC appendString:@"GPRMC,"];
    [nmea0183GPRMC appendFormat:@"%@,", [nmea0183GPRMCTimestampFormatter stringFromDate:location.timestamp]]; // 測位時刻
    [nmea0183GPRMC appendString:@"A,"]; // ステータス: 有効
    
[/code]

<http://www.gpsinformation.org/dale/nmea.htm#RMC>


CC BY-SA 3.0
2016-03-22T13:25:12.467
23352
2016-03-22T13:25:12.467
14895
9838
answer