【完全版】pythonでblfファイルのCANデータをcsv化する【詳細解説付き】

python サンプル学習

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化してみる

プログラミング学習者へのオススメ記事

エンジニア志望者へのオススメ記事

タイトルとURLをコピーしました