개발 일지/자율주행 개발일지

자율주행 개발일지 03

Woouuk 2026. 5. 27. 18:31

pi0-FAST 모델 학습 결과 ADE/FDE가 6점대에서 2점대 중반까지 내려왔다. 하지만 마냥 좋지 않았다..

html 기반 visualized한 첫 학습 결과

 

전방에 장애물이 많으면 값이 튀는걸 볼 수 있다.

 

로스는 성공적으로 떨어졌다. 하지만 데이터 전처리 과정에 문제가 있어 제대로 학습하지 못했다,,

바로 target인 waypoint가 gps 절대좌표 상의 waypoint였고, 당연히 로컬 waypoint로는 추론이 불가능했던 것.

(보면 GT와 PRED 값의 시작점이 많이 벌어져있다. 절대좌표 vs 상대좌표이기 때문)

 

또한 실패 원인으로 input data로 [전방 이미지,  instruction, waypoint] 세 개를 주고, 데이터 셋도 적은 에피소드에서 동일한 상황으로 그 외 메트릭들을 filtering한 것이 크다고 생각했다.(유연하게 적용하지 못할 거니까 생각해보면 당연하다. 수학 문제도 새로운 유형을 많이 연습하지 않으면 풀지 못하지)

poc 단계였어도 episode 하나를 정해 프레임을 잘라 학습시켰는데 이는 무모했던 것 같다,, 

그래서 데이터 명세와 전처리의 중요성을 실감하고 이를 제대로 잡으려 한다.

기존 실패 원인 분석들 ㅠ

 

 

먼저 LeRobot yaaki-v3 dataset의 column들을 보면 아래와 같다.

 

  • observation.* : 모델 입력 후보
    • speed: ego 속도(단위 따로 없음)
    • heading: 차량의 진행 방향(0~360 범위)
    • heading_error: (기준 경로 대비 차량 heading 오차, 0.2인 값들이 많아 radian일 수 있음)
    • hp_loc_latitude: 고정밀 위치 latitude
    • hp_loc_longitude: 고정밀 위치 longtitude
    • hp_loc_altitude: 고도
    • acceleration_x: 촤량 좌표계 x축 가속도로 전후방향
    • acceleration_y: 좌우방향
      • 여기서부터는 환경상태 컬럼
    • state.lanes: 차선 수
    • state.road: 도로 타입(고속도로 등)
    • state.surface: 노면(아스팔트, 흙 등)
    • state.max_speed: 제한속도(string 값임.. 왜지?)
    • state.precipitation: 강수량, 강수 강도 계열
    • state.conditions: 날씨 상태(clouds, clear, rain, snow)
    • state.lighting: 조명 상태(day, dawn, dark)
      • 여기서부터는 waypoints
    • state.waypoint: shape [10, 2]
    • readme 설명 상 future waypoints는 openstreetmap graph에 snap된 미래 경로점
    • longitude, latitude로 되어있음. (위의 고정밀 위치에서 이 값을 뺀 값을 상대 경로로서 예측하게 주면 될 거 같음)
    • [waypoint_abs_lonlat -> ego position 기준 local ENU 좌표 -> ego heading 기준 rotate] - gpt 추천
    • task.* : instruction/policy 조건
      • policy: student와 expert 두 종류(운전자의 숙련도로 보임)
      • instructions: 자연어 instruction
    • action.* : 모방 학습의 정답 라벨
      • continuous: float 라벨로 0,1,2 세 개의 index 존재
      • 가속 페달 입력, 브레이크 패달 입력, 조향각 세 개로 존재
      • discrete: int 라벨로 기어와 방향지시등 상태
    • 샘플링 메타데이터들
      • 이미지 컬럼 - 전방, 좌우 2개씩 , 후방 , 그리고 지도까지 총 7개
      • timestamp, frame_index, episode_index, index - 시퀀스 정렬/샘플링용 메타데이터

우선 모델이 다양하게 학습할 수 있게 입력 모달리티를 추가했다. waypoint 예측을 고려했을 때, ego 값으로서 speed, heading_error, acceleration_x/y, max_speed를 추가하였다. 

 

다음으로 ego 위치 값(0, 0)부터 시작해서 예측을 시키면 초기 값은 (0, 0)으로 고정되므로 Loss가 쉬워질 수 있는 것을 고려했다. 따라서 ego로부터 한 스텝 다음부터 시작하는 t+0.5s(실제 0.5초 간격은 아님)와 같은 한 스텝 다음 지점에서 시작하는게 좋다.

비디오를 보면 한 영상당 약 최대 30초 간격, 한 에피소드의 최대 시간. 평균 간격은 약 190프레임, 19초10fps이므로 0.5s를 프레임 단위로 잡고, offset은 5프레임 단위로 5, 10, 15, 20… 으로 주고자 하였다.

또한 동일 에피소드 기준 마지막 지점에 도착 시 그 다음 값들이 없어 mask 처리가 되므로영상에서 마지막 부분은 자르고, 타겟 값만 주고자 한다. (10개의 웨이포인트를 찍으므로 5초 자름)또한 영상 평균 주기가 19초인데 정규분포를 따를 확률이 높아 5초로 통일하려 한다.

 

당연히 기존의 waypoint는 절대좌표였으므로 이번엔 lat과 lon, 그리고 heading 값으로 타겟 라벨을 상대좌표로 바꿔주었다. 

 

마지막으로 filtering 과정을 거쳐 각 에피소드를 나누고, straitified sampling으로 골고루 뽑고, 이를 round-robin 방식으로 모델에게 골고루 먹여주고자 하였다.(어차피 LoRA이기 때문이다.)

 

아, 프레임도 각 에피소드별로 약 2hz로 제한을 두었다. 동일 에피소드에 여러 프레임이 필요없기도 하고, 무엇보다 우리 자원으로 너무 오래 걸리기 때문이다 ㅠㅠ

 

아래와 같이 명세를 작성하여 데이터를 추출했다.

 

모델 입력:

  • observation.images.left_forward
  • observation.images.front_left
  • observation.images.right_forward
  • observation.state.vehicle[0] speed
  • observation.state.vehicle[6] acceleration_x
  • observation.state.vehicle[7] acceleration_y
  • observation.state.max_speed
  • task.instructions

target 전처리용:

  • observation.state.vehicle[1] heading
  • observation.state.vehicle[3] hp_loc_latitude
  • observation.state.vehicle[4] hp_loc_longitude
  • observation.state.waypoints

필터링/샘플링용:

  • task.policy
  • episode_index
  • frame_index
  • timestamp
  • observation.state.road
  • observation.state.surface
  • observation.state.precipitation
  • observation.state.conditions
  • observation.state.lighting
  • observation.state.lanes

일단 제외:

  • heading_error
  • hp_loc_altitude
  • action.continuous
  • action.discrete
  • observation.images.map

데이터셋 filtering 기준

state.lanes = 1 or 2

state.road = motorway, trunk, primary, secondary, tertiary 5개

state.surface = 아스팔트 고정

max_speed = NA 제외 자유

precipitation = 자유

condition = clouds, clear 2 종류

lighting = day 고정

task.policy = expert 고정

aciont - dont care

episode_index = straitified sampling로 에피소드 추추하고 이 안에서 2~3hz 정도 프레임 추출

에피소드 당 38프레임(2hz)에서 1000 에피소드 정도

 

이제 이 데이터셋으로 학습을 시켜보고 오겠다.