[IT小話-04] サイトのGPSログのジオイド高修正の話
前回の記事で、WP GPX Mapsでログごとにマップデータの種類を変える方法が分かったので、街中散策のデータをOpen Street Mapで表示させるオプションを付けて更新した。更新後にちゃんと反映されているか確認するために、それぞれページをロードさせてチェックしていた時に、ふとおかしなことに気が付いた。
よく見ると、海岸沿いの平坦地を歩いているログなのに、標高データが30m前後の値を指していて、全体的に実際より高く表示されている。
あれ、と思って他のデータも改めてチェックしてみると、富士山の山頂に到達した時の標高が3819mになっている。今までグラフ表示が登山のデータに限られていて、数字が大きかったせいかあまり気にならなかったようだ。ご存じのとおり富士山の標高は3776mであり、43mも高い値になっている。それ以外のデータも標高値を下回るものはなく、全てが上振れしている感じだ。
まぁ、上振れしているからといって、そこを気にして見る人はほとんどいないと思うので、放っておいても何ら実害はないのだが、何となくすっきりしない。簡単に直せるものなら修正しておきたい。ということで調査開始。
まず、加工中の改変を疑った。掲載しているGPSログは実は生データではない。実際に行動していると休憩などで1ヶ所に留まったり、数メートル程度の範囲を行ったり来たりすることがあるが、そういう時の計測データはばらつきが起こって線がぐちゃぐちゃになるので、それら見栄えが悪くなるデータを間引きして保存したデータを使っている。その作業の最中に何らかの改変が起こってしまったのではないかと思ったのだが、原本の標高データも同じ値だったのでその線は消えた。
GPSデータは複数のGPS衛星によって位置や標高などを計測しているので、実際の位置から多少の誤差が生じるというのは知っているが、位置は合っているのに標高だけずれるというのは何だろうか。スマホ搭載のGPSアンテナの精度の悪さのせいなら、あれこれ悪あがきしてもしょうがない気がするが、何か原因となることがあるかもしれないと思い、ネットで調べてみる。だが「GPS 標高 ずれ」などのキーワードで調べてみたが、ピンとくる情報は得られなかった。
原因が分からないのはすっきりしないが、データが全体的に3~40m上振れしていることは分かっている。ならばデータから一括でそのくらいの数値を引けばいいのだろうと考え、次にアプリの機能を調べてみた。
現在GPSデータのチェックや加工はカシミール3Dというアプリを使っている。あれこれ調べていくと「標高の変換」というメニューを見つけた。これだ。

ところが、これは地図上の標高値に対していくらか増減させた値で一括更新をかけるか、全ての値を指定した値で一括で書き換える機能しかなく、各ポイントのデータから一括で増減させるための機能ではないようだ。
アプリ上では修正できなさそうなので、次にデータのCSVエクスポートができないか調べてみた。エクスポートさせて、EXCELかなんかで修正してまたインポートすれば、まぁひと手間ではあるが許容範囲だ。だが、CSVエクスポートの機能もないっぽい。
他のフリーウェアなども探してみたが、標高値を書き換えたり、CSVに変換してくたりするようなソフトも見つからない。こんな要望ないのだろうか?
こまった、こりゃ意外と手ごわい。データがいじれないとなると手も足も出ない・・・。
何でもいいからヒントが得られないかとさらに調べると「ジオイド高」というキーワードに目に留まった。
細かい説明は本家を参照願いたいのだが、GPSの高度測定は、地球を仮想的な楕円の球体(地球楕円体)に見立てて、測位衛星からその地球楕円体までの距離と、計測で得られた実測値との差分によって標高を導き出しているらしい。一方、日本の標高データは測量法という法律に基づき、標高は平均海水面からの高さと定められている。
平均海水面の高さはそのまま地中にも適用されるのだが、地球の中身は様々な物質で組成されているため、場所により重力が変わる。水が高い所から低い所へ流れるのは重力のためだが、その重力が場所によってまちまちなので、ことと次第によっては、(見た目上)低い所から高い所へ水が流れる可能性もある。まぁ、それは極端な話だが、平たいところを流れる水流がどちらへ向かって流れていくか、といったような場面では影響を無視できないらしく、平均海水面の値からさらにその場所の重力による差分を補正して標高を決めているらしい。
この補正を反映した地中の平均海水面の高さをジオイド高というそうだ。要は、地理院地図に記載されている標高はジオイド高を反映した値なので、GPSによって計測された標高データとは差分がありますよということだ。
で、その差分が日本国内では概ね30m~40m程度らしい。それだ!
だから30mくらい数値がずれていたのか・・・。スマホのせいにしてごめんな。
それが分かればやることはひとつ、現在の標高データからジオイド高を引けばいいわけだ。国土地理院のサイト上に指定された地点のジオイド高を表示させてくれるアプレットがある。これは地点データをアプレットにインポートすると、その地点のジオイド高情報をエクスポートしてくれるものだ。
そのインポートさせるデータだが、説明によれば、緯度と経度のDMS形式データを作って、拡張子.inで保存し、アプレットにインポートするそうだ・・・って、DMS形式ってなんだ?
いやまて。そもそもGPSデータをエクスポートする方法がまだ分かっていないではないか。それが分からなければ、ジオイド高云々も絵に描いた餅だ。CSVエクスポートができないというのなら、他の保存形式でDMS形式になっているものを見つければ良い。カシミール3Dで選べる保存形式をひとつひとつ選んで保存して、そのデータを覗いてみることにした。

