先週2月15日にスキー場で測定したデータ、とりあえず要用の部分だけは、EXCEL手作業で求めてみて、結果オーライだったので、次に、手作業で2-3時間かかっていたデータの欠陥修理をプログラム化することで10万行のデータを数秒で補修することができました。RTKの生データは、必ずなんらかの欠陥を含んでログされるので、補修作業が大変面倒です。
目的は、滑ったら即グラフをみて、自分の今したターンがどうだったのか、見られるようにするためです。急いで作らないと雪が解けてしまうのですが、いかんせん、プログラムがへたくそで
試行錯誤しているうちに1週間かかって、ようやくデータの修正、補正してグラフ用に整頓する
プログラムまで作りました。この調子だと2月末までになんとかその場でグラフがみられるプログラムを作って、左足のシステムが3月第一週にずれこむかもしれません。
●ログの内容
RTK23では、2重にログをとってます。①マイコンSDカード保存 ②モニター用BlueToothSPPでWIN10タブレット保存
①SDログ:1つは、マイコンのSDカードにバイナリーデータ保存します。周期120msecで、F9P2個分のNAV-PVT+RELPOSNED(172Byte*2=344Byte)+M9N3周期 PVT(100Byte*3=300Byte)、BNO055のQuartenionとEuler角3周期(36Byte*3=108Byte)合計752Byteが120msec周期でSDカードにバイナリーログしてます。バイナリーエディターでSDログしたデータを確認。黒い部分がf9P1個分のNAV-PVTとNAV-RELPOSENED 172Byteです。
②モニターログ:BlueTooth経由でWIN10タブレットでログします。リアルタイムでシステムの状態を把握するためのデータ群でASCIIで送信されるので、サイズはばらつきますが、文字数で230Byte前後になります。ヘッダに[m:],[s],[p][Base][Rover]{BNO]と種類が区別がつくようになってます。内容は下記で、モニターログだけで、主要な結果が得られるようになってます。今回はM9N測定は省いてます。次回左足システムで実施します。
同期は、tp0がF9Pのタイムパルスの割り込み時刻なのでそれ基準でtpがBNOサンプリング時刻
itowB,itowRで、GPSデータの時刻も同期してます。
[md], flagsB, flagsR, pdopB, pdopR, haccB, haccR, miscount0, count_upB,count_upB0,tp,tp0,
[Base],itowB, NYB, EXB, DZB, gSpeedB, headMotBZ, [Rover] ,itowR,NYR,EXR,DZR,gSpeedR,mHead,bnHosei+eX[0],relLm], [BNO],yaw1,pitch1,roll1,yaw2,pitch2,roll2,yaw3,pitch3,roll3,,, |
モニターデータは、Doubleで処理します。+文字は、SDにデータを書き込んだ時に発生するので
確実にSD書き込みされた証拠になります。モニター側で[s]指令を送ってもマイコンが確実に動作しているかをモニターで確認するためのものです。
+[s],67,67,131.00,145.00,46,95,35,10745,8027,1558622,1558542 [Base],273303960,959.93,-4972.96,48.40,118,17090886, [Rover],273303960,840.50,-4939.97,46.83,40,164.56,314.15,123.9 [BNO],158.5,-6.7,-78.7,158.3,-6.8,-78.7,158.6,-6.6,-78.8, +[s],67,67,131.00,145.00,45,92,35,10746,8028,1558742,1558542 [Base],273304080,961.54,-4973.18,48.21,71,7753443, [Rover],273304080,841.75,-4941.12,48.17,64,165.02,313.71,124.0 [BNO],158.0,-7.1,-78.5,158.0,-7.1,-78.5,158.0,-7.1,-78.6, |
今回は、モニターログの処理についての課題とプログラミングを大変だったので、
備忘録しておきます。ASCIIだと見やすいけど、逆に手間取ります。
●RTK生ログデータでみられるエラー
エラー1:欠落してデータ順が狂って、あるべき場所にあるべき数値がない。
=>数値と文字が混在して送ってきているので、数値が文字になってしまってエラーになる。
(Digit Errorと呼んでます)
エラー2:データ空っぽで、NUllになっている (Null Errorと呼んでいる)
エラー3:1周期抜けてしまう (itow Errorと呼んでいる)
●原因
エラー1,エラー2=>BlueTooth無線の遅延で、データが尻切れになって次のデータと混じってしまい
順序がバラバラになった状態で発生します。頻度は、非常に少ないですが、40分測定していると3回くらい発生してます。率で言えば、0.02%程度ですが、プログラム上では、エラーになるので、完全に排除して、穴埋めしないといけないので、このためのプログラムが手間です。無線の場合、距離とデータ量が増えるほど、どんどんロス率が悪化していきますので、無線ログだけでは、データ失うリスクがあります。私の場合は、SDカードにログしてあるので
後から、F9PのBinaryデータを再現できるようにしてあります。
エラー3=>F9Pの周期が変動して、遅延した場合にマイコン側のバッファと同期がとれなくて
一瞬の差で1周期が落ちてログされてしまう現象です。これは、マイコン側のプログラムとハードの性能が効いてきます。M5Atomで実測ログした場合数%抜けましたが、Teensy4.1で実測すると0.55%以下に収まってましたので、未だ悪いですが、使えないほど悪くはありません。
●プログラム備忘録
BlueTooth SPPの受信は、WINDOWS10が自動的にやってくれて、Teratermなどの既成のアプリで安全にログできるので、そのログしたCSVファイルを読み込むプログラムを作ってます。
自作プログラムもシリアル受信機能もついているのですが、マルチタスクが安定動作しなくて、信頼性が劣るので、当面は、TeraTermで受信ログすることにしてます。
コードはGISTにあります。
https://gist.github.com/dj1711572002/4747e1022893534ed4050e2f21a0160d
ファイル読み込み | void readDialog() ASCIIとBinaryの選択ができる、Binaryは後日作る モニターデータから実際SDにログしたデータヘッダーに+[s]マークがついているデータ +[s]行、[Base]行、[Rover]行、[BNO]行の4行が1周期 を抽出してDataGridView(dgv)に入力していく。 dgvに入力終えてから、エラーチェックするreadlineでファイルを読み込むと6MBで30秒もかかるので、rFile.ReadAllText(ofd.FileName, System.Text.Encoding.GetEncoding(“Shift_JIS”)); を使うと1秒以内で6MBデータを読み込めるが、 1個のSTRINGに全データ入っているので、後から 行抽出してからCRLFを削除する作業が必要。 CRLFが曲者で、1行にCRLFが何個もはいっている場合があるので、1回目のSPLITは、ヘッダーの”[“で切取って string[] sline = alldata.Split(‘[‘); 2回目のSPLITで string [] tsline = sline[ic].Split(“\r\n”);//行内に複数ある\r\nと余計なコメントを除去 sline[ic] = tsline[0];//再度sline[]に代入 で、正味のデータを抽出している。 |
DGVのデータ修復整頓 | void sortdgv() ①全行のセルの値でNullがあったら、”0″文字に置き換え ②Heading角度変換 (headMotとHeading角が180度方向が違うのを変換)③測定のブロック検出 ログは、1つのファイルに測定モニター操作データも詰まっているので、SDログされたデータを抽出して、連続測定されている範囲を測定モードsmodeとして範囲を検出 void smodesearch()④セルの文字が数値になっているかチェック Try parseを使って文字が数値かエラーか判定⑤itowが120msec周期になっているかチェックして 抜けていたら、補間して抜けたデータの穴埋めをする。 void rinsert()で補間、穴埋め処理⑥穴埋めでDGVの行数が増えてしまっているので、再度 smodeserch()を実行し実際のDGVと行データを合わせて 最終結果として、データ欠落%を計算する。⑦結果として、sortdgvで検出補間したデータの記録を 構造体 struct dgvchkに補間 |
■itow抜け 補間 挿入
今回のファイルは、6MBで10万行のデータをまとめて22000行にして
3つのブロックになっていてそれぞれの抜け率が0.5-0.37%
●データチェック構造体
struct dgvchk
{
public int maxrow;//Row.Count
public int startrow;//
public int endrow;//
public int maxrn;//data エポック数
public int startrn;//有効スタートrn
public int endrn;//有効エンドrn
public int miss;//itow飛び個数
public double missper;//miss%
public int[] fmiss;//smode[]範囲内でのflag 67未満の個数
public double[] fmissper;//fmiss%
// mode
public int[] smode_startNo;//=new int[10];//s] modeの開始番号 配列
public int[] smode_endNo;//=new int[10];//s] modeの終了番号 配列
public int smodeN;//測定ファイル内のsmode範囲の個数
// digit error
public string [,] digit_err;//itow+err.string
public int[] digit_errN;//[smodeN]
//itow error
public string[,] itow_error;// 足りないitow.Tostring()
public int[] itow_errN;//[smodeN]
public double[] itow_errper;//% err
};