DriftBoxのバイナリデータを読み解いた#2

この記事の内容

  • (前の記事で紹介)VSCodeのHexEditorを利用したバイナリデータの概要把握
  • (この記事で紹介)MATLABでバイナリデータからtable形式への変換

MATLABを使ったデータの読みこみ

①ヘッダー部分の読み込み

前記事に書いた、VSCodeのHexEditorで確認すると改行を示す「0D 0A」がいくつか並んでいる。

そこで読み込みにはMATLABのfgetlを用いて1行ずつ読み込んでいき、ヘッダー部分の行数分で終了するプログラムを書いた。下記のように少し工夫することでtableのヘッダー風に読み込むことができた。


clear all; clc;
filename = 'DBOX_004.DBN';

%% バイナリファイルオープン
fid = fopen(filename,'r');

% ヘッダー部分読み込み
m = 1;n = 1;
for i = 1:40
    a = fgetl(fid);    
    if isempty(a) == 1
        m = m+1;
        n = 1;
    else
        n = n+1;
    end
    A{m,n} = a;
end

Aという変数はセル配列になり、中身このようになる。

これで、ヘッダー部分を読み込むことができたようだ。

②数値データ部分の読み込み

ヘッダーに書いてあるSAT(1)という表記だが、SATは受信している衛星の数という意味で、()内は数値データのByte数を示していると想定している。衛星は1Byte,時間は3Byte,,,というように一回の記録で何Byte分あるのか確かめてみると、36Byteあるようだ。

データの形は既に想定できているので、MATLABのfreadを使って数値データの部分をいっきに読み込み、後から形を整えるようにプログラムしてみた。

freadで読み込み、reshapeで整え、衛生が受信できていない不要なデータ行を削除後、各データのByte数分を16進数の形で取り出す。その後、10進数に戻して必要な乗数を掛けている。この辺りの処理は冗長な感じが否めないので、この道のプロならおそらくもっといい方法を知っているのではないかと想像する。

kurario-tec
kurario-tec

必要な乗数はどこにも書いてなかったので、WindowsPCを借りて標準解析ツールより出力したCSVデータと見比べることで確かめました。本末転倒感。笑


num_byte = 36;
% データ部分読み込み
B = uint8(fread(fid));
% ベクトルを行列に変換 
nd  = length(B);
num_data = length(B)/num_byte;
C = reshape(B,[num_byte,num_data])';
% 衛星を受信できてないデータ行の取得
idx_nonGPS = C(:,2) = 1 | C(:,2) >= 15;
% tableに変換
D = array2table(C);
% 衛星を受信できてないデータの削除
D(idx_nonGPS,:) = [];
% 16進数で必要なバイト数分選択
time =      hex2dec([dec2hex(D.C3),dec2hex(D.C3),dec2hex(D.C3)])*10;
lat =       [dec2hex(D.C6),dec2hex(D.C7),dec2hex(D.C8),dec2hex(D.C9)];
lon =       [dec2hex(D.C10),dec2hex(D.C11),dec2hex(D.C12),dec2hex(D.C13)];
vel =       [dec2hex(D.C14),dec2hex(D.C15),dec2hex(D.C16)];
heading =   [dec2hex(D.C17),dec2hex(D.C18)];
height =    [dec2hex(D.C19),dec2hex(D.C20),dec2hex(D.C21),dec2hex(D.C22)];
vert_sp =   [dec2hex(D.C23),dec2hex(D.C24)];
yaw_1 =     [dec2hex(D.C25),dec2hex(D.C26)];
yaw_2 =     [dec2hex(D.C27),dec2hex(D.C28)];
yaw_calc =  [dec2hex(D.C29),dec2hex(D.C30)];
slip =      [dec2hex(D.C31),dec2hex(D.C32)];
checksum =  [dec2hex(D.C33),dec2hex(D.C34)];
% 10進数への変換と、データへの単位変換
E.sat =         D.C2;
E.time =        duration(milliseconds(time)+hours(9),'Format','hh:mm:ss.SSS');
E.lat_10 =      hex2dec(lat)/60*10^-5;
E.lon_10 =      hex2dec(lon)/60*10^-5;
E.vel_kmph =    hex2dec(vel)*10^-2;
E.heading_deg = hex2dec(heading)*10^-2;
E.height_m =    hex2dec(height)*10^-2;
E.vert_sp_mps = hex2dec(int16(vert_sp))*10^-2;
E.vert_sp_mps(E.vert_sp_mps > 600) = E.vert_sp_mps(E.vert_sp_mps > 600,:) - 655.35;
E.vert_sp_mps = E.vert_sp_mps*3.6;
E.yaw_2_degps = hex2dec(yaw_1)*10^-2;
E.yaw_1_degps = hex2dec(yaw_2)*10^-2;
E.yaw_calc =    hex2dec(yaw_calc)*10^-2;
E.slip_deg =    hex2dec(slip);
E.checksum =    hex2dec(checksum);
% tableへ変換
E = struct2table(E);

以上、DriftBoxのバイナリデータを読み解けた。

MATLABのgeoscatterを使って走行軌跡を確認すると、しっかり当時走行した場所を示していた。これで自分のMacBookAirでもDriftBoxのデータを解析できるようになった。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です