Python中canmatrix解析dbc文件應(yīng)用常見示例
前言
dbc文件是汽車行業(yè)常見的數(shù)據(jù)庫文件,用于描述CAN總線數(shù)據(jù)的物理值、單位、發(fā)送周期、計(jì)算公式、信號名稱等信息。
用Python處理dbc文件的庫有很多,比如 python-can,cantools和canmatrix,甚至可以用正則表達(dá)式自行進(jìn)行解析。其解析本質(zhì)差不多,下面分享下canmatrix常用的一些方法。
1. 相關(guān)庫安裝
canmatrix使用時(shí)直接"import canmatrix"即可,但是會打印出一些 "xxx is not supported"的提示信息,這是使用到的庫沒安裝導(dǎo)致的。
在.\canmatrix\formats路徑下有很多 xxx.py文件,這些文件用于解析相對應(yīng)后綴名的文件。打開"xxx is not supported"對應(yīng)的.py,安裝文件中用到(import)的三方庫即可。
2. dbc和Excel格式互轉(zhuǎn)
安裝canmatrix后,在\Python\PythonXX\Scripts路徑下,會有一個(gè)canconvert.exe??梢灾苯釉诿钚兄校?/p>
- 輸入"canconvert xxx.dbc xxx.xlsx"將dbc轉(zhuǎn)成xlsx格式。(表格中一些單元格中的字體是透明的,可以全選改成黑色。)
- 輸入"canconvert xxx.xls xxx.dbc"將xls轉(zhuǎn)成dbc格式。(不支持xlsx格式,可先將xlsx導(dǎo)出為xls格式)
也可以用canmatrix.convert py腳本,比如:
from canmatrix import convert convert.convert( r'aa.dbc', r'aa.xlsx' )
canconvert導(dǎo)入導(dǎo)出的表格是有固定格式的,常用于臨時(shí)查看dbc中的報(bào)文和信號。一般公司會有matrix特定的表格格式,這就需要特定處理了。
3. 讀取dbc文件
3.1 matrix信息
import canmatrix file = r'Test.dbc' dbs = canmatrix.formats.loadp(file) print(type(dbs), dbs)
- canmatrix.formats.loadp(file)用于load不同格式的文件。打印其信息,是一個(gè)字典類型。
matrix = dbs.get('') print(type(matrix), matrix) for k, v in matrix.__dict__.items(): print(k, v)
- 獲取字典中的value,其類型是CanMatrix,dbc中的信息都在這里。打印其中包含的信息,如下圖所示:
3.2 Ecu信息
for ecu in matrix.ecus: print(type(ecu), ecu.__dict__)
- matrix.ecus包含了dbc中所有的ecu節(jié)點(diǎn),信息如下:
3.3 Message(Frame)信息
for msg in matrix.frames: print(type(msg), msg.__dict__) for k, v in msg.__dict__.items(): print(k, v)
- 報(bào)文的信息的類型是Frame,參考圖中打印的信息,一般用到:
- name:報(bào)文的名稱
- arbitration_id.id:報(bào)文的id
- transmitters:發(fā)送報(bào)文節(jié)點(diǎn)(發(fā)送節(jié)點(diǎn)只會有一個(gè))
- receivers:接收報(bào)文的節(jié)點(diǎn)
- signals:報(bào)文中的信號
- signalGroups:報(bào)文中的signalGroups
- cycle_time:報(bào)文周期
一些其他信息會在attributes 字典中,比如Nm或者診斷報(bào)文。如果有其他信息想知道,可以用類似方式打印其.__dict__查看。
3.4 signal信息
for signal in msg.signals: print(type(signal), signal.__dict__) for k, v in signal.__dict__.items(): print(k, v)
- signal的信息參考圖中打印的內(nèi)容,一般用到:
- name:信號名稱
- start_bit:在layout中的起始位
- size:長度(bit)
- is_little_endian:Motorola(Big)和Intel(Little)格式
- is_signed:有無符號
- offset和factor:偏移和系數(shù),用于轉(zhuǎn)換成物理值
- min和max:最小值和最大值
- is_multiplexer:多路復(fù)用信號的multiplexor signal
- mux_val:multiplex value
- multiplex:和is_multiplexer、mux_val兩個(gè)量信息是重復(fù)的。當(dāng)信號是multiplexor signal時(shí),這個(gè)量是字符串“Multiplexor”;當(dāng)信號是multiplexed signal時(shí),這個(gè)量是multiplex value。
3.5 signalGroup信息
for signalGroup in msg.signalGroups: print(type(signalGroup), signalGroup.__dict__) for k, v in signalGroup.__dict__.items(): print(k, v)
- signalGroup中主要包含信號的信息,其中的信號也包含在Frame中,注意避免信號重復(fù)使用。
4. 常見應(yīng)用示例
以下示例都是應(yīng)用于vector的達(dá)芬奇開發(fā)工具,其他工具不清楚是否適用。用到的場景基本都是讀取dbc中的報(bào)文和信號名稱,再做一些其他處理。
4.1 ComCbk回調(diào)函數(shù)添加
一般E2E信號的名稱是有特定字符的,可判斷其名稱來確定所在報(bào)文是否為E2E報(bào)文。再結(jié)合xml解析腳本,可以在ComCbk中自動添加回調(diào)函數(shù)的名稱。
def is_signal_e2e(signal: canmatrix.Signal): """ 判斷信號是否是E2E信號,checksum or rolling_counter """ RCs = ("RollCnt", "RollingCounter", "AliveCounter", "Rolling_Counter", "Alive_Counter", "RollgCnt") CRCs = ("Chksum", "Chksm", "CheckSum", "CRC") for rc in RCs: if rc.lower() in signal.name.lower(): return True for crc in CRCs: if crc.lower() in signal.name.lower(): return True return False
4.2 Can_Wrapper模塊arxml或者代碼生成
一般在項(xiàng)目中,ASW和com之間會有一個(gè)中間模塊(Can_Wrapper)進(jìn)行數(shù)據(jù)的映射。這個(gè)模塊和com之間的delegation接口可根據(jù)讀取dbc自動生成。達(dá)芬奇Developer也可以批量自動創(chuàng)建,但和ASW的接口就得手動創(chuàng)建了。所以這里提下生成Can_Wrapper過程中和dbc有關(guān)的部分。接口的名稱可以根據(jù)信號名再加一些特定格式,數(shù)據(jù)類型按照信號size和is_signed等定義計(jì)算出。示例代碼如下:
def get_signal_dataType(signal: canmatrix.Signal): """ 計(jì)算信號生成代碼的數(shù)據(jù)類型。 """ dataType = "UnknownType " if signal.is_float is True: if signal.size == 32: dataType = "float32" elif signal.size == 64: dataType = "float64" else: print(f"Not supported <{signal.size}> size of <float> data type. <{signal.__dict__}>") elif (signal.factor != 1) or (signal.offset != 0): dataType = "float32" elif signal.size == 1: dataType = "boolean" elif signal.size <= 8: if signal.is_signed: dataType = "sint8" else: dataType = "uint8" elif signal.size <= 16: if signal.is_signed: dataType = "sint16" else: dataType = "uint16" elif signal.size <= 32: if signal.is_signed: dataType = "sint32" else: dataType = "uint32" elif signal.size <= 64: if signal.is_signed: dataType = "sint64" else: dataType = "uint64" else: print(f"Unexpected datatype of signal. <{signal.__dict__}>") return f"{dataType}"
總結(jié)
canmatrix不僅可以讀取數(shù)據(jù)庫文件,也可以寫入,個(gè)人感覺還是比較好用的。當(dāng)然其中也存在一些bug,在使用中慢慢探索并規(guī)避吧。 ^_^
到此這篇關(guān)于Python中canmatrix解析dbc文件應(yīng)用的文章就介紹到這了,更多相關(guān)Python canmatrix解析dbc文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用django-suit模板添加自定義的菜單、頁面及設(shè)置訪問權(quán)限
這篇文章主要給大家介紹了關(guān)于利用django-suit模板添加自定義的菜單、頁面及設(shè)置訪問權(quán)限的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起看看吧2018-07-07python ImageDraw類實(shí)現(xiàn)幾何圖形的繪制與文字的繪制
這篇文章主要介紹了python ImageDraw類實(shí)現(xiàn)幾何圖形的繪制與文字的繪制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02python subprocess pipe 實(shí)時(shí)輸出日志的操作
這篇文章主要介紹了python subprocess pipe 實(shí)時(shí)輸出日志的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12python中字典(Dictionary)用法實(shí)例詳解
這篇文章主要介紹了python中字典(Dictionary)用法,以實(shí)例形式較為詳細(xì)的分析了Python字典建立、添加、刪除等常見操作技巧,需要的朋友可以參考下2015-05-05