Files
fori_zltech_motor_test/doc/08-improvements-report.md
2026-08-24 16:00:39 +09:00

16 KiB

08. 로봇 제어 시스템 개선 보고서

이 문서는 feat/radiomaster-rc-control 브랜치에서 진행한 개선 작업을 정리한 보고서다. 모든 항목은 실제 로봇 실주행 로그로 검증을 거쳤으며, 정량적 결과는 실측 CSV 로그 분석 기반이다. 관련 상세 계획/근거는 06-imu-integration-plan.md, joystick.md에 별도로 정리되어 있다.

개요

기존 Xbox 컨트롤러(SDL2) 기반 조종을 RadioMaster Pocket + XR1 RC 수신기로 교체하면서 시작해, IMU(WitMotion HWT905) 도입을 통해 로봇이 "지령한 대로 실제로 움직이고 있는지"를 처음으로 확인·보정할 수 있게 만들었다. 그 결과 제자리 회전 성능이 지령 대비 실측 기준 **44~58% → 93.6%**로 크게 개선되었고, 직진 헤딩 자동 유지, 전신 슬립 감지, 모터 과열 조기 감지 등의 안전/편의 기능이 추가되었다.

1. RC 조종 시스템 전환

  • Xbox/SDL2 조이스틱을 RadioMaster Pocket + XR1 수신기(CRSF 프로토콜, 420000bps)로 교체.
  • 실측 하드웨어 캘리브레이션(CH1 조향/CH2 전후진/CH5 브레이크/CH6 속도모드) 및 Fail-safe 타임아웃 적용.

문제: 실측 중 채널 값이 간헐적으로 엉뚱한 값으로 튀는 현상 발견(예: 스틱을 살짝만 움직였는데 최대 후진값이 순간적으로 찍힘). CRSF 프로토콜은 표준상 CRC-8 체크섬으로 손상된 프레임을 걸러낼 수 있는데, 이 특정 수신기 하드웨어에서는 표준 CRC-8(DVB-S2) 및 가능한 변형(다항식/초기값/반전 조합 전수조사, 보율 오차 가설 등)을 모두 실측 데이터로 대조해봐도 일치율이 최대 33%에 그쳐 이 하드웨어에서는 CRC 검증 자체가 신뢰할 수 없다는 결론을 실험적으로 확정.

적용 방식: CRC 대신 3단계 방어를 조합했다.

  1. 범위 검증: 캘리브레이션으로 확인된 정상 범위를 벗어나는 값은 무조건 거부.
  2. 슬루레이트(변화율) 제한: 한 틱 사이에 물리적으로 불가능할 만큼 큰 변화는 손상 프레임으로 간주해 거부하되, 진짜 빠른 스틱 조작까지 막지 않도록 N틱 연속 거부되면 강제로 재동기화하는 예외 처리를 둠(그렇지 않으면 채널이 영구히 멈추는 결함이 있었음 — 발견 후 수정).
  3. 중앙값(median-of-3) 필터: 최근 3개 값의 중앙값을 취해 단발성 튐값의 영향을 한 번 더 줄임.
  • udev 규칙으로 /dev/ttyMOTOR//dev/ttyRC//dev/ttyIMU 고정 심볼릭 링크 적용 — USB 재연결 시 포트 번호가 매번 바뀌던 문제 해결.

2. 주행 제어 안정성 개선

  • 브레이크: 기존엔 스로틀을 중립으로 되돌려 자연 정지할 때도 전자식 브레이크가 자동으로 잠겼는데, 이를 CH5 스위치를 눌렀을 때만 잠기도록 변경.

  • 가속/감속 — 저크 제한(jerk-limited) S-curve란: 속도(RPM)를 목표까지 바로 바꾸는 게 아니라, "가속도가 변하는 속도(저크)" 자체에 상한을 둬서 가속도 곡선을 매끄러운 S자로 만드는 방식이다. 급격한 가속도 변화는 큰 전류 스파이크(역기전력)로 이어질 수 있어, 감속에는 계속 이 방식을 유지한다. 다만 하드웨어 백EMF 보호회로 구성이 완료되면서 가속은 더 이상 소프트웨어로 완만하게 램프업할 필요가 없어져, 조이스틱 목표값에 1:1로 즉시 추종하도록 변경했다(감속은 기존과 동일).

  • 정지 직전 반전 방지: 위 "즉시가속" 로직은 "목표값이 현재값보다 커지면 무조건 즉시 반영" 하는 단순 조건이었는데, 정지 막바지 저속 구간에서 RC 노이즈로 목표값이 순간적으로 반대 부호로 흔들리면 이 조건이 그대로 성립해버려 "전진→후진→전진"처럼 튀는 현상이 있었다. 적용 방식: 조건을 "같은 방향으로 더 빨라지는 경우"로 한정하고, 부호가 바뀌는 경우(RC 노이즈든 실제 방향 전환 지시든)는 전부 저크 제한 감속 경로로 보내 0을 관통할 때도 부드럽게 처리하도록 수정.

