Navigation 파라미터

1. TurtleBot3 소스 설치

cd ~/turtlebot3_ws/src

ROBOTIS의 Git 사이트에 접속하여 ROS2 humble용 TurtleBot3 소스를 다운로드 합니다.

git clone -b humble https://github.com/ROBOTIS-GIT/turtlebot3.git
git clone -b humble https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git
git clone -b humble https://github.com/ROBOTIS-GIT/DynamixelSDK.git

의존성이 필요한 경우 설치합니다.

cd ~/turtlebot3_ws
rosdep update
rosdep install --from-paths src --ignore-src -r -y

빌드를 수행합니다.

cd ~/turtlebot3_ws
colcon build --symlink-install

workspace를 활성화 합니다.

source /opt/ros/humble/setup.bash
source ~/turtlebot3_ws/install/setup.bash

아래의 명령으로 어떤 패키지가 사용되는지를 확인합니다.

ros2 pkg prefix turtlebot3_navigation2

반대로 이렇게 나오면 apt 설치본이 사용 중입니다.

/opt/ros/humble

2. TurtleBot3 Navigation 파라미터를 이해해야 하는 이유

TurtleBot3에서 Navigation을 실행하면 로봇은 단순히 목적지를 향해 움직이는 것이 아닙니다. 로봇은 먼저 자신의 위치를 알아야 하고, 지도 위에서 목적지까지 갈 수 있는 경로를 계산해야 하며, 주행 중 나타나는 장애물을 피해야 하고, 목표 지점에 도착했는지도 판단해야 합니다.

이 모든 과정은 ROS 2 Navigation2, 즉 Nav2가 담당합니다. Nav2는 하나의 프로그램이 아니라 여러 기능 노드가 묶인 시스템입니다. 각 노드는 자신의 역할을 수행하고, 그 동작 방식은 YAML 파라미터 파일로 결정됩니다.

TurtleBot3 Navigation에서 파라미터가 중요한 이유는 실제 로봇의 움직임이 이 값들에 의해 크게 달라지기 때문입니다.

예를 들어 로봇이 너무 빠르게 움직인다면 max_vel_x 값을 줄여야 합니다. 장애물에 너무 가까이 붙는다면 inflation_radius를 조정해야 합니다. 목표 지점 근처에서 계속 빙글빙글 돌거나 흔들린다면 xy_goal_tolerance, yaw_goal_tolerance, RotateToGoal 관련 값을 확인해야 합니다. 지도 위에서 로봇 위치가 자꾸 틀어진다면 AMCL의 파티클, 라이다 모델, 오도메트리 오차 파라미터를 봐야 합니다.

초보자는 보통 Navigation이 안 될 때 코드를 의심합니다. 하지만 실제로는 파라미터 문제인 경우가 많습니다. 특히 TurtleBot3처럼 이미 검증된 로봇 플랫폼에서는 기본 코드보다는 환경에 맞지 않는 파라미터 때문에 문제가 발생하는 경우가 많습니다.

따라서 Nav2 파라미터를 이해한다는 것은 단순히 YAML 파일을 읽는 것이 아니라, 로봇의 실제 동작 원리를 이해하는 것과 같습니다.

3. Navigation 파라미터 파일의 기본 구조

Navigation 문제를 해결할 때는 항상 다음 순서로 봐야 합니다.

센서 데이터가 정상인가?

TF 좌표계가 정상인가?

AMCL 위치 추정이 정상인가?

Costmap에 장애물이 정상 표시되는가?

Planner가 경로를 생성하는가?

Controller가 속도 명령을 생성하는가?

로봇 구동부가 실제로 명령대로 움직이는가?

이 순서를 지키면 문제 원인을 훨씬 빠르게 찾을 수 있습니다

Nav2 파라미터 파일은 YAML 형식입니다. YAML은 들여쓰기로 구조를 표현합니다. 따라서 들여쓰기가 틀리면 파라미터가 적용되지 않거나 노드가 실행되지 않을 수 있습니다.

기본 구조는 다음과 같습니다.

node_name:
  ros__parameters:
    parameter_name: value

예를 들어 AMCL 설정은 다음과 같은 형태입니다.

amcl:
  ros__parameters:
    alpha1: 0.2
    alpha2: 0.2
    base_frame_id: "base_footprint"
    global_frame_id: "map"
    odom_frame_id: "odom"

여기서 amcl은 노드 이름입니다. ros__parameters 아래에 들어가는 항목들이 실제 AMCL 노드에 전달되는 파라미터입니다.

YAML에서 문자열은 따옴표를 붙여도 되고 안 붙여도 되는 경우가 많습니다. 하지만 프레임 이름, 플러그인 이름, 토픽 이름은 따옴표를 붙이는 것이 가독성 면에서 좋습니다.

배열은 다음과 같이 표현합니다.

controller_plugins: ["FollowPath"]

또는 여러 줄로 표현할 수도 있습니다.

error_code_name_prefixes:
  - assisted_teleop
  - backup
  - compute_path

중첩 구조도 자주 사용됩니다.

FollowPath:
  plugin: "dwb_core::DWBLocalPlanner"
  max_vel_x: 0.3

이 경우 FollowPath는 controller plugin의 이름이고, 그 아래에 해당 플러그인의 세부 파라미터가 들어갑니다.

초보자가 가장 많이 하는 실수는 특정 파라미터를 잘못된 위치에 넣는 것입니다. 예를 들어 max_vel_x는 controller plugin인 FollowPath 아래에 있어야 의미가 있습니다. 엉뚱하게 controller_server 바로 아래에 넣으면 원하는 대로 적용되지 않을 수 있습니다.

4. Navigation 전체 흐름

TurtleBot3 Navigation은 여러 노드가 협력해서 동작합니다.

첫째, map_server가 저장된 지도를 불러옵니다.

둘째, amcl이 라이다와 오도메트리를 이용해 로봇의 현재 위치를 추정합니다.

셋째, planner_server가 현재 위치에서 목표 위치까지의 전역 경로를 생성합니다.

넷째, controller_server가 전역 경로를 따라가기 위한 실제 속도 명령을 생성합니다.

다섯째, local_costmap은 로봇 주변의 장애물을 실시간으로 반영합니다.

여섯째, global_costmap은 전체 지도 기준으로 이동 가능한 영역과 장애물 영역을 관리합니다.

일곱째, behavior_server는 로봇이 막혔거나 실패했을 때 후진, 회전, 대기 같은 복구 행동을 수행합니다.

여덟째, velocity_smoother는 속도 명령을 부드럽게 만들어 실제 로봇이 덜 튀도록 합니다.

아홉째, collision_monitor는 충돌 위험이 가까워졌을 때 정지 또는 감속을 수행합니다.

이 구조를 모르면 파라미터를 제대로 조정하기 어렵습니다. 예를 들어 로봇이 장애물을 피하지 못한다고 해서 무조건 controller만 수정하면 안 됩니다. 실제 원인은 local costmap의 obstacle layer가 라이다 데이터를 제대로 받지 못하는 것일 수 있습니다. 또는 inflation layer가 너무 작아서 장애물 주변의 안전 영역이 충분히 만들어지지 않는 것일 수도 있습니다.

5. AMCL 파라미터

AMCL은 Adaptive Monte Carlo Localization의 약자입니다. 쉽게 말하면 로봇이 지도 위에서 자기 위치를 찾는 기능입니다.

TurtleBot3는 바퀴 엔코더를 통해 이동량을 추정합니다. 하지만 바퀴는 미끄러질 수 있고, 바닥 상태에 따라 오차가 쌓입니다. 그래서 라이다 센서로 주변 벽과 장애물을 관측하고, 지도와 비교하면서 현재 위치를 보정합니다. 이 역할을 AMCL이 합니다.

대표 파라미터는 다음과 같습니다.

base_frame_id: "base_footprint"
global_frame_id: "map"
odom_frame_id: "odom"

global_frame_id는 전역 기준 좌표계입니다. 보통 map을 사용합니다.

odom_frame_id는 오도메트리 기준 좌표계입니다. 보통 odom을 사용합니다.

base_frame_id는 로봇 본체 좌표계입니다. TurtleBot3에서는 base_footprint 또는 base_link가 자주 사용됩니다.

