m-241のバイナリデータからトラックログを吸い出す
GPSロガー(Holux m-241)のメモリが破損しているのか、 実は6月30日と7月3日の軽井沢→直江津ツーリングと、9月の西九州→佐多岬ツーリングでは、 ログが破損していたため、Googleのロケーション履歴を代用している。
バイナリデータは一応吸い出せているようなので、その構造を調べると、 HOLUX m-241 LoggerUtility .trlファイル構造の覚書 より以下のような構造になっている。
- 1レコード20バイトの固定長
- 時刻4バイト
- 緯度4バイト
- 経度4バイト
- 高度3バイト
- 速度4バイト
- チェックサム1バイト
また、m-241は時折書き込み先のメモリアドレスがずれることがあるようだ、との情報も見つかったため、 バイナリエディタで除いてみると、どうも4バイトずつずれて記録されたデータがあるようだった。
そこで
- レコードの先頭バイトを4バイトずつオフセットさせて読み込んでみる
- 緯度と経度が日本付近のものと思われるものを片っ端から拾う
- 時刻は整数型なのでとりあえず読み込む
- 高度、速度のデータは無視!
という方針でMathematicaのプログラムを書いてみた。
data = Table[Module[{str, ret},
str = OpenRead["2016091200.bin", BinaryFormat -> True];
(* 最初に余分にiバイト読み込んで先頭をずらす *)
Do[
BinaryRead[str, "Byte"],
{i}
];
(* バイナリ形式で読み込む *)
ret = Cases[
MapIndexed[
{First[#2], Sequence @@ #1} &,
BinaryReadList[
str, {"Integer32", "Real32", "Real32", "Byte", "Byte", "Byte", "Real32", "Byte"}]
],
{count_, d_Integer, lat_Real, lon_Real, __} /; (30 < lat < 40 && 125 < lon < 140) :>
{count, DateString[DatePlus[{1970, 1, 1, 0, 0, 0}, {d, "Second"}], {"Year", "-", "Month", "-", "Day", "T", "Time", "Z"}], lat, lon}];
Close[str];
ret
],
{i, 0, 19, 4}];
※ 2016091200.binというのがバイナリ形式のm-241ログファイル名。もとのデータ順を保存するように、MapIndexedを使用している。日本付近、というのは今回は緯度が30度から40度、経度が125度から140度とした。
読み込めた点数は下記の通り。
In[2]:= Length /@ data
Out[2]= {13083, 9326, 5019, 7715, 9721}
本来は「HOLUXGR241LOGGER」という文字列がレコード開始位置の基準になっているのを無視すると、 ずれを起こしていないログが13083点、4バイトずれて記録されたのが9326点、8バイトずれて記録されたのが5019点・・・という結果となった。
あとはこれをGPXファイルとして出力する。
data2 = Sort[Flatten[data, 1]];
str = OpenWrite["20160912_rescue.gpx"];
WriteString[str,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>
<gpx
version=\"1.1\"
creator=\"330k.info\"
xmlns=\"http://www.topografix.com/GPX/1/1\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">
<trk>
<name>20160912</name>
<number>0</number>
<trkseg>"];
WriteString[str,
ToString@
StringForm[
"<trkpt lat=\"``\" lon=\"``\"><time>``</time></trkpt>\n",
NumberForm[#[[3]], 10], NumberForm[#[[4]], 10], #[[2]]
]
] & /@ data2;
WriteString[str, "</trkseg></trk></gpx>"];
Close[str]
GPSBabelを使用してGPXファイルに変換した場合と比べて、どの程度のログを救出できたか調べた。
日程 | 2016年6月30日→2016年7月3日 | 2016年9月6日→2016年9月11日 |
---|---|---|
経路 | 東京→軽井沢→直江津 | 小倉→長崎→佐多岬 |
トラックポイント数(GPSBabel) | 4039 | 19482 ※ 異常な点を手作業で削除 |
トラックポイント数(上記プログラム) | 12442 | 24869 ※ 異常な点を手作業で削除 |
地図 |
赤線 : GPSBabelで変換したログ 青線 : 今回のプログラムで救出したログ
結果としては、東京→軽井沢→直江津は全部救出でき、 小倉→長崎→鹿児島間では
- 3日目の福岡県柳川市付近
- 4日目の熊本県宇城市→鹿児島県霧島市
- 5日目の鹿児島県垂水市→南大隅町
のトラックポイントを合計5387点を救出できた。
福岡県糸島市→長崎県松浦市、福岡県柳川市→熊本県宇城市の区間はどうしようもなかった。
CATEYE製サイコンも3日目と4日目にトラブルを起こしているので、 今後はm-241の使用をとりやめ、Garminを購入する予定。