Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions auto_tuner_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# 🥕 CarrotPilot Auto-Tuner 사용 안내

Auto-Tuner는 운전자의 실제 주행 패턴을 학습하여 오픈파일럿의 설정값을 **내 차와 내 운전 습관에 맞게 자동으로 최적화(튜닝)**해주는 스마트한 주행 보조 기능입니다.

---

## 📊 데이터 수집 및 적용 방식

1. **주행 중 데이터 수집 (Learning)**
운전자가 오픈파일럿을 켠 상태로 주행할 때, 시스템은 백그라운드에서 차량의 속도, 가속도, 브레이크 타이밍, 조향 각도 등을 실시간으로 기록합니다. 특히 사용자가 답답함을 느껴 **가속 페달을 직접 밟거나(오버라이드)**, 불안해서 **직접 브레이크를 밟는 개입(Intervention)** 순간을 중점적으로 수집합니다.

2. **패턴 분석 (Analyzing)**
수집된 데이터를 바탕으로 현재 오픈파일럿 설정값이 운전자의 실제 주행 성향과 얼마나 차이나는지 분석하여 이상적인 파라미터 수치를 계산합니다.

3. **추천 및 적용 (Applying)**
주행을 마치고 **기어를 주차(P)로 변경**하면, 분석된 추천 설정값이 팝업으로 안내됩니다. 원하는 항목만 체크하여 **[선택 적용]**을 누르면 즉시 시스템에 반영됩니다. 적용된 내역은 설정 메뉴의 **[튜닝 이력]** 탭에서 언제든지 확인하고 관리할 수 있습니다.

---

## ⚙️ 그룹별 튜닝 설정 안내

Auto-Tuner는 크게 다섯 가지 영역의 주행감을 학습하고 개선합니다.

### 🚀 [가속] (Acceleration)
오픈파일럿의 크루즈 가속 능력(속도 대역별 엑셀 밟는 양)을 조정합니다.
운전자가 특정 속도 구간에서 직접 엑셀을 밟는 시간이 일정 기준(초)을 초과하면, 그 구간의 가속 한계치를 자동으로 올려줍니다.
- **CruiseMaxVals0 [0~10km/h]**: 출발 및 극저속 구간의 가속력
- **CruiseMaxVals1 [10~40km/h]**: 저속 시내 주행 구간의 가속력
- **CruiseMaxVals2 [40~60km/h]**: 중속 구간의 가속력
- **CruiseMaxVals3 [60~80km/h]**: 중고속 구간의 가속력
- **CruiseMaxVals4 [80~100km/h]**: 고속 구간의 가속력
- **CruiseMaxVals5 [100~130km/h]**: 초고속 구간의 가속력
- **CruiseMaxVals6 [130km/h~]**: 최고속 구간의 가속력

### 🚙 [주행] (Driving)
선행 차량과의 간격 유지, 감속 타이밍 등 종방향(브레이크) 제어 능력을 조정합니다.
운전자가 브레이크를 직접 밟아 개입(Intervention)하는 횟수가 누적되면, 시스템이 앞차와의 간격을 더 일찍 벌리거나 브레이크를 더 강하게 밟도록 유도합니다.
- **JLeadFactor3 (감속 및 정지 제어)**: 앞차가 멈추거나 가까워질 때 브레이크를 밟는 타이밍과 강도를 결정합니다. 추천값을 적용하면 오픈파일럿이 조금 더 일찍, 부드럽게 감속을 시작하도록 튜닝되어 늦은 제동으로 인한 불안감을 해소합니다.

### 🛣️ [거리] (Following Distance)
고속도로 장거리 주행 시 선행 차량과의 추종 거리(TFollow)를 최적화합니다.
운전자가 크루즈 인게이지 상태에서 선행차가 있음에도 가속 페달을 자주 밟는 패턴을 학습합니다. 이는 "시스템이 설정된 것보다 지나치게 거리를 넓게 벌려 주행하고 있어, 운전자가 능동적으로 간격을 좁히려 한다"는 신호로 해석합니다. 해당 GAP 단계의 TFollowGap 값을 자동으로 낮춰주어, 운전자가 원하는 더 촘촘한 간격으로 자연스럽게 추종하도록 개선합니다.
- **TFollowGap1 (GAP1, 가장 좁음)**: 공격적 주행 스타일에 적합한 최소 추종 거리 (0.7s 이상)
- **TFollowGap2 (GAP2)**: 일반 주행용 추종 거리
- **TFollowGap3 (GAP3)**: 여유로운 추종 거리
- **TFollowGap4 (GAP4, 가장 넓음)**: 장거리 고속 주행용 최대 추종 거리