이 세 좌표계가 맞지 않으면 Navigation은 바로 꼬입니다. RViz에서 TF가 끊겨 보이거나, 로봇 위치가 지도 밖에 표시되거나, 목표를 찍어도 움직이지 않는 문제가 생깁니다.

1) AMCL의 파티클 파라미터

AMCL은 로봇의 위치 후보를 여러 개 뿌려 놓고, 센서 데이터와 잘 맞는 후보를 남기는 방식으로 동작합니다. 이 위치 후보를 파티클이라고 합니다.

min_particles: 500
max_particles: 2000

min_particles는 최소 파티클 수입니다.

max_particles는 최대 파티클 수입니다.

파티클 수가 많으면 위치 추정이 더 안정적일 수 있습니다. 하지만 CPU 사용량도 증가합니다. TurtleBot3처럼 소형 로봇에서 너무 큰 값을 사용하면 시스템이 느려질 수 있습니다.

먼저 기본값으로 실행한 뒤, RViz에서 AMCL 파티클 분포를 확인합니다. 로봇 위치 주변에 파티클이 적당히 모여 있으면 정상입니다. 파티클이 넓게 퍼져 있거나 엉뚱한 위치에 몰려 있으면 초기 위치 설정, 지도 품질, 라이다 데이터, 오도메트리 상태를 확인해야 합니다.

실습 방법은 다음과 같습니다.

첫째, RViz에서 ParticleCloud를 표시합니다.

둘째, 로봇의 실제 위치와 지도상의 위치가 일치하는지 확인합니다.

셋째, 로봇을 손으로 약간 이동하거나 회전시켜 봅니다.

넷째, AMCL이 다시 위치를 안정적으로 잡는지 확인합니다.

다섯째, min_particles, max_particles 값을 조금씩 조정하면서 반응 차이를 관찰합니다.

처음에는 값을 크게 바꾸지 말고 20~30% 정도만 바꾸는 것이 좋습니다.

2) AMCL의 움직임 오차 파라미터

다음 파라미터는 로봇의 움직임 오차 모델과 관련이 있습니다.

alpha1: 0.2
alpha2: 0.2
alpha3: 0.2
alpha4: 0.2
alpha5: 0.2

이 값들은 로봇이 이동하거나 회전할 때 오도메트리에 어느 정도 불확실성이 있다고 볼 것인지를 결정합니다.

값이 작으면 AMCL은 오도메트리를 더 신뢰합니다.

값이 크면 AMCL은 오도메트리에 오차가 많다고 판단합니다.

바닥이 미끄럽거나 바퀴 슬립이 자주 발생하는 환경에서는 이 값을 조금 키워야 할 수 있습니다. 반대로 오도메트리가 안정적인 환경에서는 너무 크게 잡을 필요가 없습니다.

실습에서는 같은 경로를 반복 주행하면서 로봇 위치 추정이 얼마나 흔들리는지 확인하면 됩니다. 로봇이 실제 위치보다 지도상에서 자주 밀려 보이면 오도메트리와 라이다 보정 상태를 함께 확인해야 합니다.

alpha1
로봇이 제자리에서 회전할 때, 실제 회전량과 오도메트리 회전량 사이의 오차입니다.
예를 들어 로봇이 90도 회전했다고 오도메트리는 말하지만 실제로는 87도 또는 93도 정도 회전했을 수 있습니다.
이런 오차를 크게 볼지 작게 볼지를 alpha1이 정합니다.

alpha2
로봇이 직진했는데도 방향이 틀어지는 오차입니다.
예를 들어 로봇이 앞으로 2m 직진했는데 바퀴 슬립이나 좌우 바퀴 차이 때문에 살짝 오른쪽으로 틀어지는 경우입니다.
즉, 이동 때문에 생기는 회전 오차입니다.

alpha3
로봇이 앞으로 이동할 때 거리 자체가 틀리는 오차입니다.
예를 들어 오도메트리는 2m 이동했다고 하지만 실제로는 1.9m 또는 2.1m 이동했을 수 있습니다.
즉, 직진 거리 오차입니다.

alpha4
로봇이 회전했는데 그 과정에서 위치가 살짝 밀리는 오차입니다.
예를 들어 제자리 회전을 해야 하는데 바퀴 마찰이나 기구 오차 때문에 로봇 중심이 살짝 옆으로 이동하는 경우입니다.
즉, 회전 때문에 생기는 위치 이동 오차입니다.

alpha5
주로 omni wheel, mecanum wheel처럼 옆방향 이동이 가능한 로봇에서 사용하는 오차입니다.
일반적인 차동구동 로봇, 즉 좌우 바퀴로 움직이는 differential drive 로봇에서는 alpha5의 영향이 없거나 거의 의미가 없습니다.
정리하면
차동구동 로봇 기준으로는 보통 이렇게 보면 됩니다.

alpha1: 회전 → 회전 오차
alpha2: 직진 → 회전 오차
alpha3: 직진 → 직진 오차
alpha4: 회전 → 직진 오차
alpha5: 옆방향 이동 오차, 일반 차동구동에서는 거의 사용 안 함

3) AMCL Frame 파라미터

AMCL에서 가장 먼저 봐야 하는 값은 frame 관련 파라미터입니다.

base_frame_id: "base_footprint"
global_frame_id: "map"
odom_frame_id: "odom"

base_frame_id는 로봇 본체 기준 좌표계입니다. TurtleBot3에서는 base_footprint를 많이 사용합니다. 일부 구성에서는 base_link를 사용하기도 합니다. 중요한 것은 실제 TF 트리에 존재하는 프레임 이름과 일치해야 한다는 점입니다.

global_frame_id는 전역 위치 추정 기준입니다. 일반적으로 map입니다. AMCL은 로봇이 지도 위에서 어디에 있는지를 추정하므로 전역 프레임은 map이 됩니다.

odom_frame_id는 오도메트리 기준 프레임입니다. 일반적으로 odom입니다. AMCL은 mapodom 사이의 보정 관계를 만들어 줍니다.

4) AMCL의 라이다 모델 파라미터

AMCL은 라이다 데이터를 사용해 현재 위치를 추정합니다. 관련 파라미터는 다음과 같습니다.

laser_model_type: "likelihood_field"
max_beams: 60
laser_likelihood_max_dist: 2.0
sigma_hit: 0.2
z_hit: 0.5
z_rand: 0.5

laser_model_type은 라이다 관측을 지도와 비교하는 방식을 정합니다. likelihood_field는 Nav2에서 자주 사용되는 방식입니다.

likelihood_field 방식은
라이다 측정값을 이용해서 라이다 끝점을 지도 좌표로 변환합니다.likelihood는 가능도, 즉 “그럴듯함”입니다.
field는 지도 전체에 미리 계산된 점수장이라고 보면 됩니다.
예를 들어 라이다가 전방 2.3m에서 벽을 감지했다면, 현재 particle 위치 기준으로 이 점을 지도 위에 찍습니다.
그다음 이렇게 판단합니다.
“이 라이다 점이 지도상의 장애물, 즉 벽이나 물체와 얼마나 가까운가?”
가까우면 높은 점수.
멀면 낮은 점수.

max_beams는 위치 추정에 사용할 라이다 빔의 개수입니다. 라이다는 많은 거리 데이터를 내보내지만, AMCL이 모든 데이터를 사용하면 계산량이 커집니다. 그래서 일부 빔만 사용합니다.

laser_likelihood_max_dist는 라이다 관측값과 지도상의 장애물 사이의 허용 거리와 관련됩니다.

z_hit, z_rand, z_short, z_max는 라이다 측정값을 해석하는 확률 모델의 가중치입니다.

실습에서는 max_beams를 먼저 확인하는 것이 좋습니다. 값을 너무 낮추면 위치 추정이 거칠어질 수 있고, 너무 높이면 연산량이 증가합니다.

로봇을 실제로 움직이면서 다음을 확인합니다.

로봇이 직진할 때 지도상 위치가 같이 부드럽게 움직이는가?

회전할 때 로봇 방향이 갑자기 튀지 않는가?

복도나 벽 근처에서 위치가 안정적으로 잡히는가?

비슷하게 생긴 공간에서 위치가 헷갈리지 않는가?