エクスポートした各種データをテキストエディタで開いてみると、trk形式のデータがスペース区切りになっていた。これなら使えるかな・・・。
ただ、表示されているデータがどういう規則で書かれているものなのかが分からなかった。というのもカシミール3Dのトラックデータ編集画面に出てくる数値とエクスポートしたデータの数値が合っていないのである。例えば、カシミール3Dのデータは、緯度に「N 35°17’07.64」、経度に「E 136°33’11.44」と表示されているのだが、同じデータのtrkファイルを見ると、緯度が「N35.2854560」、経度が「E136.5531780」となっている。これはどういうことだろう?
またまたGoogleセンセに質問してみたら、緯度経度の表示方法として複数の種類があることが分かった。カシミール3D画面上の「N 31°48’19.43」という表記がDMS形式というそうだ。「北緯31度48分19秒43」ということだ。対してエクスポートした方のデータはDEG形式といい、単純に緯度経度を度数で表現したものだそうだ。

そういえば、DMSとDEGって保存画面の中で選べたな。ということで、DMSを選んで保存したら、ちゃんとDMS形式のスペース区切りデータを取り出すことができた。

これのヘッダー部を除いた実データ部分をコピーして、EXCELに貼り付けて、[データ]-[区切り位置]でスペース区切りで区切ってやる。

次に区切ったデータから緯度、経度のデータが記載されているセル(B,C列)のみをコピーしてテキストエディタに貼り付けて、.inの拡張子を付けて保存。やっとデータが作れたー。

そのあと、作ったデータをジオイド高計算ツールに食わせて計算実行すると、ほどなく元データにジオイド高が追加されたデータが.outの形式で吐き出された。

テキストエディタで開いてみたら、元のデータの右側にジオイド高の値が小数点第4桁までの値で追記されていた。

そこで今度は、そのデータを再びEXCELの元データの隣の列(I列)に貼り付けて、同様に区切り位置で区切る。すると元のデータとエクスポートした同地点のジオイド高が紐づく。小数点以下の値はWebやカシミール3Dで表現できないし、そもそも元データに計測誤差が含まれるので、補正しても実際の値との誤差は出てしまう。なのでそこは厳密な値を求めてもしょうがない。INT関数を使って整数部分のデータだけ利用することにした(M列)。その値を引き算で引いた値が、実際の値に近い標高となるわけである(N列)。
公開しているすべてのGPSログデータのジオイド高を抽出したら、やっぱり全体的に35~40m程度のジオイド高があり、それを差し引いてみたら、概ね実際の標高データに近い数値を求めることができた。ただし海岸沿いの散策など、全体的に標高が低いデータだと、もとの計測データが標高20m以下で記録されていることがあり、ジオイド高を引くと海抜がマイナスになりがちである。
スマホの精度の問題なのか、GPS計測上のクセなのか、海岸付近のジオイド高が実際より過剰なのか、その辺は良く分からなかったが、マイナスデータが続くとグラフ上気分が悪いので、更にいくらかの補正をして概ね0m以上になるように修正した(O列)。補正値はデータを見ながら適当に決めた。まぁ、この辺りは蛇足である。
といっても、単純に補正値を入れただけなので、街中から山に登るようなデータだと、どちらかが不自然な値になってしまう。この辺は追求してもキリがなさそうだったので、あまり深追いしないことにした。まぁ、元が正しくないデータに何をやっても正しいデータにはならないので、気分的な折り合いが付けば良しである。

ジオイド高を考慮した標高データに修正した後、元のデータ部分の標高値を、計算によって求められた値で上書き(O列の値をF列にコピー)して、A列からF列までをCSVで保存する。

trkファイルはスペース区切りデータなのだが、EXCELから直接スペース区切りで出力する方法がないので、一旦CSVでエクスポートして、それをテキストエディタで開き、置換を使って","を" (半角スペース)"に置換した。
更に元のtrkファイルのヘッダー部分をコピーして、CSVデータの先頭に貼り付けて保存(逆に元のtrkファイル側のデータ部を差し替えても良いかもしれない)。
最後に、拡張子csvをtrkに変更。これをカシミール3Dで開いて、そのままGPX形式で保存したら作業完了である。もちろん最後にWebサーバー上に転送させるのも忘れずに。
手数が多いので、マクロやバッチファイルなどを作成してもよかったのだが、それぞれのステップで都度データがどのように更新されているか確認しながら進めたかったのもあって、最後までステップバイステップでやった結果、そこそこ時間がかかった。ファイル数がせいぜい100個くらいだったので何とかなったが、数百といったレベルだったら自動化しないと心が折れる・・・というか、今後アップロードの度にこれをやるべきかどうか悩みどころである・・・。
さて、最後にもうひとつ。
GPSログを貼り付けた記事をブラウザで表示させると、ログが貼られているところに下記のエラーが出る。

何故か初回だけ表示され、ブラウザをリロードさせればエラーは出なくなり、それ以降は表示されないという、Internal Server Errorに匹敵する悩ましいエラーなのだが、こちらも調べてみて原因が分かった。
エラーメッセージを見ると、GPXデータの中に読めないタグが設定されているよと書かれている。

GPXファイルをテキストエディタで開いたら、該当のパラメータが記載されたタグがヘッダー部分にあったのでそこをまるっと削除。これでエラーが出なくなった。
ただしカシミール3Dで開いて上書き保存すると、このセクションが復活してしまう。上記のジオイド高反映作業と一緒にこれも毎度やらなければならないということか。考えただけでやや憂鬱である・・・。