Raspberry Pi 2 で USB-GPS レシーバーを使ってみた - しばやん雑記 から USB-GPS レシーバーを Raspberry Pi 2 に刺しっぱなしだったので、そろそろ C# から使ってみようかと思いました。
基本的に USB-GPS レシーバーからは NMEA フォーマットでデータが流れてくるので、それを C# からパースするだけで問題なさそうです。データ自体は cat などでレシーバーを開いてみると簡単に確認出来ます。
Windows だと USB デバイスを使うのはちょっとめんどくさい感じありますが、Linux だとファイルとして開いて読み込むだけなので簡単です。
まずは NMEA フォーマットのデータを読み込むだけのコードを書いてみました。
class Program { static void Main(string[] args) { var file = File.OpenRead("/dev/ttyACM0"); using (var reader = new StreamReader(file)) { while (true) { var line = reader.ReadLine(); Console.WriteLine(line); } } } }
StreamReader で 1 行ずつ読み込むだけのシンプルなコードです。
デバイス名は自分の Raspberry Pi 2 では USB-GPS レシーバーが /dev/ttyACM0 として認識されているので、それを決め打ちで読み込むようにしています。
Mono を使って実行してみると、NMEA フォーマットのデータが読み込めていることが分かりますね。
さて、これから実際に位置情報を取得するわけですが、折角なので NMEA フォーマットのパーサーなどを使わずに自前で計算してみたいと思います。フォーマットに関しては簡単に調べました。
NMEA 0183 - Wikipedia
緯度、経度を測る(GPSモジュール使用)
$GPRMC から始まるデータだけ見れば、最低限の緯度経度は取得できるみたいですね。緯度経度の計算部分を参考にしつつコードを書きました。
class Program { static void Main(string[] args) { var file = File.OpenRead("/dev/ttyACM0"); using (var reader = new StreamReader(file)) { while (true) { var line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) { continue; } var values = line.Split(','); if (values[0] != "$GPRMC") { continue; } var latitude = ParsePosition(values[3]); var longitude = ParsePosition(values[5]); Console.WriteLine("{0:f8} {1},{2:f8} {3}", latitude, values[4], longitude, values[6]); } } } static double ParsePosition(string str) { var value = double.Parse(str); var degree = (int)(value / 100); var minute = value - (degree * 100); return degree + (minute / 60); } }
ちょっと冗長な感じになってますが、緯度経度はちゃんと計算できていました。
3G 通信モジュールとモバイルバッテリーを組み合わせれば、位置情報を取得しつつリアルタイムで EventHub に投げて地図にマッピングとか出来そうです。