위의 상화들을 확인하면서 로봇을 주행하고 결과를 확인합니다.

5) AMCL Update 조건 파라미터

AMCL은 로봇이 조금이라도 움직일 때마다 항상 위치를 갱신하지 않습니다. 이동량 또는 회전량이 일정 기준 이상일 때 업데이트합니다.

update_min_d: 0.25
update_min_a: 0.2

update_min_d는 로봇이 몇 m 이상 이동했을 때 AMCL 업데이트를 수행할지 결정합니다.

update_min_a는 로봇이 몇 rad 이상 회전했을 때 AMCL 업데이트를 수행할지 결정합니다.

update_min_d: 0.25라면 로봇이 25cm 정도 이동해야 위치 업데이트가 수행됩니다.

update_min_a: 0.2는 약 11.5도 정도 회전했을 때 업데이트된다고 볼 수 있습니다.

값이 너무 크면 로봇이 꽤 움직인 뒤에야 위치가 갱신됩니다. 위치 추정 반응이 느려질 수 있습니다.

값이 너무 작으면 AMCL이 너무 자주 업데이트되어 CPU 사용량이 증가할 수 있습니다. 또한 센서 노이즈에 민감해질 수 있습니다.

실습에서는 로봇을 천천히 움직이면서 ParticleCloud와 로봇 위치 갱신 빈도를 확인합니다. 로봇이 조금 움직였는데도 위치 보정이 너무 늦게 되는 느낌이면 값을 줄여볼 수 있습니다. 반대로 CPU 사용량이 높고 위치가 자주 흔들리면 값을 약간 키울 수 있습니다.

6) AMCL 초기 위치 파라미터

AMCL은 초기 위치를 알아야 제대로 수렴합니다. 관련 파라미터는 다음과 같습니다.

set_initial_pose: false
always_reset_initial_pose: false
initial_pose:
  x: 0.0
  y: 0.0
  z: 0.0
  yaw: 0.0

set_initial_posetrue이면 파라미터 파일에 지정된 초기 위치를 사용할 수 있습니다.

always_reset_initial_pose는 재시작할 때 항상 초기 위치를 다시 적용할지 여부와 관련됩니다.

initial_pose는 지도 좌표계에서 로봇의 초기 위치와 방향입니다.

로봇의 초기 위치를 결정하는 가장 흔한 방법은 RViz의 2D Pose Estimate 버튼을 사용하는 것입니다. 지도 위에서 로봇의 실제 위치와 방향을 마우스로 지정하면 AMCL이 그 위치를 기준으로 파티클을 재배치합니다.

초기 위치를 잘못 지정하면 로봇은 엉뚱한 곳에 있다고 판단합니다. 이 상태에서 목표 지점을 찍으면 실제 로봇은 예상과 다른 방향으로 움직일 수 있습니다.

초기 위치 설정은 Navigation의 기본입니다. 이 단계를 대충 하면 뒤의 모든 튜닝이 의미 없어질 수 있습니다.

6. BT Navigator 파라미터

BT Navigator는 Behavior Tree를 이용해 Navigation의 전체 흐름을 관리합니다.

bt_navigator:
  ros__parameters:
    global_frame: map
    robot_base_frame: base_link
    default_nav_to_pose_bt_xml: "$(find-pkg-share nav2_bt_navigator)/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml"

Behavior Tree는 로봇 행동을 트리 구조로 구성한 것입니다. 목표까지 이동하는 동안 로봇은 단순히 경로만 따라가지 않습니다. 경로를 계산하고, 이동하고, 실패 여부를 확인하고, 필요하면 다시 계획하고, 장애물 때문에 막히면 복구 행동을 수행합니다.

BT Navigator는 이런 흐름을 관리합니다.

예를 들어 일반적인 Navigation 흐름은 다음과 같습니다.

목표 지점 수신

현재 위치 확인

전역 경로 계산

경로 추종

목표 도착 여부 확인

실패 시 재계획

재계획 실패 시 recovery behavior 수행

다시 경로 추종

이 과정을 Behavior Tree XML 파일이 정의합니다.

초보자는 BT XML을 바로 수정하지 않는 것이 좋습니다. 기본 Navigation이 안정적으로 동작한 후에 커스텀 행동을 추가하는 것이 맞습니다. 예를 들어 특정 위치에 도착하면 소리를 내거나, 카메라 촬영을 하거나, 로봇 팔을 움직이는 기능은 기본 주행이 안정화된 뒤 추가해야 합니다.

7. Controller Server의 역할

Controller Server는 전역 경로를 실제 로봇 속도 명령으로 바꾸는 역할을 합니다.

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

controller_frequency는 controller가 초당 몇 번 속도 명령을 계산할지 결정합니다. 여기서는 10Hz입니다. 즉 1초에 10번 로봇의 주행 명령을 갱신합니다.

controller_plugins에는 사용할 controller plugin 목록이 들어갑니다. 여기서는 FollowPath 하나를 사용합니다.

FollowPath:
  plugin: "dwb_core::DWBLocalPlanner"

FollowPath는 DWB(Dynamic Window Based Controller) Local Planner를 사용합니다. DWB는 여러 속도 후보를 시뮬레이션하고 점수를 매겨 가장 적절한 속도 명령을 선택합니다.

Controller Server는 실제 로봇 움직임에 매우 직접적인 영향을 줍니다. 로봇이 너무 빠르거나, 너무 느리거나, 경로를 따라가지 못하거나, 목표 근처에서 흔들리는 문제는 controller 파라미터와 관련이 많습니다.

1) DWB Local Planner 개념

DWB는 Dynamic Window Based 방식의 로컬 플래너입니다. 쉽게 말하면 로봇이 지금 선택할 수 있는 여러 속도 후보를 만들어 보고, 각 후보가 가까운 미래에 어떤 궤적을 만들지 시뮬레이션한 뒤, 가장 좋은 후보를 고르는 방식입니다.

예를 들어 로봇은 다음과 같은 후보를 만들 수 있습니다.

천천히 직진

빠르게 직진

왼쪽으로 돌면서 전진

오른쪽으로 돌면서 전진

제자리 회전

DWB는 각 후보에 대해 점수를 계산합니다. 점수 계산에는 여러 기준이 사용됩니다. 이 기준을 critics라고 부릅니다.

이 파일에서는 다음 critics를 사용합니다.

critics: ["RotateToGoal", "Oscillation", "BaseObstacle", "GoalAlign", "PathAlign", "PathDist", "GoalDist"]

각 critic은 특정 기준으로 궤적을 평가합니다.

BaseObstacle은 장애물과의 충돌 위험을 평가합니다.

PathAlign은 로봇이 전역 경로 방향과 잘 정렬되는지 봅니다.

GoalAlign은 목표 방향과 잘 맞는지 봅니다.

PathDist는 전역 경로에서 얼마나 떨어졌는지 봅니다.

GoalDist는 목표까지 얼마나 가까워지는지 봅니다.

RotateToGoal은 목표 지점 근처에서 방향을 맞추는 행동과 관련됩니다.

Oscillation은 로봇이 앞뒤로 흔들리거나 좌우로 왔다 갔다 하는 행동을 줄이기 위한 기준입니다.

DWB 튜닝은 이 critics의 scale 값을 조정하는 작업이 핵심입니다.

2) DWB 속도 제한 파라미터

TurtleBot3의 실제 주행 속도는 다음 파라미터에 의해 제한됩니다.

min_vel_x: 0.0
max_vel_x: 0.22
min_vel_y: 0.0
max_vel_y: 0.0
max_vel_theta: 1.0
min_speed_xy: 0.0
max_speed_xy: 0.22
min_speed_theta: 0.0

max_vel_x는 전진 방향 최대 속도입니다. 여기서는 0.22m/s입니다.

min_vel_x는 전진 방향 최소 속도입니다. 0.0이면 정지가 가능합니다.

max_vel_y가 0.0인 이유는 TurtleBot3가 차동구동 로봇이기 때문입니다. 차동구동 로봇은 옆으로 이동할 수 없습니다. 따라서 y 방향 속도는 0입니다.

max_vel_theta는 회전 최대 속도입니다. 단위는 rad/s입니다. 1.0rad/s는 약 57.3도/s입니다.

