Vehicle Control Model#

What you’ll do

  • velocity_mps, omega_rps 기반의 주행 명령이 Ackermann 기하를 거쳐 바퀴(eRPM)와 조향(pulse_us)로 변환되는 과정을 이해합니다.

Prerequisites

Next


Conventions

  • velocity_mps (\(v\)): \(\mathrm{m/s}\), \(v>0\) 전진, \(v<0\) 후진

  • omega_rps (\(\omega\)): \(\mathrm{rad/s}\), \(\omega>0\)이면 CCW, \(\omega<0\)이면 CW

  • curvature_1pm (\(\kappa\)): \(\mathrm{m}^{-1}\), \(\kappa = 1/r\) (단, \(r\)\(\mathrm{m}\) 단위), \(\kappa=0\) 직진

  • 변환: \(\omega = v\kappa\), \(\kappa = \omega/v\) (단, \(|v|\)가 매우 작으면 \(\kappa=0\)으로 처리)

참고

제한/안전 규약(속도 제한, 권장 곡률 범위, 데드맨 등)은 Platform Overview 하단의 “Limits & Safety”를 참고하세요.


1. 제어 입력의 물리적 의미#

우리가 제어하고자 하는 값은 차량의 중심(Rear axle 중심)을 기준으로 정의됩니다.

  • 목표 속도 \(v\) (\(\mathrm{m/s}\)): 차량 중심이 전진 또는 후진하는 선속도입니다.

  • 목표 각속도 \(\omega\) (\(\mathrm{rad/s}\)): 차량이 초당 몇 라디안만큼 회전하는지를 나타냅니다. \(\omega>0\)이면 CCW, \(\omega<0\)이면 CW입니다.

  • 곡률 \(\kappa\) (\(\mathrm{m}^{-1}\)): UART 제어 패킷에서 사용하는 값입니다. \(\kappa = \omega/v\)로 변환되며, 회전 반경의 역수(\(\kappa = 1/r\))로도 정의됩니다. 곡률로 표현하면 직진 상태(\(r=\infty\))를 \(\kappa=0\)으로 표현할 수 있고, 입력 제한이나 조향 포화 계산이 단순합니다.

부호 규약

  • 각속도는 \(\omega>0\)이면 CCW, \(\omega<0\)이면 CW입니다.

  • 전진(\(v>0\))에서는 \(\kappa=\omega/v\)이므로, \(\kappa>0\)CCW, \(\kappa<0\)CW로 해석됩니다.


2. 하드웨어 파라미터 셋업#

계산에 사용되는 차량의 고유 파라미터입니다.

항목

기호

단위

비고

Wheelbase

\(L\)

0.211

\(\mathrm{m}\)

전축과 후축 사이의 거리

Track width

\(T\)

0.18

\(\mathrm{m}\)

좌우 바퀴 사이의 거리

Wheel radius

\(R_w\)

0.034

\(\mathrm{m}\)

바퀴 반경

Max Speed

\(v_{\max}\)

2.0

\(\mathrm{m/s}\)

시스템 허용 최대 속도(절댓값)

Max Curvature (권장)

\(\kappa_{\max}\)

3.0

\(\mathrm{m}^{-1}\)

입력 권장 범위(절댓값)

Max Steering

\(\delta_{\max}\)

0.785

\(\mathrm{rad}\)

기계적 최대 조향각, 약 \(45^\circ\) (절댓값)

Motor Pole Pairs

\(p\)

11

-

eRPM 계산용

서보 PWM은 아래 파라미터를 사용합니다.

항목

단위

비고

Center pulse

1500

\(\mu\mathrm{s}\)

직진 기준

Pulse range

600

\(\mu\mathrm{s}\)

center 기준 \(\pm\)

Clamp range

\(900\sim2100\)

\(\mu\mathrm{s}\)

출력 제한


3. Ackermann Geometry (Advanced)#

단순한 차동 주행(Differential Drive)과 달리, 조향 바퀴가 있는 차량은 안쪽 바퀴와 바깥쪽 바퀴가 그리는 회전 반지름이 다릅니다.

3.1 직진 ( \(\kappa = 0\) )#

직진일 때는 조향각을 0으로 두고, 좌/우 바퀴는 같은 속도로 회전합니다.

\[ \delta_L = \delta_R = 0 \]

3.2 회전 반경 계산#

