자율주행 시스템 : 센서부터 제어까지

대상: 자율주행(모바일 로봇/차량) 소프트웨어 아키텍처를 한 번에 이해하고 싶은 개발자
환경: Ubuntu + ROS/ROS2 기반 자율주행 스택을 가정 (차량/모바일 로봇 공통적으로 적용 가능한 개념 위주)


1. 문제/주제 요약

자율주행 시스템을 공부하다 보면 보통 이렇게 쪼개서 보게 됩니다.

  • 센서: LiDAR, 카메라, IMU, GPS…
  • 알고리즘: SLAM, Object Detection, Path Planning, MPC…
  • 프레임워크: ROS/ROS2, CyberRT, Autoware, Apollo…

근데 **“전체가 어떻게 연결돼서 차가 실제로 굴러가는지”**가 한 번에 머릿속에 안 잡히는 경우가 많습니다.

이 글에서는 센서 → 인지 → 위치추정 → 계획 → 제어 → 차량 인터페이스까지
자율주행 시스템의 큰 구조를 한 장짜리 그림 + 단계별 설명으로 정리합니다.


2. 원인/배경 설명

자율주행 시스템은 대략 아래 3가지 관점으로 나눠보면 이해가 쉽습니다.

  1. 데이터 흐름 관점
    • 센서 데이터가 들어와서 → 인지/위치 추정 → 경로 계획 → 제어 명령 → 차량
  2. 시간/주기 관점
    • 센서는 주기적으로 데이터를 뿌리고, 각 모듈은 **실시간(또는 준실시간)**으로 처리해야 함
  3. 소프트웨어 모듈 관점
    • “센서 드라이버 / 인지 / 위치추정 / 계획 / 제어 / 시스템 관리” 같은 모듈로 쪼갤 수 있음

결국 구조를 한 문장으로 줄이면:

“센서로 주변/자기 상태를 이해하고,
그 정보로 ‘어디로 갈지’를 계획해서,
실제 차량을 그 계획대로 움직이게 만드는 파이프라인”

이라고 볼 수 있습니다.


3. 자율주행 전체 구조: 센서부터 제어까지

먼저 큰 그림을 텍스트 블록으로 보면 대략 이런 구조입니다.

[센서층]
  ├─ LiDAR / Radar
  ├─ Camera
  ├─ IMU / Wheel Encoder
  └─ GNSS(GPS)

        │ (Raw data)
        ▼

[센서 드라이버 & 동기화]
  ├─ 시간 동기화 (Timestamp, NTP, GNSS Time)
  └─ 좌표 변환 관리 (TF, extrinsic calibration)

        │ (동기화 & 캘리브된 센서 데이터)
        ▼

[인지(Perception)]
  ├─ 장애물/차량/보행자 인식 (Detection)
  ├─ 추적(Tracking)
  ├─ 차선/도로 구조 인식
  └─ 자유 공간 / Occupancy Grid

        │
        ├──► [지도/위치(Localization & Mapping)]
        │        ├─ SLAM / HD Map Localization
        │        └─ 차량의 현재 위치/자세 (pose)
        │
        ▼

[예측(Prediction)]
  └─ 주변 객체들의 미래 움직임 예측

        │ (현재 상태 + 미래 예측)
        ▼

[계획(Planning)]
  ├─ 행동 계획 (차선 변경, 정차, 추월 등 High-level)
  └─ 경로/궤적 계획 (Trajectory Planning, Local Path)

        │ (실제로 따라갈 궤적)
        ▼

[제어(Control)]
  ├─ 종방향 제어 (속도, 가감속)
  └─ 횡방향 제어 (조향)

        │ (steer, throttle, brake 명령)
        ▼

[차량 인터페이스(Vehicle Interface)]
  └─ CAN / LIN / DBW (Drive-by-Wire) 등

이제 각 부분을 조금씩 파고 들어가 봅니다.


3-1. 센서층: 환경과 자기 상태를 읽는 눈/귀

대표 센서들:

  • LiDAR: 거리/3D 포인트 클라우드, 장애물/지형 인지에 강함
  • Radar: 상대 속도/거리, 악천후에 강함 (비/안개/눈)
  • Camera: 차선, 신호등, 표지판, 객체 인식 등 시각 정보
  • IMU: 각속도/가속도 → 자세/관성 추정
  • Wheel Encoder, Steering Sensor: 바퀴 회전수, 조향각 → 속도 추정, Odometry
  • GNSS(GPS/RTK): 전역 위치 (위도/경도/고도)

실제로는 센서 하나만으로는 부족해서 여러 개를 조합합니다(센서 퓨전).


3-2. 센서 드라이버 & 동기화

센서는 하드웨어라서, OS/ROS에서 쓰려면 드라이버가 필요합니다.

  • sensor_driver_node
    • LiDAR: /points_raw
    • Camera: /image_raw
    • IMU: /imu/data
    • GPS: /gps/fix