max_speed_xy는 평면 이동 속도의 최대값입니다.

실제 로봇에서 가장 먼저 조정해볼 값은 max_vel_x입니다. 실내 실습에서는 0.2~0.3m/s 정도가 안정적입니다. 너무 빠르게 설정하면 장애물 회피가 늦어지고, AMCL 위치 추정이 불안정해질 수 있습니다.

실습 방법은 다음과 같습니다.

max_vel_x를 0.15로 설정합니다.

목표 지점을 1m 앞에 찍습니다.

로봇이 안정적으로 직진하는지 확인합니다.

max_vel_x를 0.22으로 올립니다.

같은 목표를 다시 수행합니다.

로봇이 더 빠르지만 안정적인지 확인합니다.

속도를 높이면 도착 시간은 줄어듭니다. 하지만 안정성과 충돌 위험도 함께 고려해야 합니다.

3) DWB 가속도와 감속도 파라미터

속도 제한만큼 중요한 것이 가속도와 감속도입니다.

acc_lim_x: 2.5
acc_lim_y: 0.0
acc_lim_theta: 3.2
decel_lim_x: -2.5
decel_lim_y: 0.0
decel_lim_theta: -3.2

acc_lim_x는 전진 방향 가속도 제한입니다.

acc_lim_theta는 회전 방향 가속도 제한입니다.

decel_lim_x는 전진 방향 감속도 제한입니다.

decel_lim_theta는 회전 방향 감속도 제한입니다.

가속도 값이 너무 크면 로봇이 갑자기 튀어나갈 수 있습니다. 특히 실제 TurtleBot3에서 바닥이 미끄럽거나 배터리 상태가 좋지 않으면 급가속 시 오도메트리 오차가 커질 수 있습니다.

감속도 값이 너무 크면 로봇이 급정지합니다. 급정지는 기구적으로도 좋지 않고, 센서 데이터와 실제 움직임 사이에 순간적인 불일치를 만들 수 있습니다.

반대로 가속도와 감속도를 너무 작게 잡으면 로봇이 너무 둔해집니다. 장애물 회피 반응이 늦어지고, 목표 지점 근처에서 미세 조정이 오래 걸릴 수 있습니다.

실습에서는 다음을 확인합니다.

출발할 때 바퀴가 헛돌지 않는가?

정지할 때 로봇이 앞으로 밀리지 않는가?

회전할 때 로봇이 급격히 튀지 않는가?

좁은 공간에서 속도 변화가 자연스러운가?

가속도 튜닝은 단순히 빠르게 만들기 위한 작업이 아닙니다. 로봇의 실제 물리적 반응을 제어 가능한 범위 안에 두는 작업입니다.

4) DWB 시뮬레이션 파라미터

DWB는 속도 후보를 실제로 실행하기 전에 짧은 미래를 시뮬레이션합니다.

vx_samples: 20
vy_samples: 0
vtheta_samples: 40
sim_time: 1.5
linear_granularity: 0.05
angular_granularity: 0.025

vx_samples는 전진 속도 후보 개수입니다.

vy_samples는 y 방향 속도 후보 개수입니다. TurtleBot3는 옆으로 움직일 수 없으므로 0입니다.

vtheta_samples는 회전 속도 후보 개수입니다.

sim_time은 각 속도 후보를 몇 초 앞까지 시뮬레이션할지 결정합니다.

linear_granularity는 시뮬레이션 궤적을 선형 거리 기준으로 얼마나 촘촘히 검사할지 결정합니다.

angular_granularity는 회전 방향으로 얼마나 촘촘히 검사할지 결정합니다.

샘플 수가 많으면 더 다양한 움직임을 검토할 수 있습니다. 하지만 계산량이 늘어납니다.

sim_time이 길면 로봇이 더 먼 미래를 고려합니다. 넓은 공간에서는 부드러운 경로 선택에 도움이 될 수 있습니다. 하지만 좁은 공간에서는 너무 보수적인 움직임이 나올 수 있습니다.

sim_time이 짧으면 빠르게 반응할 수 있지만 경로가 거칠어질 수 있습니다.

실습 방법은 다음과 같습니다.

기본값 sim_time: 1.5로 주행합니다.

로봇이 코너를 돌 때 경로를 얼마나 부드럽게 따라가는지 확인합니다.

sim_time을 1.0으로 줄입니다.

반응은 빨라지는지, 경로가 더 불안정해지는지 확인합니다.

sim_time을 2.0으로 늘립니다.

로봇이 더 보수적으로 움직이는지 확인합니다.

좁은 실내에서는 너무 긴 sim_time보다 적당한 값이 좋습니다. TurtleBot3에서는 1.0~2.0 사이에서 환경에 맞게 확인하는 방식이 현실적입니다.

5) DWB Critics 가중치 이해하기

DWB에서 가장 중요한 부분 중 하나가 critics scale입니다.

BaseObstacle.scale: 0.02
PathAlign.scale: 32.0
GoalAlign.scale: 24.0
PathDist.scale: 32.0
GoalDist.scale: 24.0
RotateToGoal.scale: 32.0

각 scale은 해당 평가 기준을 얼마나 중요하게 볼 것인지 결정합니다.

PathAlign.scale이 크면 로봇은 전역 경로의 방향과 정렬되는 것을 중요하게 봅니다.

PathDist.scale이 크면 로봇은 전역 경로에서 벗어나지 않으려 합니다.

GoalDist.scale이 크면 목표에 가까워지는 것을 중요하게 봅니다.

GoalAlign.scale이 크면 목표 방향을 향하는 것을 중요하게 봅니다.

BaseObstacle.scale은 장애물 비용과 관련됩니다.

RotateToGoal.scale은 목표 지점 근처에서 최종 방향을 맞추는 데 영향을 줍니다.

초보자가 주의해야 할 점은 scale 값 하나만 보고 판단하면 안 된다는 것입니다. DWB는 여러 critic의 점수를 합산해 최종 결정을 내립니다. 어떤 값을 키우면 그 기준은 강해지지만 다른 기준과 균형이 깨질 수 있습니다.

예를 들어 PathAlign.scale이 너무 크면 로봇은 전역 경로 방향을 지나치게 고집할 수 있습니다. 장애물을 피해야 하는 상황에서도 경로에 붙으려다가 부자연스러운 움직임이 생길 수 있습니다.

GoalDist.scale이 너무 크면 목표에 빨리 가까워지는 것만 중시해 경로 추종이 거칠어질 수 있습니다.

실습에서는 한 번에 하나의 scale만 바꾸는 것이 좋습니다. 예를 들어 PathAlign.scale을 32에서 16으로 줄인 뒤, 경로 추종이 어떻게 달라지는지 봅니다. 그다음 다시 원래 값으로 되돌리고 다른 값을 테스트합니다.

6) Goal Checker 파라미터

Goal Checker는 로봇이 목표 지점에 도착했는지 판단합니다.

goal_checker:
  stateful: true
  plugin: "nav2_controller::SimpleGoalChecker"
  xy_goal_tolerance: 0.25
  yaw_goal_tolerance: 0.25

xy_goal_tolerance는 위치 허용 오차입니다. 0.25라면 목표 지점에서 25cm 이내에 들어오면 위치상 도착했다고 볼 수 있습니다.

yaw_goal_tolerance는 방향 허용 오차입니다. 0.25rad는 약 14.3도입니다.

stateful: true는 goal checking 과정에서 상태를 유지한다는 의미입니다. 목표 위치 조건을 만족한 후 방향 조건을 확인하는 식의 동작에서 유리할 수 있습니다.

실제 로봇에서는 goal tolerance를 너무 작게 잡으면 문제가 생길 수 있습니다. 로봇은 완벽하게 정확한 위치에 멈추기 어렵습니다. 바퀴 오차, 센서 노이즈, 바닥 상태, controller 해상도 때문에 목표 지점 근처에서 계속 미세 조정하다가 흔들릴 수 있습니다.

반대로 goal tolerance를 너무 크게 잡으면 목표에 정확히 도착하지 않았는데도 성공으로 판단합니다. 일반 이동에서는 괜찮을 수 있지만, 도킹이나 물건 전달 위치에서는 문제가 됩니다.

