-
blf & dbc --> mdf 변환application 2026. 3. 8. 15:04
시작하기 전에
일이라는 것이 결정들의 연속이다. 엔지니어링도 그렇다. 측정과 연산 기술의 발전으로 감/경험에 기반한 결정들이 데이터 기반 결정들로 대체되고 있다. 최근에 데이터 기반 결정이 적용되는 영역이 빠르게 넓어지고 있다고 느낀다. CAN 데이터를 mdf 파일로 저장하는 방법 문의를 점점 더 많이 받는다.
blf 파일과 dbc 파일을 입력으로 받아 mdf 파일을 생성하는 간단한 프로그램을 클로드와 만들었다. 그 방법을 설명한다.

blf+dbc --> mdf 변환기 GUI 개요
- blf vs. mdf
- 메시지 파싱하기
- blf에서 메시지 읽기
- mdf 파일로 저장하기
- 코드
- 프로그램
- 결론
blf vs. mdf
- CAN 데이터는 주로 blf 파일로 저장된다. blf는 메시지 기반이다. 프레임들은 수신된 순서대로 타임스탬프와 함께 파일에 저장된다. 특정 신호의 시간에 따른 변화를 보기에 불편하다. 아래 그림은 blf 파일에 CAN 프레임들이 저장된 상태를 시각화한 것이다. 빈 칸은 진짜 빈 칸일 수도 다른 신호일 수도 있다.

blf 파일에 CAN 프레임은 수신 순서대로 저장된다. - 데이터가 아래 그림처럼 저장되어 있다면 데이터 처리에 좋을 것이다. 나는 이런 형태를 신호 기반이라고 칭했다. 행과 열로 구성된 엑셀 표 형식이다. 파이썬 numpy의 2-D 어레이나 pandas의 데이터프레임이 대표적이다.

pandas의 데이터프레임 형식이다. 데이터처리가 쉽다. - 나는 이전 포스트들에서 blf를 데이터프레임으로 변환하는 방법을 설명하였었다.
- mdf 파일은 신호 기반이라고 할 수 있다. mdf는 신호별로 타임스탬프를 별도로 저장한다. 위 그림의 blf 파일을 mdf 파일로 저장한 경우는 아래 그림처럼 표현할 수 있다. (개념만 표현한 것이다. 타임스탬프가 같은 경우, 저장 공간의 낭비를 줄이기 위한 방법이 적용되어 있다.)

mdf는 신호와 신호의 타임스탬프를 개별적으로 저장한다. - 기회가 있을 때 설명을 하자면, 내가 blf를 데이터프레임으로 바꾸는 방법은 아래와 같다.