여기서 중요한 두 가지:

  1. 시간 동기화
    • 각 센서가 찍은 시간(timestamp)이 다르면, 같은 “물리적인 순간”을 다르게 보게 됨
    • GNSS 타임, NTP, 하드웨어 트리거 등을 이용해 가능하면 같은 시간축에 맞추기
  2. 좌표계 관리 (TF / extrinsic calibration)
    • LiDAR, 카메라, IMU, 차량 중심(base_link)이 서로 어디에 어떻게 붙어 있는지
    • camera_linkbase_linkmap 같은 좌표 변환을 항상 유지

ROS/ROS2에서는 보통 tf / tf2 프레임으로 좌표 변환을 관리합니다.


3-3. 인지(Perception): 주변 환경/객체 이해

목표: “지금 내 주변에 뭐가 어디에 있는지”를 아는 것.

주요 기능:

  • 객체 인식(Object Detection)
    • 차량, 보행자, 자전거, 정지된 물체 등
    • Camera 기반, LiDAR 기반, 또는 센서 퓨전
  • 추적(Tracking)
    • 이전 프레임과 연결해서 각 객체의 속도/방향 추정
  • 차선/도로 구조 인식
    • 차선 위치, 차선 타입, 도로 경계
  • 자유 공간 / Occupancy Grid
    • 갈 수 있는 공간 / 갈 수 없는 공간을 Grid로 표현

출력 예시(논리적인 형태):

  • /perception/objects:
    • {id, type, position, velocity, bounding box...} 리스트
  • /perception/lane_markings:
    • 차선 다항식/좌표 목록
  • /perception/obstacle_grid:
    • Occupancy Grid Map

이 정보는 **계획(Planning)**과 **예측(Prediction)**의 입력이 됩니다.


3-4. 위치추정 & 지도(Localization & Mapping)

목표: “지도 위에서 지금 내가 어디에 있는지(pose) 정확히 아는 것”

활용 기술:

  • SLAM (LiDAR / Visual SLAM)
    • 지도와 위치를 동시에 만들어가는 경우 (지도 없음 / 동적 환경)
  • HD Map 기반 Localization
    • 이미 만들어진 고정밀 지도를 기준으로 내 위치를 추정
  • 센서 융합
    • IMU + Wheel Odometry + GNSS + LiDAR/Camera → 필터링(EKF/UKF)

출력:

  • /localization/pose:
    • 보통 map 좌표계 기준의 차량 위치/자세 (x, y, z, roll, pitch, yaw)
  • /localization/velocity:
    • 속도 정보

이 정보는 전 모듈의 기준 좌표가 되기 때문에,
정확도/안정성이 시스템 전체 퀄리티를 좌우한다고 해도 과언이 아닙니다.


3-5. 예측(Prediction): 주변 객체의 미래 행동 예측

목표: “앞차/보행자가 앞으로 몇 초 후 어디에 있을지” 예측

입력:

  • 현재 인지 정보(객체의 위치/속도/종류)
  • 도로 구조/차선 정보
  • 과거 궤적(Tracking 정보)

출력:

  • 각 객체별 future trajectories (예: 3초, 5초 후까지)
  • 객체별 위험도 / 충돌 가능성

이 단계가 있어야, 계획 모듈이 “미래 상황”을 고려한 궤적을 만들 수 있습니다.


3-6. 계획(Planning): 어디로, 어떻게 갈지 정하기

계획은 보통 두 레벨로 나눕니다.

  1. 행동 계획(Behavior Planning / Decision Making)
    • 차선 유지 / 차선 변경 / 정지 / 차단물 회피 / 추월 / U턴 등
    • “무엇을 할 것인가?”를 결정
  2. 경로/궤적 계획(Path / Trajectory Planning)
    • 실제로 따라갈 **연속적인 궤적(x(t), y(t), v(t), yaw(t))**을 생성
    • 장애물 회피, 차선 준수, 편안함(가속/조향 제한) 고려