실습에서는 다음처럼 테스트합니다.

xy_goal_tolerance를 0.25로 둡니다.

목표 지점을 찍고 성공 판정 위치를 확인합니다.

xy_goal_tolerance를 0.10으로 줄입니다.

로봇이 더 정확히 들어가려 하는지 확인합니다.

xy_goal_tolerance를 0.05로 줄입니다.

목표 근처에서 흔들림이 생기는지 확인합니다.

정밀 목적이 아니라면 너무 작은 값은 피하는 것이 좋습니다.

7) Progress Checker 파라미터 상세 설명

Progress Checker는 로봇이 실제로 진행하고 있는지 확인합니다.

progress_checker:
  plugin: "nav2_controller::SimpleProgressChecker"
  required_movement_radius: 0.1
  movement_time_allowance: 10.0

required_movement_radius는 일정 시간 안에 최소한 얼마나 움직여야 하는지를 나타냅니다.

movement_time_allowance는 그 시간을 의미합니다.

여기서는 10초 안에 0.1m 이상 움직여야 정상 진행으로 판단합니다.

이 기능은 로봇이 장애물에 막혔거나 바퀴가 헛돌거나 경로를 못 따라가는 상황을 감지하는 데 필요합니다. Progress Checker가 없다면 로봇이 제자리에서 계속 바퀴만 돌 수도 있습니다.

실습 방법은 다음과 같습니다.

로봇에게 목표 지점을 보냅니다.

로봇 앞을 손이나 물체로 막습니다.

로봇이 일정 시간 후 진행 실패로 판단하는지 확인합니다.

이후 recovery behavior가 실행되는지 확인합니다.

movement_time_allowance가 너무 짧으면 잠깐 멈춘 상황도 실패로 판단할 수 있습니다. 너무 길면 진짜 막힌 상황에서도 반응이 늦어집니다.

실내 실습에서는 5~10초 정도에서 테스트하고, 로봇의 주행 목적에 맞게 조정하면 됩니다.

8. Local Costmap의 역할

Local Costmap은 로봇 주변의 실시간 장애물 정보를 담는 작은 지도입니다.

local_costmap:
  local_costmap:
    ros__parameters:
      update_frequency: 5.0
      publish_frequency: 2.0
      global_frame: odom
      robot_base_frame: base_link
      rolling_window: true
      width: 3
      height: 3
      resolution: 0.05

update_frequency는 costmap 내부 데이터를 초당 몇 번 갱신할지 결정합니다.

publish_frequency는 costmap을 외부로 초당 몇 번 발행할지 결정합니다.

global_frame: odom은 local costmap이 odom 좌표계를 기준으로 동작한다는 의미입니다.

rolling_window: true는 costmap 창이 로봇을 따라 움직인다는 뜻입니다.

width: 3, height: 3은 로봇 주변 3m x 3m 영역을 본다는 의미입니다.

resolution: 0.05는 costmap 한 칸이 5cm라는 뜻입니다.

Local Costmap은 실제 장애물 회피에 직접적인 영향을 줍니다. 로봇 앞에 갑자기 나타난 장애물은 global path보다 local costmap과 controller를 통해 처리됩니다.

실습에서는 RViz에서 local costmap을 반드시 켜야 합니다. 로봇 주변에 작은 사각형 영역이 따라다니고, 장애물이 표시되는지 확인합니다.

장애물을 놓았는데 local costmap에 표시되지 않는다면 Navigation은 그 장애물을 피할 수 없습니다.

9. Global Costmap의 역할

Global Costmap은 전체 지도 기준의 비용 지도입니다.

global_costmap:
  global_costmap:
    ros__parameters:
      update_frequency: 1.0
      publish_frequency: 1.0
      global_frame: map
      robot_base_frame: base_link
      resolution: 0.05
      track_unknown_space: true

Global Costmap은 planner server가 전역 경로를 만들 때 사용합니다. 로봇이 현재 위치에서 목표 지점까지 어떤 길로 갈지 결정하는 데 필요합니다.

Local Costmap과 Global Costmap의 차이는 다음과 같습니다.

Local Costmap은 로봇 주변의 가까운 장애물을 실시간으로 봅니다.

Global Costmap은 지도 전체 또는 넓은 영역을 보고 전역 경로를 만듭니다.

Local Costmap은 보통 odom 프레임을 사용합니다.

Global Costmap은 보통 map 프레임을 사용합니다.

Local Costmap은 rolling window를 사용합니다.

Global Costmap은 전체 지도 기반으로 동작합니다.

10. Costmap Resolution 이해하기

두 costmap 모두 다음 값을 사용합니다.

resolution: 0.05

resolution은 costmap 한 셀의 크기입니다. 0.05는 5cm를 의미합니다.

해상도가 작을수록 더 정밀한 costmap을 만들 수 있습니다. 하지만 셀 개수가 많아지므로 연산량과 메모리 사용량이 증가합니다.

해상도가 클수록 계산은 가벼워집니다. 하지만 장애물 표현이 거칠어집니다.

예를 들어 3m x 3m local costmap에서 resolution이 0.05라면 한 변에 60개의 셀이 생깁니다. 전체 셀 수는 60 x 60 = 3600개입니다.

resolution을 0.025로 줄이면 한 변에 120개 셀이 생기고, 전체 셀 수는 14400개가 됩니다. 단순히 해상도를 절반으로 줄였지만 셀 수는 4배가 됩니다.

따라서 resolution은 정밀도와 연산량 사이의 균형입니다.

TurtleBot3 실습에서는 0.05m가 일반적으로 무난합니다. 좁은 구조물 사이를 정밀하게 지나가야 한다면 더 작은 값을 검토할 수 있지만, 먼저 CPU 사용량을 확인해야 합니다.

11. Robot Radius와 Footprint 개념

이 파일에서는 costmap에서 로봇 크기를 다음처럼 설정합니다.

robot_radius: 0.1

robot_radius는 로봇을 원으로 간주했을 때의 반지름입니다.

TurtleBot3가 완전한 원형은 아니지만, 2D Navigation에서는 로봇을 단순화해서 계산하는 경우가 많습니다. 원형 모델은 계산이 간단하고 회전 방향에 영향을 덜 받습니다.

하지만 실제 로봇에 카메라, 브래킷, 라이다 보호대, 배터리팩, 적재함이 추가되면 기본 반지름보다 커질 수 있습니다. 이 경우 robot_radius를 실제 외형에 맞게 수정해야 합니다.

robot_radius가 실제보다 작으면 로봇은 지나갈 수 있다고 판단하지만 실제로는 부딪힐 수 있습니다.

robot_radius가 실제보다 크면 안전하지만 좁은 길을 지나가지 못할 수 있습니다.

실습에서는 줄자로 로봇의 최대 폭을 측정합니다.

예를 들어 최대 폭이 28cm라면 반지름은 14cm입니다. 여기에 안전 여유 2cm를 더하면 16cm입니다. 이 경우 robot_radius: 0.16 정도가 현실적일 수 있습니다.

실제 실습에서는 반드시 로봇 외형을 먼저 측정해야 합니다. 기본값을 맹신하면 안 됩니다.

12. Obstacle Layer 상세 설명

Obstacle Layer는 센서로 감지한 장애물을 costmap에 표시합니다.

obstacle_layer:
  plugin: "nav2_costmap_2d::ObstacleLayer"
  enabled: true
  observation_sources: scan
  scan:
    topic: /scan
    max_obstacle_height: 2.0
    clearing: true
    marking: true
    data_type: "LaserScan"

plugin은 사용할 costmap layer 플러그인입니다.

enabled: true는 이 layer를 활성화한다는 뜻입니다.

observation_sources: scan은 장애물 관측 소스로 scan을 사용한다는 뜻입니다.

topic: /scan은 라이다 데이터 토픽입니다.

data_type: "LaserScan"은 센서 데이터 형식이 LaserScan이라는 뜻입니다.

marking: true는 센서로 감지한 장애물을 costmap에 표시한다는 의미입니다.

clearing: true는 더 이상 장애물이 없는 공간을 costmap에서 지운다는 의미입니다.

max_obstacle_height는 장애물로 볼 최대 높이입니다.

