python でblfデータ(バイナリ)を読み取り方のサンプルと丁寧な解説です
簡単に関数化しdataframeや、csvにする方法をご紹介します。コピペで出来ます
MATLABと異なりライセンス不要となるので、無料で実施できるのも良い点です。
本日の伝えたいこと
✔ pythonでblfデータを扱うときは、cantoolsとcanモジュールを使う
困ったこと
pythonでCANデータの解析をしたいが、blfデータの読み込み方が分からない
内容
cantoolsとcanモジュールを使いバイナリデータを読み込む
※timestamp情報の取り扱いに注意点があるので最後まで読んでほしい
メリット
blfデータをpandasのdataframe化できるため、解析やcsv化が自由にできるようになり
効率的にblfデータを扱うことができるようになる
解決方法
pythonでCANを使う事前準備
cantoolsとcanのinstallが必要となるため、下記pipコマンドにてインストール
>>pip install cantools
>>pip install python-can
使い方
cantoolsによりdbcの指定
下記書式でインポートできる
以降は、loadしたdbcの変数名やCAN_IDに応じた処理をすることになる
dbc_can = cantools.database.load_file(‘../xxx.dbc’)
can.ioによりblfデータをインスタンス化して読み込み
下記が、blfファイルをインスタンスとして読み込んでいる部分になる
読み取り後はfor文でひたすら回すことでタイムスタンプが若い順に
受信データが出力される
blfdata = can.io.blf.BLFReader(fname)
for文で、CAN受信タイミングに合わせて変数を抜き出す
messageデータには、idアクセスが可能となるため、
特定のidの時にはif文で処理して値をピックアップするようにする
if (msg.arbitration_id == int(“100”, 16)):
ピックアップしたデータへのアクセスはかなり簡単だ。
①インポートしたdbcファイルを使ってidをメッセージリスト化する
VEHICLE_100h = dbc_can.get_message_by_name(“VEHICLE_100”).decode(msg.data, decode_choices = False)
②そのリストに対して得たい変数名を記載するだけだ
VEHICLE_SPEED_FR = VEHICLE_100h[“VEHICLE_SPEED_FR”]
サンプルコード
-*- coding: utf-8 -*-
import pandas as pd
import cantools
import can
def dataframe_parser_blf(fname):
dbc_can = cantools.database.load_file(‘../xxx.dbc’)
blfdata = can.io.blf.BLFReader(fname)
sampling = 0
target_id = 0
timestamp_before = 0
#sample value
VEHICLE_SPEED_FR = 0
outputlist = []
for msg in blfdata:
#intの中はCAN_ID。今回はサンプルとして0x100を想定して記載する
if (msg.arbitration_id == int(“100”, 16)):
VEHICLE_100h = dbc_can.get_message_by_name(“VEHICLE_100”).decode(msg.data, decode_choices = False)
VEHICLE_SPEED_FR = VEHICLE_100h[“VEHICLE_SPEED_FR”]
target_id = msg.arbitration_id
if (target_id != 0):
#コメントアウトするが、ほかの関数の使い道を紹介
# print(msg.data)
# print(msg.is_extended_id)
# print(msg.dlc)
if(sampling != 0):
Timer = Timer + (msg.timestamp – timestamp_before)
outputlist.append([msg.timestamp, Timer, hex(msg.arbitration_id), VEHICLE_SPEED_FR])
timestamp_before = msg.timestamp
sampling = msg.timestamp
target_id = 0
df = pd.DataFrame(outputlist)
df.columns = ([“timestamp”, “Time[sec]”, “ID”, “VEHICLE_SPEED_FR_columns”])
df.to_csv(fname+”.csv”, encoding=”cp932″)
df = dataframe_parser(fname+”.csv”)
return df
timestamp情報についての詳細解説
10msなどでの、決まった周期でデータを書き出したいと思うかもしれないが
このモジュールのアクセス方法はCANの非同期更新に合わせているため
「何かしらのCAN IDを受信した時しか値が更新されない」

そのため、データ開始のtimestamp情報をもとに、
「計測開始に対してxx秒後の値」
という内容で取り扱うしかないのだ。
これは非同期となるCAN特有の問題で、解析ソフトを作る側からすると作りにくいが
正確に内容を理解する必要がある。
実際の現場で求められること
blfデータの解析といえば、CANalyzerやCANape、CANoeなど
優秀なVector製品がそろっているが、CAPLはかなり制限も多く出来ないことが多い
pythonにparserとして作っておくことで、即時解析やレポート作成といった
pythonの強みを生かせるようになる
まとめ
✔ pythonでblfデータを扱うときは、cantoolsとcanモジュールを使う
※ただし、Timestampには注意が必要
質問はTwitterから受け付けていますので、お気軽にどうぞ
>>pythonで生き延びる社畜(@coin_python) | Twitter
ラジオ放送でもエンジニアについて熱く語っています。こちらもお楽しみください
>>社畜戦士のエンジニアを熱く語るラジオ | stand.fm
同じくVector製品のMDFファイルもcsv化してみる
プログラミング学習者へのオススメ記事
エンジニア志望者へのオススメ記事