AEGLOSLAB ROS 2 Jazzy 대전

제8부 항법

8.5 플래너·컨트롤러 플러그인

8.5.1 이 장에서 배우는 것 / 선수 지식

8.1.7에서 "Nav2를 쓴다는 것은 플러그인을 고르는 것"이라고 했다. 그중 가장 중요한 선택이 플래너(전역 경로)와 컨트롤러(지역 제어)다.

이 선택이 중요한 이유는 명확하다. 로봇의 기구학이 다르면 갈 수 있는 경로가 다르다. 차동 구동 로봇은 제자리 회전이 되지만 자동차형은 안 되고, 전방향 로봇은 옆으로 갈 수 있다. 기구학을 모르는 플래너가 만든 경로는 로봇이 따라갈 수 없다.

배우는 것:

  • 플래너와 컨트롤러의 역할 분담 — 무엇을 누가 하는가.
  • 플래너 카탈로그 — NavFn·Smac 계열·기타.
  • 기구학별 선택 — 차동·전방향·아커만.
  • 컨트롤러 카탈로그 — DWB·RPP·MPPI.
  • 보조 플러그인 — 목표 검사기·진척 검사기·평활기.
  • 선택 가이드 — 로봇에서 플러그인으로.
  • 튜닝 요점 — 각 컨트롤러의 핵심 파라미터.

선수 지식: 8.4(코스트맵), 8.1(Nav2 구조), 6.5.6(이동 로봇 컨트롤러·/cmd_vel), 5.1.7(프레임).

정직: 플러그인 목록·파라미터는 배포판마다 추가·변경되며, 특히 MPPI·Smac 계열은 비교적 새롭다. 아래는 개념과 선택 기준에 집중하며, 정확한 파라미터는 Nav2 문서가 정본이다(확인 필요). 성능 비교 수치는 인용하지 않는다(3.6.1).

실행 확인(2026-08-16): Nav2 1.3.12를 설치해 플러그인 등록 이름을 실물과 대조했다. 이 장이 대는 플러그인은 전부 실재하나 표기 형식에 오류가 있어 정정했다 — 아래 함정 참조. 파라미터 이름·기본값·동작은 여전히 미검증이다.

함정 — pkg/Class가 아니라 pkg::Class다(실행 확인). Nav2 플러그인 이름을 "nav2_navfn_planner/NavfnPlanner"처럼 슬래시로 적은 자료가 인터넷에 아직 많고, 이 책도 그렇게 적고 있었다(정정함). 현재 Nav2(1.3.12)의 플러그인 XML은 <class type="nav2_navfn_planner::NavfnPlanner" …>만 등록하며 name= 속성이 없다. pluginlib은 name이 없으면 type을 조회 이름으로 쓰므로, 슬래시 형태는 조회에 실패한다 — 증상은 "플러그인을 찾을 수 없다"는 기동 실패다. nav2_smac_planner::SmacPlannerHybrid·nav2_behaviors::Spin(8.7) 등 전부 같다. 오래된 튜토리얼을 복사할 때 가장 먼저 확인할 지점이며, 확실한 방법은 해당 패키지의 plugins.xml을 직접 열어 type을 보는 것이다.

다만 이것을 ROS 2 전체의 규칙으로 일반화하지 말라(실행 확인). 같은 날 MoveIt 2(2.12.4)를 확인해 보니 정반대였다 — MoveIt의 플러그인 XML은 name="occupancy_map_monitor/PointCloudOctomapUpdater"처럼 슬래시 조회 이름을 그대로 유지한다. 패키지마다 다르다. 규칙은 하나뿐이다 — 그 패키지의 플러그인 XML을 열어 name이 있으면 그것을, 없으면 type을 쓴다.

8.5.2 역할 분담

목표 자세 플래너 전역 코스트맵 경로(Path) 기하학적 웨이포인트 열 컨트롤러 지역 코스트맵 속도 명령(Twist) 로봇
축플래너컨트롤러
입력전역 코스트맵 + 목표경로 + 지역 코스트맵
출력기하 경로속도 명령
시야지도 전체로봇 주변
주기낮음(1 Hz·이벤트)높음(20 Hz)
고려도달 가능성·거리동역학·즉각 장애물
시간대개 없음있음(속도·가속)

핵심 구분: 플래너는 "어디로", 컨트롤러는 "어떻게".