TurtleBot3의 2D 라이다는 특정 높이의 평면만 봅니다. 따라서 라이다보다 낮거나 높은 장애물은 제대로 감지하지 못할 수 있습니다. 예를 들어 얇은 테이블 다리는 감지될 수 있지만, 라이다 높이보다 높은 상판만 있는 구조는 감지되지 않을 수 있습니다.

실습에서는 다양한 물체를 놓고 확인해야 합니다.

박스는 잘 감지되는가?

의자 다리는 감지되는가?

얇은 기둥은 감지되는가?

유리나 검은색 물체는 잘 감지되는가?

라이다 센서는 모든 물체를 완벽하게 감지하지 않습니다. Navigation 파라미터를 조정하기 전에 센서 자체의 한계를 이해해야 합니다.

13. Voxel Layer

Voxel Layer는 3차원 격자 개념을 사용해 장애물을 처리하는 layer입니다.

voxel_layer:
  plugin: "nav2_costmap_2d::VoxelLayer"
  enabled: true
  publish_voxel_map: true
  origin_z: 0.0
  z_resolution: 0.05
  z_voxels: 16
  max_obstacle_height: 2.0
  mark_threshold: 0

origin_z는 z축 시작 위치입니다.

z_resolution은 z축 방향 해상도입니다.

z_voxels는 z축 voxel 개수입니다.

publish_voxel_map: true는 voxel map을 발행한다는 의미입니다.

TurtleBot3에서 2D 라이다만 사용하는 경우 voxel layer가 반드시 큰 효과를 내는 것은 아닐 수 있습니다. 하지만 RGB-D 카메라나 3D 센서를 사용하는 로봇에서는 voxel layer가 더 중요해집니다.

이 파일에서는 local costmap과 global costmap 모두 voxel layer를 포함하고 있습니다. 즉 장애물 처리를 더 확장 가능한 구조로 구성한 것입니다.

실습에서는 RViz에서 voxel 관련 topic을 확인할 수 있습니다. 다만 초보자는 먼저 obstacle layer와 inflation layer를 확실히 이해한 뒤 voxel layer를 보는 것이 좋습니다.

14. Raytrace Range와 Obstacle Range

Costmap의 scan 설정에는 다음 값들이 있습니다.

raytrace_max_range: 3.0
raytrace_min_range: 0.0
obstacle_max_range: 2.5
obstacle_min_range: 0.0

obstacle_max_range는 장애물로 등록할 최대 거리입니다. 여기서는 2.5m입니다.

raytrace_max_range는 빈 공간을 clearing할 때 사용할 최대 거리입니다. 여기서는 3.0m입니다.

차이를 쉽게 말하면 다음과 같습니다.

obstacle_max_range는 “이 거리 안의 물체를 장애물로 표시하겠다”는 값입니다.

raytrace_max_range는 “이 거리까지는 비어 있는 공간으로 지울 수 있다”는 값입니다.

일반적으로 raytrace 범위가 obstacle 범위보다 약간 더 큰 경우가 많습니다. 그래야 장애물이 사라졌을 때 그 뒤쪽 공간까지 clearing이 잘 됩니다.

실습에서는 로봇 앞에 장애물을 놓았다가 치워 봅니다. 장애물을 치웠는데 costmap에 흔적이 오래 남아 있다면 clearing 관련 값을 확인해야 합니다.

장애물이 너무 멀리서부터 표시되어 로봇이 과도하게 피한다면 obstacle_max_range를 확인합니다. 반대로 장애물을 너무 늦게 인식한다면 센서 범위와 이 값을 함께 확인해야 합니다.

15. Inflation Layer

Inflation Layer는 장애물 주변에 안전 여유 공간을 만듭니다.

inflation_layer:
  plugin: "nav2_costmap_2d::InflationLayer"
  inflation_radius: 0.5
  cost_scaling_factor: 5.0

inflation_radius는 장애물 주변을 얼마나 넓게 위험 영역으로 확장할지 결정합니다.

cost_scaling_factor는 장애물에서 멀어질수록 비용이 얼마나 빨리 감소하는지 결정합니다.

장애물 자체만 costmap에 표시하면 로봇은 장애물 바로 옆을 지나가려고 할 수 있습니다. 실제 로봇에는 크기가 있고, 센서 오차와 제어 오차도 있으므로 장애물 주변에 여유 공간이 필요합니다. 이 여유 공간을 만드는 것이 inflation layer입니다.

inflation_radius가 크면 로봇은 장애물에서 멀리 떨어져 이동합니다. 안전성은 높아지지만 좁은 통로를 지나가기 어렵습니다.

inflation_radius가 작으면 좁은 공간을 통과하기 쉬워집니다. 하지만 장애물에 가까이 붙어 충돌 위험이 커질 수 있습니다.

cost_scaling_factor가 크면 비용이 빠르게 떨어집니다. 장애물 바로 근처만 위험하게 보고, 조금 떨어지면 비용이 낮아집니다.

cost_scaling_factor가 작으면 비용이 천천히 떨어집니다. 장애물 주변의 넓은 영역을 계속 부담스럽게 봅니다.

실습에서는 RViz에서 costmap 색상 변화를 보면서 확인하는 것이 가장 좋습니다. 장애물 주변에 퍼지는 색상 영역이 inflation입니다.

16. Inflation Radius 실습

Inflation Radius는 실제 로봇 실습에서 가장 효과가 눈에 잘 보이는 파라미터입니다.

실습 환경은 다음처럼 구성합니다.

로봇 앞에 박스 두 개를 놓습니다.

박스 사이에 통로를 만듭니다.

통로 폭을 80cm, 70cm, 60cm, 50cm로 줄여가며 테스트합니다.

먼저 기본값으로 테스트합니다.

inflation_radius: 0.5

로봇이 통로를 통과하는지 확인합니다.

그다음 값을 줄입니다.

inflation_radius: 0.3

로봇이 더 좁은 통로를 통과하려 하는지 확인합니다.

그다음 값을 키웁니다.

inflation_radius: 0.7

로봇이 통로를 포기하거나 크게 우회하는지 확인합니다.

이 실습을 통해 알 수 있는 점은 명확합니다. 로봇이 장애물을 피하는 거리는 controller만의 문제가 아닙니다. costmap에서 장애물 주변을 어떻게 비용화하느냐가 실제 경로 선택에 큰 영향을 줍니다.

실제 로봇에서는 inflation_radius를 너무 작게 잡지 않는 것이 좋습니다. 최소한 로봇 반지름보다 커야 하고, 센서 오차와 제어 오차까지 고려해야 합니다.

17. Static Layer와 지도 반영

Global Costmap에는 static layer가 포함됩니다.

static_layer:
  plugin: "nav2_costmap_2d::StaticLayer"
  map_subscribe_transient_local: true
  transform_tolerance: 0.1

Static Layer는 map server에서 제공하는 정적 지도를 costmap에 반영합니다. 즉 벽, 고정 장애물, 구조물 같은 지도 정보를 costmap에 넣습니다.

map_subscribe_transient_local: true는 ROS 2 QoS와 관련됩니다. 지도처럼 늦게 구독해도 마지막 데이터를 받아야 하는 topic에서는 transient local 설정이 중요합니다.

실습에서는 map server가 정상적으로 지도를 발행하는지 확인해야 합니다.

ros2 topic list
ros2 topic echo /map

RViz에서 Map을 켰을 때 지도가 정상 표시되어야 합니다. 지도가 표시되지 않으면 AMCL과 Global Costmap이 제대로 동작하기 어렵습니다.

18. Planner Server 상세 설명

Planner Server는 전역 경로를 생성합니다.

planner_server:
  ros__parameters:
    expected_planner_frequency: 10.0
    planner_plugins: ["GridBased"]
    GridBased:
      plugin: "nav2_navfn_planner::NavfnPlanner"
      tolerance: 0.5
      use_astar: false
      allow_unknown: true

expected_planner_frequency는 planner가 기대하는 실행 빈도입니다.

planner_plugins는 사용할 planner plugin 목록입니다.

GridBased는 plugin 이름입니다.

plugin: "nav2_navfn_planner::NavfnPlanner"는 NavfnPlanner를 사용한다는 의미입니다.

tolerance는 목표 지점 주변 허용 범위와 관련됩니다.

