# SDK Guide

**What you’ll do**
- C++ SDK를 빌드하고 예제 코드를 실행하여 하드웨어 동작을 확인합니다.
- `Driver` 클래스를 사용해 차량에 주행 명령($v, \omega$)을 전송하는 방법을 익힙니다.
- 차량의 상태(속도, 배터리 등)를 수신하고 처리하는 구조를 이해합니다.

**Prerequisites**
- 포트/권한 준비(주로 Ubuntu): {doc}`Linux Port Setup </page/Setup_Test/linux_port_setup>`
- 하드웨어 기본 동작 확인: {doc}`Dashboard Test </page/Setup_Test/dashboard_test>`

**Next**
- Driver 기반 튜토리얼: {doc}`Driver Tutorials </page/SDK/tutorials/driver_tutorials>`
- ROS2 노드 튜토리얼: {doc}`ROS2 Driver Tutorials </page/SDK/tutorials/ros2_driver_tutorials>`
- 공개 API 상세: {doc}`C++ API Reference </page/SDK/sdk_reference>`
- 단위/부호/기하: {doc}`Vehicle Control Model </page/Introduction/control_model>`
- UART(저수준) 기반 튜토리얼(선택): {doc}`Advanced UART Tutorials </page/SDK/tutorials/uart_tutorials>`
- 프로토콜(바이트 레벨): {doc}`UART Protocol Reference </page/Protocol/uart_protocol>`

---

## 1. SDK 구성

SDK는 사용 목적에 따라 두 가지 레벨의 인터페이스를 제공합니다. 대부분의 자율주행 알고리즘 개발에는 `Driver` 클래스 사용을 권장합니다.

- `Driver` (Recommended)
  - 내부 스레드가 **명령 입력**, **속도 요청**, **보조 명령**을 주기적으로 처리합니다.
  - 수신 데이터는 메시지 큐로 전달됩니다.
  
- `UartClient` (Advanced)
  - 사용자가 송수신 시점과 파싱을 직접 제어해야 하는 Low-Level 클래스입니다.
  - 통신 프로토콜 디버깅, 커스텀 스케줄링 구현, 또는 Driver 구조를 사용할 수 없는 특수한 환경.
  - `Driver`는 `UartClient`로 구현되어있습니다.

```{admonition} 권장 사용 패턴
:class: tip

- 기본: `Driver` (I/O 스레드, 수신 큐, 타임아웃 포함)
- `UartClient`를 쓰는 경우: 프레임 단위 타이밍을 직접 제어하거나, **보조 명령** (`0xAF`)을 직접 실험 및 디버깅할 때
```

---

## 2. 빌드와 첫 동작 확인
- github repository에서 sdk를 clone합니다.
```bash
git clone https://github.com/Seo12044/KAIST_Mobility_Challenge_SDK.git
cd KAIST_Mobility_Challenge_SDK/
```

SDK 리포지토리 루트에서 빌드합니다.

### 2.1 Linux 빌드

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
```

### 2.2 동작 테스트

빌드가 완료되면 기본 예제인 `driver_demo`를 실행하여 연결을 확인합니다.

```bash
./build/driver_demo
```

```{admonition} 주의
:class: warning

초기 테스트는 바퀴가 공중에 뜬 상태(또는 아주 낮은 속도)에서 진행하세요. 
```

예제 구성:
- 속도 읽기(**속도 요청**): `read_speed`
- 배터리 전압/AllState(**보조 명령**): `read_battery`, `read_allstate`
- `Driver` 큐 처리: `driver_observe`
- 고속 성능 확인: `high_rate_control`

---

## 3. **명령 입력**

SDK는 **선속도($v$)와 각속도($\omega$)** 를 입력받습니다.`Driver`의 `setCommand(v, omega)`를 호출하여 차량을 제어합니다.
- $v$ (`velocity_mps`): $\mathrm{m/s}$
- $\omega$ (`omega_rps`): $\mathrm{rad/s}$, $\omega>0$이면 `CCW`, $\omega<0$이면 `CW`

`Driver::setCommand(v, omega)` 호출 시, SDK는 다음 수식을 통해 전송 패킷을 생성합니다.

$$
\kappa =
\begin{cases}
\omega / v, & |v| > 10^{-3} \\
0, & |v| \le 10^{-3}
\end{cases}
$$

여기서 $\kappa$의 단위는 $\mathrm{m}^{-1}$입니다. 부호/기하 의미는 {doc}`Vehicle Control Model </page/Introduction/control_model>`에 정리되어 있습니다.

---

## 4. Timing & Safety
안정적인 제어를 위해 하드웨어 송신 주기와 사용자 명령 업데이트 주기를 구분하여 이해해야 합니다.

### 4.1 주요 설정 파라미터 (`Driver::Options`)
필드별 의미/기본값은 {ref}`Driver::Options <sdk-driver-options>`에 정리되어 있습니다.

|파라미터|설명|권장 값|
|---|---|---|
|`control_rate_hz`|Driver가 하드웨어로 명령 패킷을 보내는 주기|$200 \sim 400\,\mathrm{Hz}$|
|`vehicle_speed_rate_hz`|Driver가 하드웨어에 현재 속도를 요청하는 주기|$50\,\mathrm{Hz}$ (필요에 따라 조절)|
|`command_timeout_ms`|사용자 명령 업데이트가 끊길 경우 정지하는 시간|$200\,\mathrm{ms}$|

$$
command\_timeout\_ms \approx \max(50,\ 2 \cdot \frac{1000}{command\_hz})
$$

예를 들어 $command\_hz=50\,\mathrm{Hz}$이면, $command\_timeout\_ms \approx 200\,\mathrm{ms}$가 됩니다.

---

## 5. 수신 데이터 처리

### 5.1 Driver 큐 사용
`Driver`는 수신된 UART 패킷을 파싱하여 **메시지 큐**에 저장합니다. 사용자는 메인 루프에서 이 큐를 비우며 데이터를 처리해야 합니다.

```cpp
while (auto msg = drv.tryPopMessage()) {
  if (auto* vs = std::get_if<KMC_HARDWARE::VehicleSpeed>(&*msg)) {
    // vs->mps : 차량 속도 (m/s)
  } else if (auto* st = std::get_if<KMC_HARDWARE::AllState>(&*msg)) {
    // st->error_code : 에러 코드(bitmask)
  }
}
```

`AllState.error_code`의 비트 정의는 {doc}`UART Protocol Reference </page/Protocol/uart_protocol>`의 AllState 섹션을 따릅니다.

### 5.2 UartClient 폴링 사용

`UartClient`는 요청을 보낸 뒤 `poll(timeout_ms)`로 응답을 받아 처리하는 구조입니다. **명령 입력**과 **속도 요청**, **보조 명령**의 스케줄링을 직접 구현할 때 사용합니다.

---

## 6. 고속 제어

$1\,\mathrm{kHz}$ 수준의 고속 제어가 필요한 경우, 시스템 설정을 최적화해야 합니다.
* **Baud Rate 상향**: $921{,}600\,\mathrm{bps}$ 또는 $1{,}000{,}000\,\mathrm{bps}$ 사용 권장.
* **Realtime Priority** (Linux): 스레드 스케줄링 지연을 줄이기 위해 Driver 옵션에서 realtime_priority를 설정하십시오 (root 권한 필요 가능성 있음).
---

## Troubleshooting
{doc}`UART Troubleshooting </page/Troubleshooting/uart_troubleshooting>`
