-
CAN 신호를 실시간으로 필터링 하기 - 미니프로그램과 aianalysis 2024. 10. 25. 01:57
시작하기 전에
CAN 신호들로 실시간 연산하기 - 미니프로그램으로 yaw_rate_ws 계산에서 CAN 버스의 뒷 바퀴 신호들 (WHL_SPD_RR, WHL_SPD_RL)에서 요-레이트(yaw_rate_ws)를 계산하고, 차량 센서가 측정하여 CAN 버스에 올린 요-레이트(YAW_RATE)와 그래픽 창에서 비교하는 방법을 설명하였다.
결과를 보면, YAW_RATE는 매끈한데 비해 yaw_rate_ws는 거칠다. yaw_rate_ws에 실시간으로 필터를 적용할 수 있을까? 하는 의문이 들었다.
사실 나는 '필터는 신호와 노이즈가 섞인 데이터에서 노이즈를 제거한다'는 개념적인 이해를 갖고 있으나 연산 측면에서 필터를 어떻게 코드로 작성할 수 있는 지는 모른다. claude.ai에게 요청하여 코드를 작성했다. 그 코드로 yaw_rate_ws에 필터를 적용하여 yaw_rate_ws_filt를 계산할 수 있었다.
아이디어가 생겨서 구현하기까지 전 과정이 2 시간도 안 걸렸다. 필터에 대한 내 지식, 내 코딩 능력, 내 학습 능력을 고려하면 40 시간은 걸려야 할 수 있는 일이라고 짐작한다.
개요
- claude.ai에게 필터 코드를 요청하기
- 기존 yaw_rate_ws를 계산하는 미니프로그램에 필터 코드를 추가하기
- 그래픽에 yaw_rate_ws_filt 추가하기
- 실행
claude.ai에게 필터 코드를 요청하기
- yaw_rate_ws에서 노이즈를 제거하기 위해 적절한 필터인지 모르겠지만 어디선가 들어본 적이 있는 칼만(Kalman) 필터를 적용해보기로 한다. (필터 적용 방법 설명이 주요 주제라서 필터의 적절성은 부차적이다. )
- 데이터를 어레이로 받아서 필터를 해야할 것으로 짐작했었다. ( claude.ai가 작성한 코드를 보니 내 짐작은 틀렸다. 어레이도 필요없다. 변수 1개면 된다.) 그래서 아래와 같이 요청하고 코드를 받았다.
기존 yaw_rate_ws를 계산하는 미니프로그램에 필터 코드를 추가하기
칼만 필터 사용법
- 칼만 필터 사용법은 간단하다.
- 칼만 필터 클래스를 정의한다. claude.ai가 만든 코드를 복붙한다.
- 칼만 필터 객체를 만든다.
- WHL_SPD11_1 메시지를 받을 때마다 on_can_rx_WHL_SPD11() 함수가 호출된다. on_can_rx_WHL_SPD11() 함수 yaw_rate_ws를 계산한다. 이 계산 후에 yaw_rate_ws에 칼만 필터를 적용하여 yaw_rate_ws_filt를 계산하도록 코드를 수정한다. 함수 호출 때마다 칼만 필터를 새로 만들지 않도록 칼만 필터를 Global Definition에서 만든다.
- 칼만 필터가 적용된 yaw_rate_ws_filt를 그래프로 표시하기 위해서 시스템 변수에 저장한다. 이렇게 하기 위해서는 시스템 변수를 사전에 만들어 두어야 한다.
Global Definition 코드 수정
- 아래와 같이 코드를 수정한다.
- "# 칼만 필터" 이하 부분이 추가된 코드다.
- class KalmanFilter의 정의는 claude.ai가 작성한 코드를 복붙하였다.
- kalman_filter = KalmanFilter(...)은 내가 짠 코드 한 줄이다. (한 줄의 코드를 읽기 좋게 여러 줄로 분리했다.) KalmanFilter 클래스에서 kalman_filter 객체를 만든다.
# Databases.py에 dbc의 메시지들과 신호들이 정의됨 # 미니프로그램에서 불러서 사용할 수 있도록import함 import Databases as dbs # Databases.py에 TWHL_SPD11_1 이라는 클래스가 정의되어 있다. # WHL_SPD11_1 메시지에서 신호들을 읽기 위해 # TWHL_SPD11_1 클래스의 변수를 선언한다. WHL_SPD11_1 = dbs.TWHL_SPD11_1() # 칼만 필터 # claude.ai가 작성한 코드이다. # 칼만 필터 클래스를 정의한다. class KalmanFilter: def __init__(self, initial_state, initial_estimate_error, measurement_noise, process_noise): self.state = initial_state self.estimate_error = initial_estimate_error self.measurement_noise = measurement_noise self.process_noise = process_noise def update(self, measurement): # 예측 prediction = self.state prediction_error = self.estimate_error + self.process_noise # 업데이트 kalman_gain = prediction_error / (prediction_error + self.measurement_noise) self.state = prediction + kalman_gain * (measurement - prediction) self.estimate_error = (1 - kalman_gain) * prediction_error return self.state # 칼만 코드 객체를 만든다. kalman_filter = KalmanFilter( initial_state=0, initial_estimate_error=1, measurement_noise=0.1, process_noise=0.01 )
시스템 변수 만들기
- yaw_rate_ws_filt를 그래프에 표시하기 위해서는 시스템 변수가 필요하다.
- 메인 메뉴/ Simulation/ System Variables 버튼을 클릭하여 System Variable Management 창을 열고, yaw_rate_ws_filt 변수를 추가한다. (상세한 방법은 CAN 신호들로 실시간 연산하기 - 미니프로그램으로 yaw_rate_ws 계산)의 yaw_rate_ws 사용자변수 만들기 부분을 참조해 주십시오.)
on_can_rx_WHL_SPD11() 변경하기
- 아래와 같이 코드를 수정한다.
- "# yaw_rate_ws를 필터링한다." 부분과 " # 사용자 변수 calc.yaw_rate_ws_filt에 위에서 계산한 yaw_rate_ws_filt를 넣는다." 두 부분만 추가된 코드다.
def on_can_rx_WHL_SPD11(ACAN: RawCAN) -> None: # global yaw_rate_ws_filt # global KalmanFilter global kalman_filter # if (ACAN.idx_chn != CH1): # if you want to filter channel # return # WHL_SPD11 메시지를 WHL_SPD11_1 변수에 넣는다. # WHL_SPD11_1 변수를 먼저 선언해주어야 함. # 변수 선언은 Global Definition에서 함 WHL_SPD11_1.FRawCAN = ACAN # yaw_rate_ws를 계산한다. whl_spd_rr_minus_rl = WHL_SPD11_1.WHL_SPD_RR - WHL_SPD11_1.WHL_SPD_RL # 베뉴의 rear track은1.555m이다. # wheel_spd_rr_minus_rl를 rear track으로 나눠서 yaw rate를 구한다. # wheel speed는 kph이다. mps로 변환하기위해 1000 / 36000을 곱한다. # radian을 deg로 변환하기 위해 180 / pi를 곱한다. # 위 연산을 하는 것은 whl_spd_rr_minus_rl에 10.27을 곱하는 것과 같다. yaw_rate_ws = whl_spd_rr_minus_rl * 10.27 # yaw_rate_ws를 필터링한다. yaw_rate_ws_filt = kalman_filter.update(yaw_rate_ws) # 사용자 변수 calc.yaw_rate_ws에위에서 계산한 yaw_rate_ws를 넣는다. app.set_system_var_double("calc.yaw_rate_ws", yaw_rate_ws) # 사용자 변수 calc.yaw_rate_ws_filt에위에서 계산한 yaw_rate_ws_filt를 넣는다. app.set_system_var_double("calc.yaw_rate_ws_filt", yaw_rate_ws_filt)
그래프에 yaw_rate_ws_filt 추가하기
- 그래픽스 창의 신호 리스트에서 우클릭하여 Add System Variables 를 클릭하여 yaw_rate_ws_filt를 그래프에 추가한다.
- 나는 쉬운 비교를 위해서 화면에 스플릿을 여러 개 추가하였다. 그리고 각 스플릿에 비교할 신호들을 추가하였다.
실행
- 미니프로그램을 실행한다.
- 메인 메뉴/ Analysis에서 Start Logging 한다. 혹은 메인 메뉴/ Analysis에서 Bus Replay를 한다.
- 위 "시작하기 전에"의 그래프와 같은 출력을 볼 수 있다.
결론
- 데이터 처리는 소프트웨어 개발 및 검증에 요긴하다. 특히 실시간 데이터 처리와 표시는 개발 시간 단축에 매우 요긴하다.
- ai로 코딩 시간이 극적으로 단축되었다.
- TSMaster는 C와 Python을 지원한다. 두 언어는 ai 코드의 질이 상당히 높다. 이 예제의 칼만 필터의 경우 코드를 단순 복붙하여 사용해도 잘 작동한다.
- ai, TSMaster의 C, Python 지원으로 실시간 데이터 처리를 금방 구현할 수 있다.
- 위에 설명한 방법으로 실시간 FFT(Fast Fourier Transformation) 계산과 표시 방법을 개발하고 있다. 개발이 완료되면 방법을 설명하는 블로그를 작성할 것이다.
'analysis' 카테고리의 다른 글
CAN 데이터로 제동 성능 평가하기 (0) 2024.10.25 CAN 신호들로 실시간 연산하기 - 미니프로그램으로 yaw_rate_ws 계산 (0) 2024.10.25 CAN 트레이스 받기 - 하드웨어 설정 (0) 2024.10.25 CAN 트레이스 보기 - 바퀴 속도 (4) 2024.10.25 FFT 비주얼라이저 개선 - 미니프로그램과 ai (2) 2024.10.25