use_astar: false이면 기본 NavFn 방식으로 동작합니다. true로 하면 A* 방식을 사용할 수 있습니다.

allow_unknown: true는 알려지지 않은 공간으로도 경로를 계획할 수 있게 합니다.

allow_unknown은 실전에서 매우 중요합니다. 탐색 성격의 주행이라면 unknown 영역을 허용할 수 있습니다. 하지만 이미 작성된 실내 지도에서 안전하게 이동하는 목적이라면 unknown 영역을 통과하는 것이 위험할 수 있습니다.

실습에서는 RViz에서 목표 지점을 지도상의 known 영역과 unknown 영역 근처에 찍어보면 됩니다. allow_unknown 값에 따라 경로가 생성되는지 달라질 수 있습니다.

19. NavfnPlanner와 A* 차이 이해하기

NavfnPlanner는 전통적인 grid 기반 경로 계획 방식입니다. 지도는 격자 형태이고, 각 셀은 이동 가능, 장애물, unknown 같은 상태를 가집니다. Planner는 현재 위치에서 목표 위치까지 비용이 낮은 경로를 찾습니다.

use_astar: false일 때는 기본 NavFn 방식이 사용됩니다.

use_astar: true일 때는 A* 방식이 사용됩니다.

A*는 목표 방향을 고려해 탐색을 효율적으로 수행하는 알고리즘입니다. 복잡한 지도에서는 경로 계산 방식에 차이가 생길 수 있습니다.

실습 방법은 다음과 같습니다.

같은 지도에서 같은 목표 지점을 찍습니다.

use_astar: false 상태의 global path를 기록합니다.

use_astar: true로 바꿉니다.

Nav2를 재시작합니다.

같은 목표 지점을 다시 찍습니다.

경로 모양, 계산 속도, 장애물 우회 방식을 비교합니다.

초보자는 알고리즘 이론보다 RViz에서 경로가 어떻게 달라지는지 보는 것이 훨씬 이해가 빠릅니다.

20. Behavior Server

Behavior Server는 Navigation 실패 상황에서 로봇이 수행할 행동을 담당합니다.

behavior_server:
  ros__parameters:
    behavior_plugins: ["spin", "backup", "drive_on_heading", "wait", "assisted_teleop"]

각 behavior는 다음 역할을 합니다.

spin은 제자리 회전입니다. 주변을 다시 관측하거나 방향을 바꿀 때 사용됩니다.

backup은 후진입니다. 로봇이 막혔을 때 뒤로 빠져나올 수 있습니다.

drive_on_heading은 특정 방향으로 직진하는 행동입니다.

wait는 일정 시간 대기입니다.

assisted_teleop은 보조 수동 조작과 관련된 행동입니다.

관련 파라미터는 다음과 같습니다.

cycle_frequency: 10.0
local_frame: odom
global_frame: map
robot_base_frame: base_link
transform_timeout: 0.1
simulate_ahead_time: 2.0
max_rotational_vel: 1.0
min_rotational_vel: 0.4
rotational_acc_lim: 3.2

cycle_frequency는 behavior server의 실행 주기입니다.

simulate_ahead_time은 행동 수행 시 충돌 여부를 예측할 시간입니다.

max_rotational_vel은 최대 회전 속도입니다.

min_rotational_vel은 최소 회전 속도입니다.

rotational_acc_lim은 회전 가속도 제한입니다.

실제 로봇에서 recovery behavior는 안전성과 직결됩니다. 후진 행동이 너무 길거나 빠르면 뒤쪽 장애물과 충돌할 수 있습니다. 회전 속도가 너무 빠르면 좁은 공간에서 부딪힐 수 있습니다.

실습할 때는 넓은 공간에서 recovery behavior가 어떻게 실행되는지 먼저 확인해야 합니다.

21. Waypoint Follower

Waypoint Follower는 여러 목표 지점을 순서대로 이동할 때 사용합니다.

waypoint_follower:
  ros__parameters:
    loop_rate: 2000
    stop_on_failure: false
    waypoint_task_executor_plugin: "wait_at_waypoint"

loop_rate는 waypoint follower가 초당 몇 번 상태를 확인할지 결정합니다.

stop_on_failure: false는 특정 waypoint에서 실패하더라도 전체 작업을 중단하지 않을 수 있다는 의미입니다.

waypoint_task_executor_plugin은 waypoint 도착 시 수행할 작업 plugin입니다.

여기서는 wait_at_waypoint를 사용합니다.

wait_at_waypoint:
  plugin: "nav2_waypoint_follower::WaitAtWaypoint"
  enabled: true
  waypoint_pause_duration: 200

이 설정은 waypoint에 도착했을 때 잠시 대기하는 기능입니다.

실제 응용에서는 waypoint마다 작업을 넣을 수 있습니다. 예를 들어 순찰 로봇이라면 특정 지점에서 5초 대기하면서 카메라 촬영을 할 수 있습니다. 배송 로봇이라면 특정 지점에서 도착 알림을 보낼 수 있습니다.

TurtleBot3 실습에서는 먼저 간단히 여러 waypoint를 보내고 로봇이 순서대로 이동하는지 확인합니다.

22. Docking Server 파라미터

파라미터 파일에는 docking server 설정도 포함되어 있습니다.

docking_server:
  ros__parameters:
    dock_plugins: ['nova_carter_dock']
    nova_carter_dock:
      plugin: 'opennav_docking::SimpleChargingDock'
    docks: ['home_dock','flex_dock1', 'flex_dock2']

Docking Server는 로봇이 충전 도크나 특정 도킹 위치로 접근하는 기능과 관련됩니다.

도크 위치는 다음과 같이 설정되어 있습니다.

home_dock:
  type: 'nova_carter_dock'
  frame: map
  pose: [0.0, 0.0, 0.0]

frame: map은 도크 위치가 지도 좌표계 기준이라는 의미입니다.

pose는 도크의 x, y, yaw 위치입니다.

TurtleBot3 기본 실습에서는 docking 기능을 바로 사용하지 않을 수도 있습니다. 하지만 자율 충전 로봇을 만들려면 docking 개념이 중요합니다.

도킹에서는 일반 Navigation보다 더 정밀한 위치 제어가 필요합니다. 따라서 AMCL 위치 추정, goal tolerance, controller 속도, collision monitor 설정이 모두 더 엄격해야 합니다.

23. Collision Monitor의 역할

Collision Monitor는 로봇이 충돌 위험 상황에서 정지하거나 감속하도록 도와주는 안전 계층입니다.

collision_monitor:
  ros__parameters:
    base_frame_id: "base_footprint"
    odom_frame_id: "odom"
    cmd_vel_in_topic: "cmd_vel_smoothed"
    cmd_vel_out_topic: "cmd_vel"

cmd_vel_in_topic은 입력 속도 명령입니다. 여기서는 velocity smoother를 거친 cmd_vel_smoothed를 받습니다.

cmd_vel_out_topic은 최종 출력 속도 명령입니다. 여기서는 cmd_vel입니다.

즉 controller가 만든 속도 명령이 velocity smoother를 거치고, collision monitor를 거쳐 최종적으로 로봇에 전달되는 구조로 볼 수 있습니다.

Collision Monitor는 costmap과는 다릅니다. Costmap은 경로 계획과 장애물 회피에 사용됩니다. Collision Monitor는 더 직접적인 안전 필터입니다. 로봇이 충돌 위험 영역에 장애물을 감지하면 속도를 제한하거나 정지시킬 수 있습니다.

실제 로봇에서는 collision monitor를 매우 중요하게 봐야 합니다. 특히 사람과 함께 있는 환경에서는 필수 안전 장치에 가깝습니다.

24. Collision Monitor PolygonStop

정지 영역 설정은 다음과 같습니다.

PolygonStop:
  type: "circle"
  radius: 0.1
  action_type: "stop"
  min_points: 4
  visualize: true
  polygon_pub_topic: "polygon_stop"
  enabled: true

type: "circle"은 원형 영역을 사용한다는 의미입니다.

radius: 0.1은 반지름 10cm입니다.

action_type: "stop"은 이 영역에 장애물이 감지되면 정지한다는 뜻입니다.