입력:

  • 현재 위치/속도 (/localization/pose)
  • 인지 정보 (/perception/*)
  • 예측 정보 (/prediction/*)
  • 고정밀 지도/HD Map 혹은 경로 (/map/route)

출력 예시:

  • /planning/trajectory:
    • 일정 시간동안의 (t, x, y, v, yaw, curvature …) 시퀀스

이 궤적은 **제어(Control) 모듈이 따라가야 할 “목표 값”**이 됩니다.


3-7. 제어(Control): 계획된 궤적을 실제 차량으로

목표: “계획된 궤적을 최대한 정확하고 안정적으로 따라가게”

주요 구성:

  • 종방향 제어(Longitudinal)
    • 속도/거리 제어
    • 입력: 현재 속도, 목표 속도/가속도
    • 출력: 스로틀(throttle), 브레이크(brake) 명령
    • PID, LQR, MPC 등 사용
  • 횡방향 제어(Lateral)
    • 조향 제어 (Steering)
    • 입력: 현재 위치/자세, 궤적, 차량 모델
    • 출력: 조향각(steering angle)
    • Pure Pursuit, Stanley, MPC 등 사용

출력은 보통 아래와 같은 형식의 메시지로 표현됩니다.

/vehicle/control_cmd
  ├─ steering_angle
  ├─ throttle
  └─ brake

이 명령을 실제 차량/로봇 하드웨어에 전달하는 게 Vehicle Interface의 역할입니다.


3-8. 차량 인터페이스(Vehicle Interface)

목표: 소프트웨어 명령을 실제 차량 액추에이터로 연결

  • CAN / LIN / FlexRay 등 버스 프로토콜로 차량 ECU와 통신
  • Drive-by-Wire(조향/브레이크/스로틀 전자 제어) 시스템과 연결
  • 종종 “안전 제어 계층(안전 컨트롤러)”이 별도로 있어서
    • 명령이 이상할 때 차량을 정지시키거나, 운전자에게 제어를 넘기는 역할도 포함

ROS/ROS2에서는 /vehicle/status, /vehicle/control_cmd
실제 차량 CAN 메시지로 변환하는 노드가 존재하게 됩니다.


3-9. 시스템/플랫폼 관점: ROS/ROS2, 미들웨어, ECU 분할

실제 차량 수준 자율주행에서는, 위 모듈들을 단일 PC에 때려넣지 않습니다.

  • 센서 ECU
  • Perception ECU
  • Planning/Control ECU
  • Safety ECU

등으로 나누고, 사이에 DDS/ROS2, 자체 미들웨어, Ethernet 등을 이용해 통신합니다.

ROS/ROS2 기반의 연구/프로토타입에서는 보통:

  • 하나의 PC 혹은 2~3개의 PC에 노드를 분산 배치
  • DDS/ROS2 토픽으로 모듈 간 통신
  • launch 파일로 전체 시스템을 한 번에 bring-up

하는 식으로 사용합니다.


4. 추가 팁 / 자주 하는 실수

4-1. 모듈 경계를 애매하게 두는 경우

  • 인지/위치/계획/제어의 역할이 겹치면 디버깅이 매우 힘들어집니다.
  • “이 값은 어느 레이어에서 책임지는가?”를 명확히 나누어 설계하는 게 중요합니다.
    • 예: 장애물 필터링은 Perception 책임인지, Planning에서 다시 할 건지?

4-2. 시간 동기화와 좌표계(TF)를 가볍게 보는 경우

  • 센서 타임스탬프/TF 잘못 설정 →
    • SLAM 튀고, 인지 결과가 엉뚱한 곳에 찍히고, 제어도 이상해짐
  • **“이 데이터는 어느 시점, 어느 좌표계 기준인가?”**를 항상 의식하는 습관이 중요합니다.

4-3. 플래닝 결과를 차량이 못 따라가는 설계

  • 차량의 물리 제약(최대 조향, 최대 가속/감속)을 고려 안 하고 궤적을 생성하면
    • 제어기가 그 궤적을 물리적으로 따라갈 수 없음
  • Planning에서 차량 동역학/제한을 고려한 궤적을 만들어야
    • Control이 안정적으로 작동합니다.

4-4. 시뮬레이션만 믿는 경우

  • 시뮬레이터에서는 센서 노이즈/오차가 현실보다 과하게 단순함
  • 실제 차량/로봇에서는
    • GNSS 튀고, IMU 바이어스 생기고, LiDAR/Camera 가려지고, 네트워크 딜레이도 발생
  • 반드시 시뮬레이션 → 실차/실기기로 단계적으로 검증해야 합니다.

5. 정리

  • 자율주행 시스템은 센서 → 드라이버/동기화 → 인지 → 위치추정 → 예측 → 계획 → 제어 → 차량 인터페이스의 파이프라인으로 이해하면 전체 구조가 한 번에 잡힙니다.
  • 각 모듈은 “어떤 입력을 받아 어떤 출력을 내는지”가 명확해야, 디버깅과 확장이 쉬워집니다.
  • 시간 동기화, 좌표계 관리, 차량 동역학 고려는 초반에 대충 넘어가면 나중에 크게 발목을 잡는 부분이니, 아키텍처 설계 단계에서부터 신경 쓰는 것이 좋습니다.
  • 이 큰 틀만 머릿속에 들어오면, 이후에는 각 레이어(예: Perception, Localization, Planning)를 개별 주제로 파고들면서 기술 스택을 쌓아갈 수 있습니다.

댓글 남기기