함정: 플래너가 만든 경로를 컨트롤러가 못 따라갈 수 있다. 차동 구동 로봇에 홀로노믹 경로를 주면, 컨트롤러가 근사해서 따라가려다 진동하거나 실패한다. 둘의 기구학 가정이 일치해야 한다 — 이것이 선택의 핵심이다.

8.5.3 플래너 카탈로그

플래너기구학특징
NavFn홀로노믹 가정다익스트라·A*, 빠름·검증됨
Smac 2D홀로노믹 가정격자 A*, NavFn 대안
Smac Hybrid-A*아커만·차동기구학 제약 반영, 후진 지원
Smac State Lattice임의 기구학사전 정의 모션 프리미티브
Theta*홀로노믹격자 제약 없는 직선 경로

실물 등록 이름(실행 확인, Nav2 1.3.12): nav2_navfn_planner::NavfnPlanner · nav2_smac_planner::SmacPlanner2D · nav2_smac_planner::SmacPlannerHybrid · nav2_smac_planner::SmacPlannerLattice · nav2_theta_star_planner(별도 패키지). 위 표의 다섯 항목이 전부 실재한다.

planner_server:
  ros__parameters:
    expected_planner_frequency: 1.0
    planner_plugins: ["GridBased"]

    GridBased:
      plugin: "nav2_navfn_planner::NavfnPlanner"
      tolerance: 0.5
      use_astar: false
      allow_unknown: true

Smac Hybrid-A* 예:

    GridBased:
      plugin: "nav2_smac_planner::SmacPlannerHybrid"
      tolerance: 0.25
      downsample_costmap: false
      allow_unknown: true
      max_iterations: 1000000
      motion_model_for_search: "DUBIN"      # 또는 "REEDS_SHEPP"(후진 허용)
      angle_quantization_bins: 72
      minimum_turning_radius: 0.4           # ★ 로봇 최소 회전 반경
      reverse_penalty: 2.0
      change_penalty: 0.0
      non_straight_penalty: 1.2
      cost_penalty: 2.0
      analytic_expansion_ratio: 3.5
      smooth_path: true

핵심 차이 — 기구학 반영:

플래너만드는 경로
NavFn·Smac 2D격자 위 자유 경로(제자리 회전 가정)
Smac Hybrid-A*최소 회전 반경을 지키는 곡선
Smac Lattice정의된 모션 조합
예 (차동 · 전방향) 예 아니오 (아커만) 로봇 기구학 제자리 회전 가능? NavFn · Smac 2D 충분한 경우가 많다 Smac Hybrid-A* 필수 좁은 공간에서 정밀 기동? Smac Hybrid-A* 검토

견해: 차동 구동 실내 로봇에는 NavFn으로 시작해도 충분한 경우가 많다. 빠르고 검증됐고 튜닝이 단순하다. Smac Hybrid-A*는 아커만 조향이나 후진이 필요한 경우, 또는 좁은 공간에서 정밀한 기동이 필요할 때 값을 한다.

함정: minimum_turning_radius를 로봇 실제 값보다 작게 설정하면 못 따라가는 경로가 나온다. 차동 구동은 0으로 둘 수 있지만, 아커만은 실측값을 넣어야 한다.

함정: allow_unknown이 참이면 미지 영역을 통과하는 경로가 나온다(8.4.2). 탐사 로봇에는 맞지만, 안전이 중요하면 거짓으로 두는 것을 검토한다.

8.5.4 컨트롤러 카탈로그

컨트롤러방식특징
DWB궤적 샘플링 + 평가검증됨·플러그인 가능한 평가자(critic)
RPP(Regulated Pure Pursuit)기하학적 추종단순·부드러움, 경로 추종 우선
MPPI샘플링 기반 최적화강력, 계산 비용 큼
Rotation Shim보조큰 각도 차이를 먼저 회전으로
Graceful(확인 필요)부드러운 자세 수렴 제어실물에 nav2_graceful_controller::GracefulController로 실재(실행 확인). 이 책은 다루지 않는다

실물 등록 이름(실행 확인): dwb_core::DWBLocalPlanner · nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController · nav2_mppi_controller::MPPIController · nav2_rotation_shim_controller::RotationShimController · nav2_graceful_controller::GracefulController.