3. IMU 통합 — 오도메트리 (Phase 1~2)

  • WitMotion HWT905-RS232 IMU를 별도 USB 포트로 연동, 전원 인가 시점의 방향을 정면(0°) 기준으로 저장.

적용 방식 — 데드 레커닝(dead reckoning): GPS 없이 "지금까지 어느 방향으로 얼마나 움직였는지"를 누적 적분해서 현재 위치(x, y)를 추정하는 고전적 방식이다. 매 제어 주기(틱)마다 (1) 바퀴 인코더 피드백으로 계산한 이동 속도와 (2) 그 순간의 헤딩(진행 방향)을 곱해 이동한 x, y 변위를 누적한다. 정확도는 전적으로 헤딩을 얼마나 정확히 아는가에 달려 있다 — 헤딩이 조금만 틀려도 매 틱 누적되며 오차가 기하급수적으로 벌어지기 때문에, 이번 작업에서 가장 공들인 부분이 헤딩 소스 선정이었다.

  • 바퀴 엔코더 기반 위치 적분(x, y)과 회전율(wheel_omega) 대 IMU 실측 회전율(imu_omega) 비교 로직 추가.
  • 헤딩 소스 결정 — 실측 검증으로 설계를 뒤집은 사례: 처음엔 상식적으로 "IMU 자체 내장 융합 yaw(가속도+자이로를 자체적으로 결합해 계산한 값)가 원시 자이로를 그냥 적분하는 것보다 안정적일 것"이라 예상하고 그렇게 구현했다. 그런데 검증 방법으로 "제자리로 돌아오는 루프백 주행"을 설계해서(직선/원 등 정해진 경로로 나간 뒤 출발점으로 복귀시켜, 오차가 없다면 최종 위치가 (0,0)에 가까워야 한다는 원리) 실측해보니 시작점 대비 20.8m나 이탈하는 심각한 오차가 나왔다. 원인을 더 파보니 IMU가 자체적으로 계산해 내놓는 융합 yaw가 자기 자신의 원시 자이로 방향과도 1초 평균 기준 72%밖에 일치하지 않음을 발견했다(저가 IMU가 모터 전류로 인한 자기장 간섭 등으로 내부 지자기 보정이 흔들리는 것으로 추정). 이후 헤딩 소스를 바퀴 인코더로 추정한 회전율과 원시 자이로 값의 평균(단순 상보 융합)으로 교체 — 이 두 신호는 서로 독립적인 센서(엔코더 vs IMU)인데도 부호/크기 일치율이 99.3%로 매우 높아 신뢰할 수 있음을 먼저 확인한 뒤 채택했다.
  • 재검증: 동일한 루프백 테스트를 다시 수행해 이탈 거리가 20.8m → 0.55m로 개선됨을 확인(22m 주행 기준 약 2.5% 오차) — 같은 검증 방법을 "전/후 비교"에도 그대로 재사용해 설계 변경의 효과를 정량적으로 입증했다.

4. 직진 헤딩 자동 유지 (Phase 3)

  • 조향이 중립이고 실제로 주행 중이며 라이다 회피가 개입하지 않을 때, 진입 시점의 헤딩을 목표로 고정하고 PI 제어로 좌우 편향을 자동 보정.

적용 방식 — PI 제어: 목표 헤딩과 현재 헤딩의 차이(오차)를 계속 관찰하면서, (1) P(비례)항 — 오차가 클수록 더 크게 보정하고, (2) I(적분)항 — 작은 오차가 오래 지속되면(예: 좌우 노면 마찰 차이로 인한 지속적 편향) 그것까지 누적해서 보정을 강화하는 두 요소를 더해 좌우 바퀴 속도에 미세한 트림(보정값)을 얹는 방식이다. 트림 값에는 상한을 둬서 사용자의 의도적 조향 입력을 절대 압도하지 않도록 제한했고, 적분항에도 별도 상한(anti-windup)을 둬 트림이 무한정 커지는 것을 방지.

  • 실주행 검증(다양한 노면, 총 20분 이상): 평균 오차 0.48~1.24°, 최대 오차 10° 이내, 트림 값은 상한(±0.15 rad/s)의 최대 38%까지만 사용 — 포화·진동 없이 안정적으로 수렴.

5. 전신 슬립 감지 (Phase 4)

