Post

Velocity Planner: 곡률로 속도 프로파일 입히기

Velocity Planner: 곡률로 속도 프로파일 입히기

경로 최적화가 끝나면 “어디로 주행할지”는 정해지지만, 각 지점에서 “얼마나 빠르게 달릴지”는 아직 정해지지 않습니다. Velocity Planner는 이 고정된 경로(Waypoints) 위에 곡률(curvature)을 기준으로 각 지점의 목표 속도 프로파일(vx, ax)을 입히는 알고리즘입니다. 경로의 모양은 그대로 두고 속도만 결정한다는 점에서, 경로 최적화와는 분리된 독립적인 단계입니다.

본 포스트에서는 곡률로부터 속도를 도출하는 원리, 경험적으로 튜닝하는 마찰 한계(GGV), 가속·감속을 모두 반영하는 Forward–Backward 계산을 차례로 살펴보며, UNICORN Racing의 velocity planning 과정에 대해서 다룹니다.

무엇을 풀어야 하는가

UNICORN Racing 팀은 다양한 주행 상황에 robust하게 대응하기 위해 여러 플래너를 함께 사용하며, 각 플래너가 내놓은 경로에는 공통의 Velocity Planner로 속도를 입힙니다.

목표: 오버슛이나 의도하지 않은 슬립이 없는 주행

목표 속도를 코너의 물리적 한계보다 높게 잡으면 차량이 라인을 벗어나거나 타이어가 접지력을 잃게 되므로, 속도 프로파일은 반드시 차량이 실제로 낼 수 있는 동역학적 제약 안에서 결정되어야 합니다.

문제: 동역학적 제약을 정확히 알기 어려움

  • 타이어-노면 마찰, 서스펜션, 구동계 응답을 모두 담은 정밀한 차량 동역학 모델을 확보하기는 현실적으로 쉽지 않습니다.
  • 노면 상태나 타이어 컨디션에 따라 그 값이 달라지기도 합니다.

해결: 마찰 한계의 경험적 튜닝

모델을 정밀하게 구하는 대신, 타이어가 낼 수 있는 마찰 한계를 실제 주행 데이터로부터 경험적으로 튜닝합니다. 주행에서 관측된 한계를 표로 정리해 두고, 곡률만 주어지면 그 표를 참조해 안전한 속도를 계산하는 구조입니다.

핵심 아이디어 — 정확한 동역학 모델을 추정하는 대신, 타이어의 종·횡 가속도 한계(GGV)를 주행 데이터로 경험적으로 튜닝합니다. 속도는 이 한계와 경로의 곡률만으로 결정되므로, 특정 점이나 구간에 종속되지 않고 어떤 경로에도 동일하게 적용할 수 있습니다.

곡률에서 속도를 도출하는 원리

곡률과 속도의 관계

곡률이 큰(급한) 코너에서는 속도를 낮추고, 곡률이 작은(완만한) 구간에서는 속도를 높입니다. 코너를 도는 데 필요한 횡가속도가 타이어의 횡가속 한계를 넘지 않아야 하므로, 각 지점의 곡률 $\kappa$ 와 횡가속 한계 $a_{y,max}$ 로부터 코너링 상한 속도가 정해집니다.

\[v_{max}(i) = \sqrt{\frac{a_{y,max}}{|\kappa(i)|}}\]

이 값은 코너링 한계만 고려한 이론적 상한이며, 여기에 가속·감속 능력을 반영해 실제 주행 가능한 프로파일로 다듬는 과정이 이어집니다.

GGV: 경험적으로 튜닝하는 마찰 한계

속도별 종·횡 가속도 한계를 나타낸 GGV 다이어그램 속도별 종·횡 가속도 한계를 나타낸 GGV 다이어그램 (개념 이해를 돕기 위한 예시, 실제 설정과는 다름)

타이어가 낼 수 있는 종방향(가·감속)과 횡방향(코너링) 가속도의 조합은 하나의 마찰 한계 안에 갇힙니다. 속도별로 이 한계를 정리한 표가 GGV(ggv.csv)이며, 각 행은 속도와 그때의 종가속 한계 $a_{x,max}$, 횡가속 한계 $a_{y,max}$ 로 이루어집니다. 이 값들은 정밀 모델에서 유도한 것이 아니라, 주행 데이터를 보며 슬립이나 오버슛이 나타나지 않는 선까지 경험적으로 조정한 결과입니다.