controller_server:
  ros__parameters:
    controller_frequency: 20.0
    controller_plugins: ["FollowPath"]

    FollowPath:
      plugin: "nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController"
      desired_linear_vel: 0.5
      lookahead_dist: 0.6
      min_lookahead_dist: 0.3
      max_lookahead_dist: 0.9
      use_velocity_scaled_lookahead_dist: true
      # 규제(regulation) — 속도를 줄이는 조건
      use_regulated_linear_velocity_scaling: true
      regulated_linear_scaling_min_radius: 0.9    # 곡률이 크면 감속
      use_cost_regulated_linear_velocity_scaling: true
      # 충돌 검사
      max_allowed_time_to_collision_up_to_carrot: 1.0

8.5.4.1 DWB

궤적을 여러 개 샘플링해 각각을 점수화한다.

    FollowPath:
      plugin: "dwb_core::DWBLocalPlanner"
      max_vel_x: 0.5
      max_vel_theta: 1.5
      acc_lim_x: 2.5
      acc_lim_theta: 3.2
      vx_samples: 20
      vtheta_samples: 40
      sim_time: 1.7
      critics: ["RotateToGoal", "Oscillation", "BaseObstacle",
                "GoalAlign", "PathAlign", "PathDist", "GoalDist"]
      PathAlign.scale: 32.0
      GoalAlign.scale: 24.0
      PathDist.scale: 32.0
      GoalDist.scale: 24.0
      BaseObstacle.scale: 0.02

평가자(critic)가 DWB의 핵심이다:

Critic평가
PathDist경로와의 거리
PathAlign경로 방향 정렬
GoalDist목표와의 거리
GoalAlign목표 방향 정렬
BaseObstacle장애물 비용
Oscillation진동 방지
RotateToGoal목표 근처에서 방향 정렬

견해: DWB의 critic 스케일 튜닝은 상호작용이 복잡하다. 한 값을 높이면 다른 행동이 바뀌고, 조합이 많아 시행착오가 길어진다. 처음 쓴다면 RPP가 튜닝이 단순하다 — 파라미터가 적고 각각의 의미가 직관적이다.

8.5.4.2 RPP (Regulated Pure Pursuit)

경로 앞의 한 점(carrot)을 향해 조향한다.

로봇 위치 경로에서 lookahead_dist 앞의 점 그 점을 향하는 원호 계산 선속도 · 각속도 규제: 곡률·비용·근접에 따라 감속
파라미터효과
lookahead_dist작으면 정밀 추종·진동 위험, 크면 부드럽지만 코너 절단
use_velocity_scaled_lookahead_dist속도에 비례해 조정
regulated_linear_scaling_min_radius급커브에서 감속
use_cost_regulated_...장애물 근처에서 감속

견해: RPP는 "경로를 잘 따라가는" 것을 우선한다. 플래너가 좋은 경로를 만들었다면 잘 동작하고, 결과가 부드럽다. 반면 경로에서 크게 벗어난 회피는 잘 못한다 — 그것이 필요하면 DWB나 MPPI를 검토한다.

8.5.4.3 MPPI

여러 궤적을 샘플링해 비용을 최소화하는 제어를 찾는다.

    FollowPath:
      plugin: "nav2_mppi_controller::MPPIController"
      time_steps: 56
      model_dt: 0.05
      batch_size: 2000
      vx_max: 0.5
      wz_max: 1.9
      motion_model: "DiffDrive"        # 또는 Omni · Ackermann
      critics: ["ConstraintCritic", "ObstaclesCritic", "GoalCritic",
                "GoalAngleCritic", "PathAlignCritic", "PathFollowCritic",
                "PathAngleCritic", "PreferForwardCritic"]
축평가
회피 성능강력 — 복잡한 상황 대응
부드러움좋음
계산 비용높음(배치 크기·시간 단계에 비례)
기구학모델 선택 가능
튜닝critic 다수

정직: MPPI의 계산 부하는 상당하며, 임베디드 보드에서 20 Hz를 유지할 수 있는지 확인이 필요하다(확인 필요). batch_size·time_steps를 줄이면 부하가 줄지만 성능이 떨어진다. 도입 전에 목표 하드웨어에서 주기를 측정하라.

견해: MPPI는 "회피가 중요하고 계산 여유가 있을 때" 선택한다. 사람이 많은 환경, 동적 장애물이 잦은 곳에서 강점이 있다. 반대로 정적 환경에서 단순 경로를 따라가는 용도라면 RPP가 경량이고 충분하다.

8.5.5 기구학별 선택

