# Vehicle Control Model

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

**Prerequisites**
- Introduction: {doc}`Platform Overview </page/Introduction/intro>`

**Next**
- {doc}`Dashboard Test </page/Setup_Test/dashboard_test>`

---

```{admonition} Conventions
:class: tip

- `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$으로 처리)
```

```{admonition} 참고
:class: note

제한/안전 규약(속도 제한, 권장 곡률 범위, 데드맨 등)은 {doc}`Platform Overview </page/Introduction/intro>` 하단의 “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$으로 표현할 수 있고, 입력 제한이나 조향 포화 계산이 단순합니다.
```{admonition} 부호 규약
:class: tip

- 각속도는 $\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}
$$

2. **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(제한) 처리합니다.

```{admonition} 부호 정리
:class: note

$\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}$로 제한됩니다. (빠르게 바뀌는 명령은 즉시 그대로 따라가지 않을 수 있습니다.)