GGV는 속도별로 한계를 담을 수 있는 표 구조이지만, UNICORN Racing 팀은 모든 속도에서 타이어가 동일한 능력을 낸다고 가정하고 튜닝합니다. 즉 ggv.csv의 모든 행이 같은 $a_{x,max}$·$a_{y,max}$ 값을 가지며(현재 5.0·4.5 m/s²), 튜닝은 속도별 곡선을 맞추는 대신 이 단일 한계값을 조정하는 방식으로 이루어집니다.

종·횡 가속도가 동시에 발생할 때 그 조합이 얼마나 허용되는지는 Generalized Friction Circle 모델로 표현합니다.

\[\left(\frac{a_x}{a_{x,max}}\right)^p + \left(\frac{a_y}{a_{y,max}}\right)^p \leq 1\]

이 관계로부터, 코너에서 이미 횡가속도 $a_{y,used}=v^2/r$ 를 쓰고 있을 때 남는 종방향 가속도는 다음과 같이 줄어듭니다.

\[a_{x,avail} = a_{x,max} \left(1 - \left(\frac{a_{y,used}}{a_{y,max}}\right)^p\right)^{1/p}\]

직선 구간에서는 횡가속도가 없어 종가속을 최대로 쓸 수 있지만, 코너로 들어가 조향이 커질수록 가용 종가속도가 줄어듭니다. 지수 $p$(dyn_model_exp)는 이 마찰 한계의 형태를 결정하며, 값이 작을수록(1.0에 가까울수록) 코너 중 가속을 더 보수적으로 제한합니다. 현재 UNICORN Racing Stack은 dyn_model_exp: 1.0을 기본값으로 두고, 노면 상태에 따라 이 값을 미세하게 변형해가며 사용합니다.

Forward–Backward 두 방향 계산

Forward pass·Backward pass와 최종 속도 프로파일 Forward pass·Backward pass와 두 결과의 최소값으로 얻는 최종 속도 프로파일

코너링 상한 속도만으로는 부족합니다. 한 지점에서 다음 코너에 맞춰 미리 감속해야 하고, 코너를 빠져나온 뒤에는 가속 능력만큼만 속도를 올릴 수 있기 때문입니다. 이 가속·감속 제약을 반영하기 위해 경로를 두 방향으로 훑습니다.

  • Forward pass: 시작점부터 진행하며, 각 지점에서 이용 가능한 종가속도로 낼 수 있는 최대 속도를 앞으로 전파합니다.
  • Backward pass: 끝점부터 역행하며, 다음 지점의 목표 속도에 맞춰 안전하게 감속할 수 있는 속도를 뒤로 전파합니다.

두 방향 모두 속도 갱신은 등가속도 관계 $v_{i+1}=\sqrt{v_i^2 + 2\,a_x\,\Delta s}$ 로 이루어지며, 각 지점의 최종 속도는 두 결과 중 더 작은 값으로 정합니다.

\[v_{final}(i) = \min(v_{forward}(i),\, v_{backward}(i))\]

Forward–Backward pass를 거치면 코너링 한계, 가속 한계, 감속 한계가 한 프로파일에서 동시에 만족됩니다. 이때 이용 가능한 종가속도에는 타이어 마찰뿐 아니라 모터·브레이크 성능(ax_max_machines, b_ax_max_machines)까지 함께 반영되며, 이 값들도 GGV와 마찬가지로 경험적으로 튜닝한 한계값을 사용합니다.

이 방식이 강점인 이유

이 파이프라인의 핵심은 속도가 경로의 곡률과 튜닝된 마찰 한계에만 의존한다는 점입니다. 여기에서 몇 가지 실전적 이점이 따라옵니다.

전역적으로 재사용 가능한 속도 세팅 — 속도가 곡률의 함수이므로, 특정 트랙이나 특정 구간에 맞춘 값이 아니라 곡률만 주어지면 어떤 경로에도 그대로 입힐 수 있습니다. 한 번 튜닝한 GGV로 여러 경로에 균일한 속도 성능을 낼 수 있습니다.

경로가 바뀌어도 같은 한계를 재적용합니다. 최소 곡률(IQP)이나 최단 거리(SP)로 최적화된 global raceline은 물론, 회피·추월 상황에서 다른 planner가 생성한 경로에도 곡률 정보만 있으면 동일한 Velocity Planner를 그대로 적용할 수 있습니다. 경로마다 속도 규칙을 따로 정의할 필요가 없으므로, 스택 전반에서 일관된 주행 특성을 유지합니다.