로봇플래너컨트롤러비고
차동 구동(실내)NavFn·Smac 2DRPP 또는 DWB가장 흔한 조합
차동 + 동적 환경NavFnMPPI회피 강화
전방향(메카넘)NavFn·Smac 2DDWB(omni)·MPPI(Omni)측면 이동 활용
아커만(자동차형)Smac Hybrid-A*RPP·MPPI(Ackermann)최소 회전 반경
트랙터·견인Smac Lattice전용특수 기구학
좁은 공간 정밀Smac Hybrid-A*MPPI후진 활용
# 전방향 로봇 — DWB 설정 예
    FollowPath:
      plugin: "dwb_core::DWBLocalPlanner"
      max_vel_x: 0.5
      max_vel_y: 0.5            # ★ 측면 이동 허용
      vy_samples: 10

함정: 전방향 로봇인데 max_vel_y: 0.0으로 두면 측면 이동을 안 쓴다. 반대로 차동 구동인데 y 속도를 허용하면 로봇이 따라갈 수 없는 명령이 나간다. 기구학과 설정이 일치해야 한다.

8.5.6 보조 플러그인

8.5.6.1 목표 검사기(Goal Checker)

"도착했다"를 판정한다.

controller_server:
  ros__parameters:
    goal_checker_plugins: ["general_goal_checker"]
    general_goal_checker:
      plugin: "nav2_controller::SimpleGoalChecker"
      xy_goal_tolerance: 0.25
      yaw_goal_tolerance: 0.25
      stateful: true
파라미터의미
xy_goal_tolerance위치 허용 오차
yaw_goal_tolerance방향 허용 오차
stateful위치를 먼저 만족하면 그 뒤 방향만

함정: 허용 오차가 너무 작으면 도착 판정을 못 해 계속 미세 조정한다. 측위 정확도(8.3)보다 작게 설정하면 원리적으로 불가능하다. 측위 오차의 2~3배가 현실적이다.

견해: stateful: true가 유용하다. 위치에 도달한 뒤 제자리에서 방향만 맞추므로, 위치와 방향을 동시에 만족시키려 진동하는 것을 막는다.

8.5.6.2 진척 검사기(Progress Checker)

"진전이 없다"를 감지한다.

    progress_checker_plugins: ["progress_checker"]
    progress_checker:
      plugin: "nav2_controller::SimpleProgressChecker"
      required_movement_radius: 0.5
      movement_time_allowance: 10.0

10초 안에 0.5 m를 못 움직이면 실패로 판정하고, BT가 복구를 시작한다(8.6·8.7).

함정: 이 값이 너무 엄격하면 정상적인 느린 기동(좁은 곳 정밀 조작)에서 실패한다. 반대로 너무 느슨하면 갇힌 것을 오래 못 알아챈다. 로봇 속도와 환경에 맞춰 조정한다.

8.5.6.3 평활기(Smoother)

smoother_server:
  ros__parameters:
    smoother_plugins: ["simple_smoother"]
    simple_smoother:
      plugin: "nav2_smoother::SimpleSmoother"
      tolerance: 1.0e-10
      max_its: 1000
      do_refinement: true

격자 기반 플래너의 계단식 경로를 부드럽게 만든다. RPP처럼 경로를 충실히 따르는 컨트롤러에서 특히 효과가 있다.

8.5.6.4 Rotation Shim

목표 방향과 크게 다를 때 먼저 회전한다.

    FollowPath:
      plugin: "nav2_rotation_shim_controller::RotationShimController"
      primary_controller: "nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController"
      angular_dist_threshold: 0.785        # 45도
      rotate_to_heading_angular_vel: 1.8

견해: 차동 구동 로봇에서 Rotation Shim이 유용하다. 경로가 뒤쪽을 향할 때 곡선으로 선회하는 대신 제자리 회전으로 정렬한 뒤 출발하므로, 동작이 자연스럽고 공간을 덜 쓴다.

8.5.7 선택 절차

시작 기구학 확인 제자리 회전 · 측면 이동 · 최소 회전 반경 플래너 선택 8.5.5 표 컨트롤러 선택 회피 요구 · 계산 여유 기본 파라미터로 시험 속도·가속 한계를 실제 사양으로 목표·진척 검사기 조정 환경별 튜닝 8.8