입력받은 곡률을 바탕으로 차량 중심 및 좌/우 바퀴의 회전 반경을 구합니다.

  1. 차량 중심 반경: \(r=1/\kappa\)

    • 또는: \(r=v/\omega\) (\(\omega \neq 0\))

  2. 좌측 바퀴 경로 반경: \(r_L = r-T/2\)

  3. 우측 바퀴 경로 반경: \(r_R = r+T/2\)

3.3 조향각 도출 및 제한#

각 바퀴가 꺾여야 할 각도(\(\delta\))는 삼각함수로 계산됩니다.

\[ \delta_L = \arctan(\frac{L}{r_L}),~~\delta_R = \arctan(\frac{L}{r_R}) \]

중요: 하드웨어의 최대 조향각은 내측의 기계적 한계(\(\delta_{max}\))에 제한됩니다.

조향각이 한계에 걸리면(포화) 내측 조향각을 \(\pm\delta_{max}\)로 제한한 뒤, 그 기하에 맞춰 외측 조향각과 중심 반경을 다시 계산합니다.


4. 구동 모터 제어 (RPM 변환) (Advanced)#

차량이 곡선을 돌 때, 바깥쪽 바퀴는 안쪽보다 더 빨리 돌아야 합니다.

4.1 좌/우 바퀴 선속도 (\(v_L, v_R\))#

차량의 각속도 \(\omega\)를 각 바퀴의 회전 반경에 곱하여 구합니다.

\[ v_L = \omega \cdot r_L, ~~~ v_R = \omega \cdot r_R \]

4.2 모터 명령값 (eRPM) 변환#

모터 컨트롤러가 이해할 수 있는 전기적 회전수(eRPM)로 변환하는 과정입니다.

  1. Wheel RPM: 선속도를 바퀴 둘레로 나누어 분당 회전수를 구합니다.

\[ rpm = \frac{v\cdot 60}{2\pi R_w} \]
  1. eRPM: 모터의 극쌍수(p)를 곱합니다.

\[ eRPM = p\times rpm \]

5. 조향 서보 제어 (PWM 변환) (Advanced)#

계산된 조향각 \(\delta\)를 서보 모터가 인식하는 PWM 펄스폭(pulse_us)으로 매핑합니다.

  • Center(직진): \(\delta=0\)이면 \(1500\,\mu\mathrm{s}\)

  • 변환 식:

\[ pulse\_us=1500-\delta\cdot(\frac{600}{\delta_{\max}}) \]
  • 안전 장치: 계산된 값은 항상 \(900\sim2100\,\mu\mathrm{s}\) 범위로 clamp(제한) 처리합니다.

부호 정리

\(\kappa>0\)(좌회전)일 때 \(\delta>0\)이므로 pulse_us\(1500\,\mu\mathrm{s}\)보다 작아지고, \(\kappa<0\)(우회전)일 때는 \(1500\,\mu\mathrm{s}\)보다 커집니다.


6. 제어 순서 (Advanced)#

사용자가 \((v, \omega)\)를 입력하면 시스템은 내부적으로 다음 과정을 거칩니다.

  1. 곡률 변환: \(\kappa=\omega/v\)로 변환(정지 근처에서는 \(\kappa=0\)).

  2. 곡률 해석: \(\kappa\)를 통해 목표 회전 반경 \(r\) 설정.

  3. 기하학 계산: \(r\)\(L,T\)를 이용해 좌/우 바퀴의 조향각 계산.

  4. 한계 검사: 조향각이 \(\delta_{max}\)를 초과하는지 확인 후 클램핑 및 역산.

  5. 속도 분배: 목표 속도 \(v\)를 좌/우 바퀴 속도(\(v_L, v_R\))로 차등 분배.

  6. 명령 출력: 최종적으로 eRPM(구동)과 PWM(조향) 신호를 하드웨어로 전송.


7. 운용 (Advanced)#

  • 보드는 응답(ACK) 없이 마지막으로 수신한 \((v,\kappa)\)를 계속 적용합니다. 제어 루프가 멈췄을 때도 차량이 계속 움직일 수 있으니, 호스트(PC)에서 데드맨(타임아웃) 처리를 해주는 것을 권장합니다.

  • 정지시키려면 \((v,\omega)=(0,0)\)을 보내는 방식이 가장 확실합니다.

  • 속도 입력 \(v\)는 내부에서 평활화(moving average 10개)되며, \(|v| \le v_{\max}\)로 제한됩니다. (빠르게 바뀌는 명령은 즉시 그대로 따라가지 않을 수 있습니다.)