대회 현장에서 빠르게 속도를 갱신할 수 있습니다. 연습 시간이 부족한 대회에서는 매 경로마다 속도를 세밀히 손보기 어렵습니다. 타이어를 교체하거나 맵을 다시 만들거나, 에어컨 바람에 트랙 바닥이 미끄러워지는 등 주행 조건은 수시로 바뀝니다. 이런 상황마다 GGV와 모터·브레이크 한계 몇 개 값만 조정하면 전 구간의 속도 프로파일이 한 번에 다시 계산됩니다. 실제로 global_velocity_planner.py/global_waypoints를 구독해 곡률로부터 속도를 재계산하고 다시 발행하므로, 경로 최적화를 처음부터 다시 돌리지 않고도 현장에서 튜닝한 한계값을 전체 스택에 즉시 반영할 수 있습니다. 덕분에 다양한 현장 조건에 효율적이면서도 일관되게 대응할 수 있습니다.

어디에서 쓰이는가

Velocity Planner

관련 코드: race_utils/f110_utils/libs/vel_planner/vel_planner/vel_planner.py

경로의 곡률(kappa)·element length와 함께 마찰 한계(GGV)·모터 한계(ax_max_machines)·브레이크 한계(b_ax_max_machines)를 배열로 입력받아, forward–backward pass로 속도 프로파일을 계산해 돌려줍니다.

기본적으로 사용하는 input: stack_master/config/<racecar_version>/veh_dyn_info/

CSV내용형식
ggv.csv마찰 한계속도별 ax_max, ay_max
ax_max_machines.csv모터(구동) 한계속도별 ax_max_machines
b_ax_max_machines.csv브레이크(제동) 한계속도별 ax_max_machines

UNICORN Racing 팀은 모든 속도에서 같은 한계값을 사용하도록 튜닝합니다.

활용 방법

  • planner/gb_optimizer/
    calc_vel_profile 호출을 통해 기본 input CSV와 최적화된 경로의 곡률을 넘겨 raceline에 속도를 부여하고, vx_mps가 포함된 /global_waypoints로 발행합니다.
  • state_machine/state_machine/state_machine_node.py
    calc_vel_profile 호출을 통해 planner의 출력 경로에 기본 input CSV와 곡률을 기반으로 속도를 부여하며, safety factor로 종방향 가·감속 여유를 조정합니다.
  • stack_master/scripts/global_velocity_planner.py
    calc_vel_profile 호출 시 노드 내에서 튜닝한 input 값을 넘겨, /global_waypoints의 곡률로부터 속도를 재계산·재발행합니다.

global_velocity_planner.py는 CSV 대신 노드 내부의 하드코딩 값으로 한계를 덮어써, CSV를 직접 고치지 않고도 실시간으로 튜닝할 수 있습니다.

1
2
3
4
5
6
7
# ---- tune here: hardcoded limits override the ini/csv values ----
self.v_max = 12.0
self.ax_max_motor = 7.0
self.ax_max_brake = 8.0
self.dyn_model_exp = 1.0
self.a_y_max = 6.5
self.a_x_max = 9.0

여기서 v_max·ax_max_motor·ax_max_brake·dyn_model_exp·a_y_max·a_x_max 여섯 값을 조정하면, 노드가 /global_waypoints의 곡률로부터 속도 프로파일을 다시 계산해 발행하므로 재최적화 없이 결과를 즉시 확인할 수 있습니다. save_csv:=true로 실행하면 튜닝한 한계값이 veh_dyn_info/의 세 CSV로 저장되어 이후 다른 노드들이 참조하는 기본값으로도 반영됩니다.

주행 중 global_velocity_planner.py로 튜닝하는 영상

파라미터 튜닝

각 파라미터의 의미와 튜닝 방법은 아래 문서에 자세하게 설명되어 있습니다.

참고: Velocity Planner (UNICORN Racing docs)

마무리

Velocity Planner는 고정된 경로 위에 곡률과 경험적으로 튜닝한 마찰 한계(GGV)만으로 속도 프로파일을 입히는 단계입니다. 코너링 상한을 곡률로 정하고, Forward–Backward pass로 가속·감속 한계까지 반영하면 어떤 경로에도 동일하게 적용할 수 있는 일관된 속도 세팅이 완성됩니다. 현장에서는 global_velocity_planner.py로 몇 개의 한계값만 조정해 전 구간의 속도를 즉시 갱신할 수 있으며, 이 튜닝이 곧 주행 성능을 좌우하는 핵심 작업이 됩니다.

This post is licensed under CC BY 4.0 by the author.