CSVで記録されたNXT走行体の走行ログには、各種センサーからの入力値やモーターの動きが数値として連続的に記録されている。
走行体の動きを把握するためにはこのデータの分析が必須だが、市販の表計算ソフトを使って処理しようとするとデータ量が多いので、
1つ1つのファイルを読み込んで描画すると、操作に多大な時間がかかり効率が悪い。
ここでは、スクリプト言語(groovy)とグラフ化ツール(gnuplot)を用いて、効率的にデータを処理する簡単な方法を紹介する。
なお、ここで紹介するスクリプトやデータは、以下のzipファイルにまとめてあるので、必要に応じて参照すること。
DataAnalysisAndDrawGraph20130617.zip
今回は、Cygwin環境下で、javaのjvm上で動作するスクリプト言語groovyを使用するので、その環境を用意する。
以下のURLより、最新版のJDKを入手して、インストールする。
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Cygwinのパッケージ管理ツールを使って以下のパッケージを追加する。
|— Net | |— curl | |— Graphics | |— gnuplot
GVM: Groovy enVironment Managerは、cygwin上で、groovyに必要な環境を自動でインストールしてくれるパッケージマネージャーである。 cygwinから、以下のコマンドを実行してインストールする。
$ curl -s get.gvmtool.net | bash
先ほどインストールしたGVMを初期化するために、以下のコマンドを実行する。
$ .gvm/bin/gvm-init.sh
次に、以下のコマンドを実行してgroovyをインストールする。
$ gvm install groovy
以下は、必要に応じて実行すること。
$ gvm list groovy # 利用可能なバージョンのチェック
$ gvm selfupdate # gvmのバージョンアップ
また、以下のツールは便利なので、必要に応じてインストールするとよい。
$ gvm install grails # Ruby on Railsライクな開発を行えるWebアプリケーションフレームワーク
$ gvm install griffon # Grailsと同様の使い勝手でデスクトップアプリケーションを構築することができるフレームワーク
$ gvm install gradle # Groovyで書かれたビルドシステム
ログデータの読み出し
まず、ログデータを読み出してみる。
使用するログデータは、以下のファイルを使用する。そのサイズは、34375行のデータである。
$ wc 20130613_183553.csv
34375 34385 1841244 20130613_183553.csv
class readLine { static void main(args){ def f = new File(args[0]) // ファイルを開く。 f.eachLine { line -> // 1行づつ読み込む。 println(line) // それを1行づつ表示する。 } } }
$ groovy readLine.groovy 20130613_183553.csv
これは、catコマンドと同じである。
$ cat 20130613_183553.csv
ログデータを行単位で読み出し、要素に分解した後にタブ区切りで表示する。
class readLineSplit { static void main(args){ def f = new File(args[0]) // ファイルを開く。 // ファイルから1行づつ読み込む。 f.eachLine { line -> // カンマを区切りの単位として分割。 def column = line.split(",") column.each { // Tab区切りで表示 print(it + '¥t') } print('¥n') } }
$ groovy readLineSplit.groovy 20130613_183553.csv
1カラム目の時間データと、10カラム目の光センサのデータを情報を取り出し、タブ区切りで出力する。
class readLineSplitSelect { static void main(args){ print("# ") def f = new File(args[0]) // ファイルを開く。 // ファイルから1行づつ読み込む。 f.eachLine { line -> // カンマを区切りとして分割。 def column = line.split(",") // カラム0,9をTab区切りで表示 println(column[0] + "¥t" + column[9]) } } }
最初は、タブ区切りの出力をそのまま表示する。
$ groovy readLineSplitSelect.groovy 20130613_183553.csv
次に、タブ区切りの出力をリダイレクトで、photo.datに保存する。
$ groovy readLineSplitSelect.groovy 20130613_183553.csv > photo.dat
gnuplotを使用して、先ほど作成したphoto.datをグラフ化する。 まず、描画の設定ファイルを用意する。
$ cat photo.plt
set grid # 格子線を描画
set xrange [0:150000] # X軸の描画範囲
set yrange [400:800] # Y軸の描画範囲
plot 'photo.dat' with line # photo.datを読み込み線グラフを描画
set terminal png medium # 画像の出力形式をpngに設定
set output 'photo.png' # 出力ファイル名を設定
replot # グラフ画像をファイルに保存する。
上記の設定ファイルを引数としてgnuplotを実行するとグラフが描画される。
$ gnuplot photo.plt
出力された画像
なお、gnuplotを使ったグラフの詳細な設定方法や応用例などは、以下のURLを参照するとよい。
以下は、10カラム目の光センサのデータを情報を取り出し、最大値、最小値を求めるスクリプトである。
class checkMinMax { static void main(args) { int min = 65536; int max = 0; def f = new File(args[0]) f.eachLine { line -> if ('T' != line.charAt(0)) { def column = line.split(",") int n = Integer.decode(column[9]).intValue() if (min > n ) min = n if ( n > max) max = n println(column[0] + ", " + column[9]) } } println("min:" + min + ", max:" + max) } }
$ groovy checkMinMax.groovy 20130613_150517.csv
0, 619
4, 618
8, 619
.......
.......
137593, 612
137597, 612
137601, 611
min:507, max:712
このスクリプトを拡張していけば、平均値、標準偏差などの算出に応用できるはずである。
各員プログラムの奥義を極め、CS大会に向けて一層奮闘努力せよ!