GPXデータをスリムにする 4月23日, 2012


GPSロガーないしは、サイコンの話です。gpxデータのポイント数が多い場合、例えばルートラボなどにインポートしようとすると8,000ポイントの制限を越えてしまって、保存することができませんよね。以下は、それを削ることに関して、自分ではこうするということを簡単にまとめたものです。Lionのシステム既存のrubyで処理しています。環境が変ればこのままではうまくいかないかもしれません。例によって、自分の目の前で必要な処理ができればよい、というスタンスで考えたものですが、同じような環境の方なら多分同じ動きをするはずです。

今、試しにgpxのファイルをエディターで開いてみると、それが単純なXMLファイルであることがわかります。各ポイントデータは<trkpt>と</trkpt>のタグで囲まれ、その下位の<time>タグにUTCで表現された時間データが記録されています。試しにのぞいたものは、4秒毎にデータを取得していて毎分15ポイント。走行時間が10時間の遠出ではデータが9,000ポイントにもなります。ここはひとつ思い切って毎分1ポイントにスリム化してしまいましょう。

スクリプトではREXMLライブラリを使用して、分毎の重複するエレメントを削除しています。ごく短い純朴なもので、かなり遅いのですが、ちゃんと処理してくれます。手元のデータをスリム化した例では、10,000ポイントを少し越えるものを1,000ポイント以下まで削ってくれました。ここまで削る必要はありませんが、まあ今時スリムにこしたことはないでしょう。遅さは驚く程です。3〜4分はかかるのを覚悟して動かします。そう頻繁に使うものではないし、短時間で簡単に書けるスクリプトの方がありがたいといういつもの発想です。

point_reducer.rbのfile_nameに編集対象ファイル名を指定した上で、
$ ./point_reducer.rb | sed '/^ *$/d' > OUT.gpx

delete_elementした結果の空白行をsedを通して削っています。簡単なのがなにより。結果はOUT.gpxにリダイレクトしています。

上記をまとめたあと、思いたってperlでも挑戦してみた。XMLモジュールは用いずに、高校生のように素朴にパターンマッチで処理した。別にperlに慣れているわけでもないのでね。上記と同様に毎分1ポイントにスリム化し、Rubyの動作確認に使用したのと同一の10,000ポイントを越えるデータを処理してみたところ、処理に要した時間は驚きのもの。timeコマンドの出力で0m0.093s。あまりに速いので、気づかない手抜かりでもしているのではないかと心配で、Rubyでやったものと比較してみると、Byte数・行数は同一。これで安心と思いつつも、念押しのdiff。無論同一となるとの予想に反し行数と同じくらいの数のズレを指摘された。いやあ、ミスしたかなとソースと目で比べてみると意外や意外。RubyのREXMLライブラリーを使用したものは、属性の配列順序がソースと異なるのだ。何か指定しなければいけなかったかなあ、ライブラリー内部ではハッシュが返す値を用いて再構成しているのかな、複雑なことをやっているのだろうなあなどと思いつつ、中心としていたtrkpt要素については全く影響がないことなのでいいことにした。今後はperlの方を使おう。

$ ./reduce_point.pl GPX.gpx > REDUCED.gpx

GPX.gpxがソースファイル名、REDUCED.gpxが出力先ファイル名。

[追記 2012-08-14]: 上記perlスクリプトについて、timeタグのフォーマットが異なるロガーがあることに気づいたので、16行目の正規表現に手を加えた。