仕事で地図アプリを触る機会があった。
内容は既存システムの機器リプレースで、外付けの単体GPSモジュールから「ワイヤレスWANモジュール内蔵GPS」というものに変更になる。
内蔵モジュール名は「Sierra Wireless Snapdragon X7 LTE-A NMEA Port」というもの。
上記の検証として、機器を入れ替えても現在地が正しく取れるよね、という確認。
「ただのリプレースだから~」と言われても、いざ実施して問題が出ない方が珍しい。
今回も例に漏れず問題は起きた。
事象としては、現在地が約50キロずれるという、地図アプリとしては致命的なバグ。
早速原因を探ってみた。
まずGPSの受信には、NMEA 0183というプロトコルが使用されていて、
当アプリではその中の「GMC」というセンテンスから現在地を取得している。
$GPRMC,023301.0,A,3624.902708,N,14030.742828,E,0.0,0.0,290920,5.2,W,A*1D
先頭2文字は下記の衛星システムからの受信を意味する。
4番目が緯度:3624.902708
6番目が経度:14030.742828
というわけだ。
プログラムを見ると、受信した度数・分数の文字列から度数に変換する際に、下記のような取り方をしていた。
WEB上でNMEAのフォーマットを見ると、座標の形式は「ddmm.mmmm」という表記が多かった。この表記通りの桁数なら上記の処理でうまくいく。しかし、実際のこの機器は「ddmm.mmmmmm」で受信している。右から7桁目から取るとしているせいで、最初のmmが取れていないわけだ。
RMCのフォーマットについてはググればいっぱい出るが、
緯度・経度の桁数について記載されている情報はなかなか見つけられなかった。
が、見つけた。
緯度の値は2桁の固定桁です
度、2つの固定桁の分、および可変数の
分数の小数の数字
度は固定桁、分は可変桁のようだ。
これは経度も同様だ。
今回の現在地がずれる件は、受信した座標がそもそも誤っているのか、座標の表示処理が誤っているのかの2択となるが、NMEAの受信した座標をGoogle MAPで入力すれば原因の切り分けは可能だ。
Google Mapでの確認手順を下記に記載する。
まず、GPRMCフォーマットから緯度・経度を抜く。
緯度:3624.902708
経度:14030.742828
上記の値を、度と分の間に空白を入れてカンマで繋ぐ。
するとこうなる。
36 24.902708, 140 30.742828
これをGoogleMAPの検索窓に入れればOK。
こちらは、度・分の形式から度に変換して検索する方法。
こちらもGPRMCフォーマットから緯度・経度を抜く。
緯度:3624.902708
経度:14030.742828
上記から度数に変換するには、緯度・経度それぞれ度数 + (分数 / 60)で出せる。
36 + (24.902708 / 60) = 36.4150…….(略)
140 + (30.742828 / 60) = 140.5123…….(略)
上記の値を、カンマで繋ぐ。
するとこうなる。
36.4150, 140.5123
これをGoogleMAPの検索窓に入れればOK。
Google MAPではもう1つ、「度分秒(DMS)」による検索もできるが、この形式にする方が面倒だったので未実施。