견해: 속도·가속 한계를 실제 사양으로 설정하는 것(6단계)이 자주 누락된다. 기본값이 로봇보다 빠르면 컨트롤러가 불가능한 명령을 내고, 느리면 성능을 낭비한다. max_vel_x·acc_lim_x 등을 실측·사양으로 채우라 — 5.3.3에서 URDF의 effort·velocity를 실제 값으로 넣으라고 한 것과 같은 논리다.

함정: 컨트롤러의 속도 한계와 velocity_smoother·컨트롤러(ros2_control)의 한계가 일관되어야 한다(6.5.6·8.7). 서로 다르면 예상치 못한 동작이 나온다.

8.5.8 튜닝 요점

컨트롤러별로 먼저 볼 파라미터가 다르다.

증상RPPDWBMPPI
코너를 절단한다lookahead_dist ↓PathDist.scale ↑PathFollowCritic ↑
진동한다lookahead_dist ↑Oscillation 조정샘플·시간 조정
장애물에 너무 가깝다비용 규제 활성BaseObstacle.scale ↑ObstaclesCritic ↑
너무 느리다규제 조건 완화속도 한계 확인속도 한계
목표 근처에서 수렴하지 못한다목표 검사기 허용오차RotateToGoalGoalAngleCritic

정직: 위 표는 일반적 경향이며, 파라미터 상호작용 때문에 예외가 많다(확인 필요). 한 번에 하나씩 바꾸고 결과를 관찰하는 것이 유일하게 확실한 방법이다.

견해: 튜닝 전에 경로 자체를 보라. 컨트롤러가 비정상적으로 움직이는 원인이 플래너의 부적절한 경로인 경우가 많다. RViz2에서 /plan을 표시해 경로가 합리적인지 먼저 확인하고, 그 다음 추종을 본다. 순서를 거꾸로 하면 컨트롤러 파라미터를 헛되이 조정한다.

8.5.9 함정 카탈로그

#함정증상대처
1기구학과 플래너 불일치못 따라가는 경로8.5.5 표
2minimum_turning_radius 부정확아커만이 경로 이탈실측값
3전방향인데 max_vel_y: 0측면 이동 미사용설정 일치
4차동인데 y 속도 허용불가능한 명령0으로
5속도·가속 한계 기본값 방치성능 낭비·불가능 명령실제 사양
6컨트롤러·smoother 한계 불일치예상 밖 동작일관 설정
7목표 허용오차 < 측위 정확도도착 판정 실패2~3배로
8진척 검사기 과엄격정상 기동에서 실패환경에 맞게
9MPPI를 계산 확인 없이주기 미달목표 하드웨어 측정
10DWB critic을 한꺼번에 조정원인 불명하나씩
11경로 확인 없이 컨트롤러 튜닝무익한 작업/plan 먼저
12allow_unknown 무의식적 참미지 통과 경로안전 요구 검토

8.5.10 체크포인트

  • 플래너와 컨트롤러의 역할 분담을 여섯 축으로 비교할 수 있는가. "어디로"와 "어떻게"의 구분은?
  • 플래너가 만든 경로를 컨트롤러가 못 따라가는 경우가 왜 생기는가.
  • 플래너 다섯 가지와 각각의 기구학 가정을 말할 수 있는가. Smac Hybrid-A*가 필요한 경우는?
  • minimum_turning_radius를 잘못 설정하면 무슨 일이 생기는가.
  • DWB의 critic 구조와, 처음 쓰는 사람에게 RPP를 권하는 이유는?
  • RPP의 lookahead_dist가 작을 때·클 때의 트레이드오프는?
  • MPPI의 강점과 대가는? 도입 전에 확인해야 할 것은?
  • 기구학별 플래너·컨트롤러 조합을 여섯 가지 말할 수 있는가.
  • 목표 검사기의 허용오차를 측위 정확도와 어떻게 연관지어야 하는가. stateful의 이점은?
  • 진척 검사기가 하는 일과, 값이 극단적일 때의 각 문제는?
  • Rotation Shim이 차동 구동에서 유용한 이유는?
  • 선택 절차에서 자주 누락되는 단계는 무엇인가.
  • 컨트롤러 튜닝 전에 무엇을 먼저 확인해야 하는가.

다음 장 8.6은 이 모든 것을 조율하는 행동 트리를 다룬다. 왜 상태 기계가 아니라 행동 트리인가, 그리고 기본 트리를 어떻게 읽고 고치는가.