대상: 자율주행(모바일 로봇/차량) 소프트웨어 아키텍처를 한 번에 이해하고 싶은 개발자
환경: Ubuntu + ROS/ROS2 기반 자율주행 스택을 가정 (차량/모바일 로봇 공통적으로 적용 가능한 개념 위주)
1. 문제/주제 요약
자율주행 시스템을 공부하다 보면 보통 이렇게 쪼개서 보게 됩니다.
- 센서: LiDAR, 카메라, IMU, GPS…
- 알고리즘: SLAM, Object Detection, Path Planning, MPC…
- 프레임워크: ROS/ROS2, CyberRT, Autoware, Apollo…
근데 **“전체가 어떻게 연결돼서 차가 실제로 굴러가는지”**가 한 번에 머릿속에 안 잡히는 경우가 많습니다.
이 글에서는 센서 → 인지 → 위치추정 → 계획 → 제어 → 차량 인터페이스까지
자율주행 시스템의 큰 구조를 한 장짜리 그림 + 단계별 설명으로 정리합니다.
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
- LiDAR:
여기서 중요한 두 가지:
- 시간 동기화
- 각 센서가 찍은 시간(
timestamp)이 다르면, 같은 “물리적인 순간”을 다르게 보게 됨 - GNSS 타임, NTP, 하드웨어 트리거 등을 이용해 가능하면 같은 시간축에 맞추기
- 각 센서가 찍은 시간(
- 좌표계 관리 (TF / extrinsic calibration)
- LiDAR, 카메라, IMU, 차량 중심(
base_link)이 서로 어디에 어떻게 붙어 있는지 camera_link→base_link→map같은 좌표 변환을 항상 유지
- LiDAR, 카메라, IMU, 차량 중심(
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): 어디로, 어떻게 갈지 정하기
계획은 보통 두 레벨로 나눕니다.
- 행동 계획(Behavior Planning / Decision Making)
- 차선 유지 / 차선 변경 / 정지 / 차단물 회피 / 추월 / U턴 등
- “무엇을 할 것인가?”를 결정
- 경로/궤적 계획(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)를 개별 주제로 파고들면서 기술 스택을 쌓아갈 수 있습니다.