blf를 데이터프레임으로 변환하는 방법 - dbc의 메시지/신호 정의를 이용하여 메시지 기반의 blf 데이터를 신호 기반으로 변환(파싱)한다.
- 변환된 데이터에는 빈 칸이 많이 있다. "결측치"이다. 이 결측치를 채운다. 빈 칸 바로 위의 측정값으로 채운다.
- 필요한 주기로 다시 샘플링(resample) 한다. 샘플링 구간의 대표값을 구간의 시작값/마지막값/평균값/중간값 등으로 할 수 있다.
메시지 파싱하기
- CAN 메시지의 데이터를 신호로 파싱하기 위해서는
- dbc를 읽어 메시지/신호 정의를 파악해야 한다.
- 메시지/신호의 정의에 따라 데이터를 파싱해야 한다.
- cantools 모듈을 사용했다. (cantools/cantools: CAN bus tools.)
import cantools # cantools를 import 한다. # dbc 파일 읽기 db = cantools.database.load_file(dbc_path) # CAN 메시지의 데이터를 신호별로 읽기 # 한 개 CAN 메시지에 대해 아래 작업을 한다. decoded = db.decode_message(mid, data) # mid: message id, data: data for sig_name, value in decoded.items(): try: fval = float(value) # 일반 신호를 읽는다. except (TypeError, ValueError): fval = float(value.value) # ValueTable이 있는 경우, 값을 읽는다. results.append((mid, sig_name, ts, ch, fval)) # 메시지를 처리하여 신호 단위로 모은다.blf 에서 메시지 읽기
- blf 파일에서 CAN 프레임을 하나씩 읽어가며 파싱을 해야 한다. 그러기 위해 python-can 모듈을 사용했다. ( hardbyte/python-can: The can package provides controller area network support for Python developers)
import can # python-can을 import 한다. # blf 파일에서 메시지 읽기 with can.BLFReader(path_to_blf_file) as reader: # blf 파일을 연다. for msg in reader: # 메시지를 하나씩 읽는다. mid = msg.arbitration_id # ID 확인 방법 ch = msg.channel # 채널 확인 방법 ts = msg.timestamp # 타임스탬프 확인 방법 data = msg.data # 데이터를 bytearray로 확인 방법- 여기 mid와 data를 db.decode_message(mid, data) 함수에 넣어서 최종적으로 (신호, 값) 쌍들로 파싱한다.
- 이를 처리하여 신호별로 (타임스탬프, 값) 쌍의 어레이를 만들 수 있다.
mdf로 저장하기
- mdf는 ASAM(Association for Standardization of Automotation and Measuring Systems, https://www.asam.net/)이라는 조직에서 만든 표준이다.
- (타임스탬프, 값) 쌍의 어레이의 묶음을 mdf 파일로 저장한다. 이를 위해서 asammdf 모듈을 사용했다. ( Welcome to asammdf’s documentation! — asammdf 8.7.2 documentation)
from asammdf import MDF # mdf 파일을 다루기 위해 asammdf 모듈에서 MDF를 import 한다. from asammdf import Signal as MdfSignal # 신호 수준 처리를 위해 asammdf 모듈에서 Singla을 import 한다. mdf = MDF(version=mdf_version) # mdf 파일을 연다. # Build unit lookup: sig_name → unit mdf_signals = [] for fname, (ts, vs) in final_signals.items(): # fname format: "MSG_NAME.SIG_NAME" or "MSG_NAME.SIG_NAME_chN" raw_sig_name = fname.split(".")[-1] # Strip _chN suffix to find unit base_sig_name = raw_sig_name if "_ch" in raw_sig_name: base_sig_name = raw_sig_name.rsplit("_ch", 1)[0] unit = sig_unit.get(base_sig_name, "") mdf_signals.append( MdfSignal( samples=vs, timestamps=ts, name=fname.replace(".", "__"), unit=unit, ) # 신호값(vs), 타임스탬프(ts), 신호 이름, 신호 단위로 mdf 신호를 생성한다. ) # Mdf 신호들을 묶어서 mdf_signals라는 리스트를 만든다. mdf.append(mdf_signals) # mdf 파일에 mdf_signals의 데이터를 추가한다. mdf.save(output_path, overwrite=True) # mdf 파일에 저장한다. mdf.close() # mdf 파일을 닫는다.코드
- 코드와 파이썬 모듈 설치를 위한 requirements.txt 파일은 첨부와 같다. 두 파일들을 같은 디렉토리에 저장한다.
blf_dbc_to_mdf_mp.py0.09MBrequirements.txt0.00MB- 파일들을 저장한 디렉토리에서 커맨트라인 창을 연다.
- 아래 명령어로 프로그램 실행에 필요한 파이썬 모듈들을 설치한다.
pip install -r requirements.txt- 아래 명령으로 프로그램을 실행한다.
python blf_dbc_to_mdf_mp.py- 프로그램 이름 마지막의 mp는 multiprocessing을 의미한다. 변환 속도를 높이기 위해 blf 파일을 쪼개서 각각 변환한 후에 다시 합치는 방식을 적용했다. 각각을 변환할 때 멀티프로세싱을 적용했다. 클로드가 없었다면 여러 시간/날 걸렸을 일이다. 멀티프로세싱 적용 가능성과 기대 효과를 문의하고, 구현해 달라고 요청하는 것으로 멀티프로세싱 기능을 추가했다.
- 클로드와 코딩을 하면서 작성한 FRD: FRD: blf & dbc --> mdf :: hsl's tsmaster 사용기
프로그램
파일 입력
- blf 파일과 dbc 파일을 선택할 수 있따. '선택...' 버튼을 클릭하면 익숙한 파일 열기 대화창이 뜬다.
- blf와 dbc를 선택한 후에 '파싱' 버튼을 누르면
- blf 파일에 포함된 메시지 아이디들을 추출한다.
- dbc 파일에 포함된 메시지/신호 정의를 로드한다.

신호 선택
- mdf 파일로 추출할 신호들을 선택한다. blf에 있는 신호들만 선택 가능하다. 선택을 json 파일로 저장하여 재사용 할 수 있다.

변환 옵션 및 실행
- blf를 mdf로 변환 한다.
- 리샘플링 주기와 방법을 설정할 수 있다.
- 첫 메시지의 타임스탬프를 0s이 되도록(타임스탬프 정규화) 할 수 있다.
- mdf 버전을 선택할 수 있다.
- mdf 파일 경로와 이름을 지정할 수 있다.
미리보기
- (변환 결과로 생성된) mdf 파일을 볼 수 있다.
- 관심이 있는 신호들을 그래프로 볼 수 있다.

결론
- 메시지 기반 blf 파일에서 신호 기반 mdf 파일 생성하는 프로그램을 만들었다.
- blf에 정의된 메시지/신호를 알기 위해서 dbc 파일이 함께 필요하다.
- cantools 모듈을 사용하면 몇 줄의 코드로 dbc에서 메시지/신호 정의를 알 수 있고, CAN 메시지를 신호들로 파싱할 수 있다.
- python-can 모듈을 사용하면 blf 파일에서 CAN 메시지를 하나씩 읽어서 처리할 수 있다.
- asammdf 모듈을 사용하면 신호별로 마련한 (타임스탬프, 값) 에레이들을 묶어서 mdf 파일로 저장할 수 있다.
'application' 카테고리의 다른 글
dbc 병합 (1) 2026.03.16 blf & dbc --> mdf or csv 변환 (0) 2026.03.10 바이브 코딩으로 진단기 만들기 (0) 2026.01.19 diag_tester_FRD (0) 2026.01.19 포르쉐 타이칸 CAN 데이터에서 횡가속도 신호 찾기 (0) 2026.01.06