적용 방식 — 독립 신호 교차검증: 기존 걸림/들뜸 판정은 "지령 RPM 대비 실제 RPM"과 "전류"만으로 개별 바퀴 상태를 추정하는데, 이 두 값 모두 바퀴 자체(엔코더/전류 센서)에서 나오는 신호라 만약 4바퀴가 동시에(예: 빙판·젖은 잔디) 헛돌면 "다들 정상적으로 지령을 따라가는 것처럼" 보여 잡아내지 못하는 사각지대가 있다. 그래서 바퀴 시스템과 완전히 독립적인 IMU(관성 센서)로 실제 차체가 얼마나 돌고 있는지를 직접 재서 지령값과 비교하는 이중 안전망을 추가했다: 지령 회전율과 IMU 실측 회전율의 비율이 임계값 밑으로 일정 시간 지속되면 "전신 슬립"으로 판정해 라이다 회피의 감속 패턴과 동일한 방식으로 속도를 일시적으로 낮춘다. 제자리 회전은 원래도 지령보다 덜 도는 게 정상(스크럽 마찰)이라, 오탐을 피하기 위해 "거의 안 도는" 극단적인 경우만 잡히도록 문턱값을 보수적으로 설정.

  • 18분 실주행 중 11회, 0.4%의 틱에서만 발동 — 오탐 거의 없음. 가장 긴 발동 사례(1.68초)를 분석한 결과, 고속 주행 중 급선회 시 관성으로 인한 언더스티어(로봇이 거의 안 도는 상황)를 정확히 감지해 속도를 절반으로 낮췄고, 그 직후 실제로 회전이 정상적으로 회복되는 것을 확인 — 설계 의도대로 작동.

6. 킨매틱스 실측 캘리브레이션 — 제자리 회전 성능 대폭 개선 (Phase 5a)

6.1 원인 진단

제자리 회전이 지령한 만큼 돌지 않는 문제의 원인을 로그로 추적한 결과, 두 가지가 확인됨:

  1. 회전 시 반력 토크로 인한 대각선 방향 하중 이동(FL+RR 또는 FR+RL 바퀴 쌍이 동시에 가벼워짐)이 정상적인 물리 현상인데, 기존 "들뜸(바퀴가 지면에서 떨어짐)" 판정 로직이 이를 오탐하여 목표 속도를 0으로 꺼버려 4륜 중 사실상 2륜만 구동되는 상황이 전체 회전 틱의 **38%**에서 발생.
  2. 회전 반경 계산에 쓰이는 트랙폭 계수(k_skid, effective_w)가 기하학적 공식값으로, 실제 스킷스티어 특유의 스크럽 마찰(바퀴가 옆으로 긁히며 도는 저항)을 반영하지 못해 지령보다 작은 차동 속도를 걸고 있었음.

6.2 조치 및 결과

  • 제자리 회전 중에는 "들뜸" 판정으로 목표 속도를 꺾는 개입을 비활성화(판정 표시는 유지).

적용 방식 — 실측 역산(파라미터 피팅): 기존 k_skid/effective_w는 로봇의 트랙폭·휠베이스 치수만으로 계산한 순수 기하학적 공식값이었는데, 실제 지면에서는 바퀴가 옆으로 긁히는 저항 때문에 이 공식이 가정하는 것보다 더 큰 차동을 걸어줘야 같은 회전 속도가 나온다. 이를 정량화하기 위해 매 틱 로그에 이미 기록되고 있던 "바퀴 인코더로 계산한 회전율"과 "IMU로 실측한 실제 회전율"을 이용해, 공식을 거꾸로 풀어서(예: 유효계수 = 바퀴 기반 회전율 추정치 × 기존계수 ÷ IMU 실측 회전율) 틱마다 "실제로 맞았어야 할 계수값"을 역산했다. 이렇게 나온 수천 개의 값 중 이상치 영향을 줄이기 위해 평균이 아닌 중앙값을 대표값으로 채택했고, 서로 다른 날 수집한 3차례의 독립적인 실주행 로그에서 반복 계산해도 값이 거의 같게 수렴하는 것을 확인해 신뢰도를 높였다. 회전 반경별로 값을 나눠 보면 완만한 커브(0.44)와 급한 커브(0.53) 사이에서 계수가 변하는 경향도 확인했는데, 정적 상수 하나로는 이 편차를 완전히 없앨 수 없어 실용적인 절충값(중앙값)을 채택 — 이걸 실시간으로 자동 보정하는 방식(Phase 5b)도 검토했으나, 슬립이 발생하는 바로 그 순간에 추정 신호 자체가 같이 왜곡되는 구조적 문제가 있어 득보다 실이 크다고 판단해 보류했다. 아래 값으로 최종 수렴:

파라미터 기존(기하학적 공식) 실측 캘리브레이션
k_skid (커브 선회) 0.406 0.51
effective_w (제자리 회전) 0.684 0.87
  • 최종 성능: 제자리 회전 시 지령 대비 실제 회전율(IMU 실측 기준)이 **44~58% → 93.6%**로 개선. 완전히 100%에 도달하지 못하는 잔여 오차는 스킷스티어 구조 특유의 물리적 한계(4륜 전부가 옆으로 긁히며 돌아야 하는 구조상 슬립 없이는 방향 전환이 불가능)로 판단되며, 현재 수준이 이 하드웨어에서 실용적으로 기대 가능한 한계에 근접한 것으로 평가.
  • 실시간 온라인 적응형 보정(Phase 5b)은 추가 정확도 이득 대비 구현/검증 리스크가 크다고 판단해 보류 결정(근거는 06번 문서 참고).

7. 모터/드라이버 온도 모니터링

  • 기존엔 사용하지 않던 드라이버 레지스터(모터 온도 0x20A4, 드라이버 온도 0x20B0)를 읽어 HUD/CSV에 실시간 노출.

적용 방식: 드라이버와의 통신은 매 제어 주기(약 27Hz)마다 이루어지는데, 통신 1회를 늘릴 때마다 제어 루프 지연이 커진다. 모터 온도 레지스터(0x20A4)는 마침 기존에 읽고 있던 레지스터 범위(0x20A5~) 바로 앞이라, 읽는 레지스터 개수만 하나 늘려서 통신 횟수 추가 없이 얻어냈다. 반면 드라이버 자체 온도(0x20B0)는 기존 읽기 범위와 떨어져 있어 합치면 통신이 늘어나는데, 온도는 물리적으로 초 단위로 천천히 변하는 값이라 매 틱 갱신할 필요가 없다는 점을 이용해 약 1.1초에 한 번만 별도로 폴링하는 저빈도 방식을 택했다 — 정확도 손실 없이 통신 비용을 최소화한 설계.

  • 60℃ 이상 시 HUD에 경고 표시.

8. 진단만 완료, 조치는 보류 중인 이슈

  • 급정지 시 미세한 요잉(회전) 현상: 처음엔 "조이스틱을 놓을 때 튕기는 물리적 반동" 가설을 세우고 로그의 RC 원시값 변화를 직접 확인했으나, 해당 구간에서 스틱 값은 매끄럽게 중립으로 복귀했을 뿐 반대 방향으로 튀는 값은 전혀 없어 이 가설은 기각했다. 대신 정지 이벤트마다 전후 바퀴 명령/피드백/상태 플래그를 시간순으로 대조해본 결과 두 가지 원인을 확인: (1) 거친 노면에서 정지 직전 특정 바퀴가 순간적으로 "들뜸" 판정되어 다른 바퀴와 감속 타이밍이 어긋나는 것, (2) 드라이버 자체의 속도 제어 루프가 급정지 시 0을 살짝 지나쳤다 돌아오는 오버슈트(4바퀴가 0을 지나치는 타이밍이 서로 달라 그 사이 짧게 회전 모멘트가 생김). 감속 속도를 낮추면 완화될 여지가 있으나 "즉각 정지" 체감이 희생되는 트레이드오프가 있어 적용 여부는 보류 중.

9. 자동화 및 진단 인프라

  • 매 주행마다 logs/ 폴더에 타임스탬프 CSV 자동 저장(수동으로 --log 지정할 필요 없음) — RC/IMU/모터 피드백/오도메트리/헤딩홀드/슬립감지/온도까지 전 항목 기록, 이번 보고서의 모든 정량적 검증이 이 로그를 근거로 이루어짐.

10. 향후 계획

라이다(Livox Mid-360S) 기반 SLAM/자율주행 확장 계획은 07-lidar-slam-plan.md에 별도 정리되어 있음(아직 미착수).

종합 결과 요약

항목 개선 전 개선 후
조종기 Xbox/SDL2 (유선) RadioMaster Pocket + XR1 (무선 RC)
브레이크 자연 정지 시에도 자동 잠김 CH5로만 제어
헤딩 인지 없음 오도메트리(x,y,θ) + 자동 직진 유지
제자리 회전 정확도(지령 대비) 44~58% 93.6%
슬립 감지 개별 바퀴 전류 기반만 존재 + IMU 기반 전신 슬립 이중 감지
모터 상태 가시성 전류만 + 온도(모터/드라이버) 실시간 감시
주행 기록 수동 --log 필요 매 주행 자동 저장