### 🎛️ [동적제어] (Dynamic Control)
선행차 또는 내 차의 속도 변화에 따라 차간거리를 **동적으로** 조절하는 파라미터를 학습합니다.
브레이크 관련 파라미터(JLeadFactor3 / DynamicTFollow / TFollowDecelBoost)가 동시에 여러 개 발동되면, 모두 "거리 확대" 방향이므로 합산 시 과보정 위험이 있습니다. 따라서 Auto-Tuner는 **이벤트가 가장 많은 1개만 먼저 추천**하고, 나머지는 다음 세션에서 재평가하도록 안내합니다.
- **DynamicTFollow (앞차 급감속 반응 민감도)**: 앞차가 갑자기 감속할 때 차간거리를 얼마나 빠르게 넓힐지 결정합니다. 앞차의 급격한 속도 감소(jLead < -1.0) 중에 운전자가 직접 브레이크를 밟은 횟수가 쌓이면, 이 값을 높여 시스템이 앞차의 감속에 더 민감하게 반응하도록 합니다. (0이면 동적 조절 없음)
- **TFollowDecelBoost (감속 중 추가 간격 확보)**: 내 차가 강하게 감속하는 상황에서 속도가 줄어들면 실제 거리 여유도 함께 줄어들게 됩니다. 강감속(a_ego < -0.8 m/s²) 중에 브레이크 개입이 반복되면 이 값을 높여, 감속이 강할수록 자동으로 더 넉넉한 간격을 유지하도록 보완합니다. (기본값 10, 범위 0~100)

### 🔄 [조향] (Steering)
직진 주행 시의 쏠림 현상과 곡선(커브) 도로에서의 핸들링 반응성을 조정합니다.
- **PathOffset (직진 편차)**: 직선 도로를 달릴 때 운전자가 지속적으로 핸들을 미세하게 한쪽으로 당기고 있는 패턴을 분석합니다. 차가 미세하게 좌측이나 우측으로 쏠려서 주행한다고 판단되면 차선 내 중앙 위치(Offset)를 보정합니다.
- **SteerActuatorDelay (조향 반응 지연)**: 커브 진입 시 오픈파일럿의 조향이 늦어 운전자가 핸들을 직접 꺾어(오버라이드) 궤적을 수정하는 패턴을 학습합니다. 잦은 오버라이드가 발생하면 액추에이터의 지연 시간(Delay) 변수를 늘려, 선행 조향각을 더 공격적으로 꺾어주어 빠르고 날카로운 코너링을 수행하도록 최적화합니다.
- **SteerRatioRate (조향비율 배율)**: SteerActuatorDelay를 올려도 커브 추종이 개선되지 않고 오버라이드 빈도가 여전히 매우 높은 경우, 조향력 자체가 부족한 것으로 판단합니다. LiveParameters에서 측정된 실제 차량의 조향비(SR)에 추가로 배율을 곱해주어, 같은 핸들 각도에서 더 강하게 조향하도록 만들어 코너에서 차선 중앙 유지 능력을 개선합니다.

---

## ℹ️ 참고: 커브 구간 속도 제어
커브 구간에서 고정된 속도 제한은 직선 주행에서는 답답하고, 급커브에서는 불안할 수 있습니다. CarrotPilot은 **오픈파일럿 모델이 예측하는 도로 곡률(Curvature)**을 실시간으로 읽어 커브의 강도에 따라 가속을 자동으로 제한하는 **동적 커브 속도 제어(Adaptive Curve Speed)** 기능을 별도 파라미터로 지원할 예정입니다. 이 기능은 Auto-Tuner와는 별개로 설정 메뉴의 크루즈/속도 탭에서 직접 조정할 수 있습니다.
6 changes: 6 additions & 0 deletions common/params_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ShowPathColorLane", {PERSISTENT, INT, "13"}},
{"ShowPlotMode", {PERSISTENT, INT, "0"}},
{"CarrotTireTrajectory", {PERSISTENT, INT, "0"}},
{"CarrotLearningActive", {PERSISTENT, INT, "0"}}, // Auto-Tuner: 학습 활성화 (0=off, 1=on)
{"CarrotLearningData", {PERSISTENT, BYTES, ""}}, // Auto-Tuner: 누적 데이터 (JSON)
{"CarrotLearningRecommend", {PERSISTENT, BYTES, ""}}, // Auto-Tuner: 추천값 (JSON)
{"CarrotLearningPopupReady", {PERSISTENT, BOOL, "0"}}, // Auto-Tuner: 팝업 신호
{"CarrotLearningClear", {PERSISTENT, BOOL, "0"}}, // Auto-Tuner: 데이터 초기화 신호
{"CarrotLearningHistory", {PERSISTENT, BYTES, ""}}, // Auto-Tuner: 튜닝 이력 (JSON)
{"RecordRoadCam", {PERSISTENT, INT, "0"}},
{"HDPuse", {PERSISTENT, INT, "0"}},