min_points: 4는 장애물로 판단하기 위한 최소 포인트 수입니다.

visualize: true이면 RViz에서 영역을 볼 수 있도록 topic을 발행합니다.

실습에서는 RViz에서 polygon_stop을 표시하고, 로봇 주변의 정지 영역을 확인합니다. 장애물을 이 영역 안으로 넣었을 때 로봇이 정지하는지 확인합니다.

정지 영역이 너무 작으면 충돌 직전에야 멈춥니다. 너무 크면 불필요하게 자주 멈출 수 있습니다.

25. Collision Monitor PolygonSlow

감속 영역 설정은 다음과 같습니다.

PolygonSlow:
  type: "polygon"
  points: "[[0.1, 0.1], [0.1, -0.1], [-0.1, -0.1], [-0.1, 0.1]]"
  action_type: "slowdown"
  min_points: 4
  slowdown_ratio: 0.3
  visualize: true
  polygon_pub_topic: "polygon_slowdown"
  enabled: true

type: "polygon"은 다각형 영역을 사용한다는 의미입니다.

points는 로봇 기준 좌표계에서 다각형 꼭짓점을 정의합니다.

action_type: "slowdown"은 이 영역에 장애물이 들어오면 감속한다는 뜻입니다.

slowdown_ratio: 0.3은 속도를 30% 수준으로 줄인다고 이해할 수 있습니다.

실습에서는 로봇이 천천히 주행할 때 전방에 물체를 접근시켜 감속이 되는지 확인합니다. 이때 /cmd_vel/cmd_vel_smoothed를 함께 보면 속도 명령이 어떻게 변하는지 확인할 수 있습니다.

ros2 topic echo /cmd_vel
ros2 topic echo /cmd_vel_smoothed

실제 로봇에서는 정지 영역보다 감속 영역을 더 넓게 잡는 것이 자연스럽습니다. 먼저 감속하고, 더 가까워지면 정지하는 구조가 안전합니다.

26. FootprintApproach 설정

FootprintApproach는 로봇 footprint를 기준으로 미래 충돌 가능성을 예측합니다.

FootprintApproach:
  type: "polygon"
  action_type: "approach"
  footprint_topic: "/local_costmap/published_footprint"
  time_before_collision: 2.0
  simulation_time_step: 0.02
  min_points: 6
  visualize: False
  enabled: true

time_before_collision: 2.0은 2초 앞까지 충돌 가능성을 예측한다는 의미입니다.

simulation_time_step: 0.02는 시뮬레이션 간격입니다.

footprint_topic은 로봇 footprint 정보를 받는 topic입니다.

이 기능은 단순히 현재 위치의 장애물만 보는 것이 아니라, 현재 속도로 움직였을 때 가까운 미래에 충돌할 수 있는지를 판단하는 데 도움이 됩니다.

실습에서는 로봇을 천천히 장애물 방향으로 이동시키고, 접근 상황에서 속도 제한이 걸리는지 확인합니다.

27. Velocity Smoother의 역할

Velocity Smoother는 속도 명령을 부드럽게 만들어 줍니다.

velocity_smoother:
  ros__parameters:
    smoothing_frequency: 20.0
    scale_velocities: false
    feedback: "OPEN_LOOP"
    max_velocity: [0.5, 0.0, 2.5]
    min_velocity: [-0.5, 0.0, -2.5]
    deadband_velocity: [0.0, 0.0, 0.0]
    velocity_timeout: 1.0
    max_accel: [2.5, 0.0, 3.2]
    max_decel: [-2.5, 0.0, -3.2]

Controller가 만든 속도 명령은 상황에 따라 급격하게 변할 수 있습니다. 실제 로봇에 급격한 속도 변화가 전달되면 로봇이 튀거나 흔들릴 수 있습니다. Velocity Smoother는 이런 속도 변화를 완화합니다.

smoothing_frequency: 20.0은 초당 20번 속도 smoothing을 수행한다는 의미입니다.

feedback: "OPEN_LOOP"은 오도메트리 피드백을 적극적으로 사용하지 않고 명령 기반으로 smoothing한다는 의미입니다.

max_velocity[x, y, theta] 방향의 최대 속도입니다.

min_velocity[x, y, theta] 방향의 최소 속도입니다.

max_accel은 최대 가속도입니다.

max_decel은 최대 감속도입니다.

TurtleBot3는 y 방향 이동이 불가능하므로 y축 값은 0입니다.

실습에서는 velocity smoother를 적용했을 때와 적용하지 않았을 때의 주행 느낌을 비교할 수 있습니다. 출발과 정지가 부드러워지면 smoother가 효과적으로 작동하는 것입니다.

28. cmd_vel 흐름 이해하기

이 파라미터 파일에서는 속도 명령 흐름을 이해하는 것이 중요합니다.

Controller Server는 경로 추종을 위해 속도 명령을 만듭니다.

Velocity Smoother는 그 속도 명령을 부드럽게 만듭니다.

Collision Monitor는 최종적으로 충돌 위험을 확인하고 필요하면 속도를 제한합니다.

관련 topic은 다음과 같습니다.

cmd_vel_in_topic: "cmd_vel_smoothed"
cmd_vel_out_topic: "cmd_vel"

이 구조에서는 cmd_vel_smoothed가 collision monitor로 들어가고, collision monitor가 최종 cmd_vel을 출력합니다.

실습할 때는 다음 명령어로 topic을 확인합니다.

ros2 topic list | grep cmd_vel

그리고 각 topic을 echo해서 속도 값이 어떻게 변하는지 봅니다.

ros2 topic echo /cmd_vel_smoothed
ros2 topic echo /cmd_vel

장애물이 없을 때는 두 값이 비슷해야 합니다.

장애물이 감지되어 collision monitor가 개입하면 최종 /cmd_vel 값이 줄어들거나 0이 될 수 있습니다.

이 흐름을 이해하면 “controller는 명령을 내는데 로봇이 안 움직인다” 같은 문제를 추적할 수 있습니다. 중간에서 velocity smoother나 collision monitor가 속도를 제한하고 있을 수 있기 때문입니다.

29. Map Server와 지도 파일

Map Server는 저장된 지도를 불러옵니다.

map_server:
  ros__parameters:
    yaml_filename: "map.yaml"

map.yaml은 지도 이미지와 해상도, 원점, 점유 기준 등을 담고 있는 파일입니다.

보통 map.yaml은 다음과 같은 구조를 가집니다.

image: map.pgm
resolution: 0.05
origin: [0.0, 0.0, 0.0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.25

image는 지도 이미지 파일입니다.

resolution은 지도 한 픽셀이 실제 몇 m인지 나타냅니다.

origin은 지도 원점입니다.

occupied_thresh는 점유 공간 판단 기준입니다.

free_thresh는 자유 공간 판단 기준입니다.

Navigation이 잘 되려면 지도 품질이 좋아야 합니다. 지도에서 벽이 휘어 있거나, 실제와 다르게 어긋나 있거나, 장애물이 잘못 저장되어 있으면 로봇 주행이 불안정해집니다.

실습에서는 SLAM으로 지도를 만든 뒤 반드시 실제 환경과 비교해야 합니다. RViz에서 라이다 점이 지도 벽과 잘 겹치는지 확인하는 것이 핵심입니다.

30. Map Saver 파라미터

Map Saver는 SLAM으로 만든 지도를 저장할 때 사용합니다.

map_saver:
  ros__parameters:
    save_map_timeout: 5.0
    free_thresh_default: 0.25
    occupied_thresh_default: 0.65
    map_subscribe_transient_local: true

save_map_timeout은 지도 저장 시 대기 시간입니다.

free_thresh_default는 자유 공간으로 판단하는 기본 기준입니다.

occupied_thresh_default는 점유 공간으로 판단하는 기본 기준입니다.

지도 저장 명령은 보통 다음과 같습니다.

ros2 run nav2_map_server map_saver_cli -f my_map

그러면 my_map.yamlmy_map.pgm 같은 파일이 생성됩니다.

지도 저장 후에는 반드시 다시 불러와 확인해야 합니다. 저장된 지도와 SLAM 중 보이던 지도가 다르게 보이면 threshold나 저장 과정에 문제가 있을 수 있습니다.

Leave a Comment