Expand Down
73 changes: 73 additions & 0 deletions karpathy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.

**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.

## 1. Think Before Coding

**Don't assume. Don't hide confusion. Surface tradeoffs.**

Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

## 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**

- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

## 3. Surgical Changes

**Touch only what you must. Clean up only your own mess.**

When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

## 4. Goal-Driven Execution

**Define success criteria. Loop until verified.**

Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

---

**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.

## 5. Domain-Specific Verification (Openpilot / Cereal)

**Never guess dynamic schemas. Verify against existing patterns.**

When working with Openpilot's `cereal` (Cap'n Proto) framework or similar dynamic data structures:
- **No Blind Imports:** Do not assume standard Python directory structures (e.g., `from cereal.car import CarState`). `cereal` generates objects dynamically from `.capnp` schemas.
- **Cross-Reference Usage:** Before using a new attribute or enum (e.g., `GearShifter`), always `grep` or `view_file` existing Openpilot codebase to see exactly how it is imported and referenced (e.g., `from cereal import car` -> `car.CarState.GearShifter.park`).
- **Assume Local Context Blindness:** Understand that local Mac environments often lack the `capnp` libraries or hardware dependencies required to test Openpilot code locally. Because local unit tests cannot catch `AttributeError` or `ModuleNotFoundError` for these hardware schemas, extreme caution and code-pattern matching must be used before committing.
24 changes: 24 additions & 0 deletions selfdrive/carrot/carrot_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from openpilot.common.conversions import Conversions as CV
from openpilot.common.filter_simple import MyMovingAverage
from openpilot.selfdrive.selfdrived.events import Events
from openpilot.selfdrive.carrot.carrot_learning import CarrotLearner

EventName = log.OnroadEvent.EventName
LaneChangeState = log.LaneChangeState
Expand Down Expand Up @@ -139,6 +140,7 @@ def __init__(self):

self._stop_x_rl = None
self.last_event_time = 0.0
self.learner = CarrotLearner()

def _params_update(self):
self.frame += 1
Expand Down Expand Up @@ -628,6 +630,28 @@ def update(self, sm, v_cruise_kph, mode):
self.mode = mode
#return v_cruise, stop_dist, mode

# Auto-Tuner: 학습 데이터 수집
from cereal import car
gear_park = carstate.gearShifter == car.CarState.GearShifter.park
engaged = sm.alive.get('selfdriveState', False) and sm['selfdriveState'].enabled

# 현재 GAP 단계 파악 (Personality 기반)
personality = sm['selfdriveState'].personality
current_gap = 2 # default standard
if personality == log.LongitudinalPersonality.moreRelaxed: current_gap = 4
elif personality == log.LongitudinalPersonality.relaxed: current_gap = 3
elif personality == log.LongitudinalPersonality.standard: current_gap = 2
elif personality == log.LongitudinalPersonality.aggressive: current_gap = 1
self.learner.set_current_gap(current_gap)

self.learner.update(v_ego_kph, carstate.gasPressed, engaged, gear_park,
steer_deg=carstate.steeringAngleDeg, steer_pressed=carstate.steeringPressed,
brake_pressed=carstate.brakePressed,
lead_drel=leadOne.dRel if leadOne.status else 0.0,
lead_v_kph=leadOne.vLead * CV.MS_TO_KPH if leadOne.status else 0.0,
a_ego=a_ego, lead_jlead=leadOne.jLead if leadOne.status else 0.0,
v_cruise_kph=v_cruise_kph)

return v_cruise_kph

class DrivingModeDetector:
Expand Down
Loading
Loading