본문으로 건너뛰기
버전: v26.06a

로봇의 상태 표현과 SLAM

로봇의 상태 표현

TF

TF 예시 이미지

ROS에서 빠질 수 없는 개념인 TF는 Transformation(변환)의 줄임말로, 시간에 따라 달라지는 여러 좌표계(Frame)의 관계를 관리하는 시스템입니다. 각 좌표계 사이의 이동과 회전 관계를 저장하고, 특정 시각을 기준으로 한 좌표 변환을 계산할 수 있도록 도와줍니다.

예를 들어, 로봇의 특정 위치에 부착된 LiDAR 센서의 측정값을 로봇의 중심 좌표계(base_link 등)를 기준으로 변환하거나, RViz에서 시각화할 때 TF를 사용하여 각 부위의 상대 위치를 정확히 표시할 수 있습니다.

Frame

ROS에서 Frame은 하나의 좌표계를 의미하며, 로봇의 특정 부위나 센서 위치를 기준으로 정의됩니다. MechaShip에서는 LiDAR에 base_scan, 카메라에 camera_link, IMU에 imu_link 프레임을 사용합니다.

이러한 프레임 정보는 센서 데이터의 헤더(header)에 포함된 frame_id 필드를 통해 지정됩니다.

이전 시간에 RViz를 사용하여 LiDAR 데이터를 시각화해 보았습니다. 이때 Fixed Frame은 시각화의 기준 좌표계를 의미합니다. 예를 들어 Fixed Framebase_link로 설정하면 로봇 본체를 기준으로 다른 센서 데이터가 시각화됩니다. 오도메트리를 확인할 때는 odom, SLAM 지도를 확인할 때는 map을 기준으로 사용합니다.

RViz Fixed Frame 예시

📢 실습

TF는 다음 두 토픽으로 나뉩니다.

토픽의미
/tf시간에 따라 변하는 동적 변환움직이는 조인트, odom에서 본 선박 위치
/tf_static변하지 않는 정적 변환본체에 고정된 LiDAR·카메라·IMU 위치
  1. bringup을 실행한 후 ros2 topic list에서 /tf/tf_static을 찾습니다.

  2. 다음 명령으로 두 토픽을 각각 수신하여 발행되는 프레임과 갱신 방식의 차이를 확인합니다.

    ros2 topic echo /tf
    ros2 topic echo /tf_static

robot_state_publisher

robot_state_publisher는 로봇 모델에 정의된 본체·센서·관절의 연결 관계를 읽어 각 좌표계의 위치를 TF로 알려주는 노드입니다. 본체에 고정된 센서는 정해진 위치를 사용하고, 움직이는 관절은 /joint_states로 받은 각도에 따라 위치를 계산합니다. 이때 사용할 로봇 모델은 robot_description으로 전달됩니다.

ROS에서 널리 사용하는 로봇 모델 형식에는 URDFSDF가 있습니다. 두 형식 모두 링크, 조인트, 시각 형상, 충돌 형상, 질량과 관성 등을 표현할 수 있습니다. URDF는 로봇의 운동학적 구조를 표현하는 데 주로 사용하고, SDF는 로봇뿐 아니라 센서, 플러그인, 조명, 물리 속성, 월드 등 시뮬레이션에 필요한 정보를 더 폭넓게 표현할 수 있습니다.

sdformat_urdf를 사용하면 robot_state_publisher가 SDF에 정의된 링크와 조인트를 읽어 TF를 생성할 수 있습니다.

MechaShip은 model.sdf 하나를 Gazebo 시뮬레이션과 TF 구성에 함께 사용합니다. mechaship_state_publisher.launch.py가 이 파일을 robot_description으로 전달하면, Gazebo는 로봇 모델을 불러오고 robot_state_publisher는 링크와 조인트 관계를 읽어 TF를 발행합니다. 따라서 Gazebo용 SDF와 TF용 URDF를 따로 작성하거나 관리할 필요가 없습니다.

정보

Gazebo 패키지를 설치하면 sdformat_urdf도 의존성으로 함께 설치되므로 별도로 설치할 필요가 없습니다. 만약 설치되지 않았다면 다음 명령으로 설치할 수 있습니다.

sudo apt install ros-jazzy-sdformat-urdf

로봇 형상 정보 예시

URDF와 SDF의 로봇 모델은 주로 각 몸체를 나타내는 Link와 링크 사이의 연결 관계를 나타내는 Joint로 구성됩니다. 여러 링크 중 하나가 전체 모델의 기준 역할을 하며, 보통 base_linkbase_footprint와 같은 이름을 사용합니다. Base라는 요소가 Link, Joint와 별도로 존재하는 것은 아닙니다.

joint_state_publisher

joint_state_publisher는 움직이는 관절의 각도를 /joint_states 토픽으로 발행하는 노드입니다. camera_jointgps_joint와 같이 fixed 타입으로 설정된 조인트는 항상 같은 위치에 고정되므로 /joint_states 입력이 필요하지 않습니다.

joint_state_publisher는 실제 인코더가 없는 환경에서 기본 위치나 시험 값을 발행할 때 주로 사용합니다. 키(Key)처럼 실제로 움직이는 조인트의 현재 각도는 하드웨어 드라이버나 컨트롤러가 센서값을 읽어 /joint_states로 발행해야 합니다. Gazebo에서는 시뮬레이터가 조인트 상태를 발행하므로 MechaShip의 joint_state_publisher는 비활성화됩니다.

TF 확인하기

앞서 robot_state_publisherjoint_state_publisher를 통해 TF가 어떻게 생성되고 구성되는지를 살펴보았습니다. 이제 이렇게 만들어진 TF 데이터를 실시간으로 확인하고 시각화하는 방법을 알아보겠습니다.

ROS에서는 TF를 확인할 수 있는 여러 도구를 제공하는데, 그중 대표적인 방법은 RViz를 활용하는 방법과 RQT의 TF Tree 플러그인을 사용하는 방법입니다. 이 두 가지 방법 모두 실시간으로 TF 프레임 간의 관계를 시각적으로 파악할 수 있기 때문에, 디버깅이나 구조 이해에 매우 유용하게 사용됩니다.

RViz를 이용한 TF 시각화

RViz는 로봇 센서 데이터와 모델을 3차원으로 시각화해주는 도구입니다. 따라서, 각 프레임의 실제 위치나 방향을 직관적으로 파악하기 위해선 RViz를 사용하는 것이 좋습니다. 아래 과정을 따라서 시각화를 진행해보겠습니다.

  1. 터미널에서 RViz를 실행합니다.

    rviz2
  2. 좌측 하단의 [Add] 버튼을 클릭합니다.

  3. 목록에서 TF를 선택하고 [OK]를 누르면 화면에 각 프레임이 빨간(X), 초록(Y), 파란(Z) 축으로 표시됩니다.

  4. 마우스를 이용하여 화면을 회전하거나 확대/축소하면, 각 프레임 간의 상대적인 위치와 방향을 직관적으로 확인할 수 있습니다.

📢 실습

  1. RViz에서 TF의 모든 Frame 이름이 나타나도록 조작하시오.

  2. TF의 마커 크기를 조절해 보시오.

RQT TF Tree를 이용한 TF 시각화

RViz가 3D 시각화에 강점이 있다면, RQT TF Tree는 프레임 간 연결 구조를 트리 형태로 간결하게 파악할 수 있다는 강점이 있습니다. 복잡한 구조의 로봇에서 프레임들 간의 연결 관계를 확인할 때 자주 사용됩니다. 아래 과정을 따라서 시각화를 진행해보겠습니다.

  1. 플러그인을 설치합니다.

    sudo apt install ros-jazzy-rqt-tf-tree
  2. 터미널에서 RQT를 실행합니다.

    rqt

    이전 설정 때문에 플러그인이 정상적으로 표시되지 않을 때만 rqt --clear-config로 설정을 초기화합니다.

  3. 상단 메뉴에서 [Plugins] → [Visualization] → [TF Tree]를 선택합니다.

  4. 잠시 기다리면 현재 실행 중인 TF 프레임들의 계층 구조가 Tree 형태로 표시됩니다.

📢 실습

  1. RQT에서 TF Tree를 이미지로 저장하고 구조를 확인하시오.

로봇의 위치 표현

Odometry

Odometry 예시

자동차, 선박, 드론처럼 움직일 수 있는 로봇은 센서와 운동 정보를 이용해 시간에 따른 위치와 방향의 변화를 추정합니다. 이를 오도메트리(Odometry)라고 합니다. ROS의 odom 프레임은 단기적으로 부드럽고 연속적인 위치를 제공하지만, 시간이 지날수록 오차가 누적되어 실제 위치에서 멀어질 수 있습니다.

일반적인 바퀴형 로봇은 바퀴 회전수를 이용해 오도메트리를 계산합니다. 하지만 선박은 바퀴가 아닌 쓰러스터(Thruster)로 움직이며, 쓰러스터가 멈춰 있는 상태에서도 물살이나 바람 등의 외부 요인으로 인해 계속 움직일 수 있습니다. 이처럼 주변 환경에 많은 영향을 받는 선박의 특성상, 쓰러스터의 회전수만으로는 선박의 이동 거리나 위치를 계산하기 어렵습니다.

따라서 선박에서는 IMU, LiDAR, GPS와 같은 다양한 센서를 활용하여 주변 환경의 변화를 분석하고, 이를 기반으로 오도메트리를 계산합니다. 센서마다 측정할 수 있는 정보나 특징이 다르기 때문에 하나의 센서에 의존하기보다는 여러 센서를 적절히 조합하여 사용하는 것이 더욱 정확한 위치 추정에 도움이 됩니다.

base_footprint

base_link는 로봇 모델의 중심 좌표계이며, 센서와 다른 링크들은 주로 base_link를 기준으로 연결됩니다. base_footprint는 2D 위치 추정과 이동을 위해 사용하는 수평 기준 좌표계입니다. 지상 로봇에서는 바닥면에 투영한 중심을 의미하는 경우가 많지만, MechaShip에서는 선박이 지면에 닿는 위치가 아니라 평면 운항을 위한 기준 프레임으로 사용합니다.

MechaShip 모델에서는 base_footprint가 전체 모델의 기준 링크이고, base_link는 그 위에 고정 조인트로 연결되어 있습니다. 위치 추정과 SLAM에 사용하는 대표적인 TF 연결은 다음과 같습니다.

map → odom → base_footprint → base_link → sensor frames
변환담당 기능
map → odomSLAM이나 전역 위치 추정
odom → base_footprintLiDAR 오도메트리와 EKF
base_footprint → base_link → sensor frames로봇 모델과 robot_state_publisher

Odometry 출력하기

Lidar Odometry

2D LiDAR(평면 레이저 스캔) 기반의 2D 오도메트리를 계산해 주는 패키지입니다. 앞서 언급한 대로, 바퀴의 회전수만으로 오도메트리를 계산할 수 없는 이동형 로봇에 사용됩니다.

주변에 고정된 구조물이 적은 환경에서는 정확도가 낮아질 수 있습니다.

알고리즘에 대한 더 자세한 설명은 아래 링크에서 설명하고 있습니다.

https://mapir.uma.es/papersrepo/2016/2016_Jaimez_ICRA_RF2O.pdf

Extended Kalman Filter

EKF, 즉 확장 칼만 필터는 기본적인 칼만 필터(Kalman Filter)를 비선형 시스템에 적용할 수 있도록 확장한 필터입니다.

여러 센서로부터 들어오는 데이터에는 각기 다른 노이즈가 포함되어 있는데, EKF는 이러한 센서 데이터를 통합 및 보정하여 로봇의 위치, 속도, 자세 등의 상태를 추정하는 데 사용됩니다.

EKF를 구현하기 위해선 다소 복잡한 계산 과정을 거쳐야 하지만, ROS에서는 robot_localization 패키지를 통해 파라미터 설정만으로 간단하게 활용할 수 있습니다. 다만, 파라미터 설정이 잘못되면 필터 결과도 부정확해지므로 단순히 여러 토픽을 연결하는 것만으로 정확도가 높아지는 것은 아닙니다.

MechaShip은 LiDAR 오도메트리와 IMU 데이터를 EKF로 결합해 위치를 추정합니다.

아래 과정을 따라서 EKF를 활용해 계산한 오도메트리를 확인해 보겠습니다.

  1. 터미널에서 EKF 패키지를 실행합니다.

    ros2 launch mechaship_slam ekf.launch.py
  2. 새로운 터미널을 열고 RViz를 실행합니다.

    rviz2

📢 실습

  1. ros2 topic echo /scan/odomros2 topic echo /odom을 각각 실행해 RF2O 원본과 EKF 출력의 차이를 확인합니다.
  2. RViz의 Fixed Frameodom으로 설정하고 Odometry, TF, LaserScan 표시를 추가합니다.
  3. 선박을 정지시킨 상태에서 /odom의 위치와 yaw가 얼마나 흔들리는지 확인합니다.
  4. 직진과 회전 후 원래 위치로 돌아왔을 때 RF2O 원본과 EKF 출력에 남는 오차를 비교합니다.
  5. 입력 공분산과 rejection threshold를 한 번에 하나씩 조정하고, 변경 전후의 정지 상태 흔들림과 이동 후 오차를 기록합니다.

SLAM

SLAM은 Simultaneous Localization And Mapping의 약자로, 동시적 위치 추정 및 지도 작성을 의미합니다. 쉽게 말해, 자율주행 기능이 탑재된 로봇이 센서나 카메라를 활용해 주변 지도를 실시간으로 작성하고, 그 지도에서 자신의 현재 위치를 추정하는 기술입니다.

이러한 기술 덕분에 로봇이 처음 가보는 장소에서도 스스로 경로를 만들고 주행할 수 있습니다.

라인트레이서 예시

예를 들어, 라인트레이서와 같은 단순한 로봇은 정해진 경로만 따라가기 때문에 순간적인 환경 변화에 유연하게 대응하거나 예측하기 어렵습니다.

SLAM 예시

반면, SLAM이 적용된 로봇은 실시간으로 주변 환경을 인식하고 순간적인 변화를 반영할 수 있기 때문에 훨씬 유연하고 효율적으로 움직일 수 있습니다.

즉, SLAM은 로봇에게 눈과 귀의 역할을 해주는 핵심 기술입니다.

SLAM은 어디에 있는가?주변은 어떻게 생겼는가?를 동시에 해결해주는 기술입니다. 자율주행 로봇에서는 SLAM이 감각 기관처럼 작용하고, 경로 계획 알고리즘은 뇌처럼 작동합니다. SLAM만으로는 어떻게 갈 것인가?를 판단할 수 없으며, 두 기술이 서로 보완되며 함께 동작해야 로봇이 자율적으로 움직일 수 있습니다.

SLAM의 종류

SLAM은 입력 데이터에 따라 여러 종류로 나뉩니다. 대표적으로 카메라 기반의 Visual SLAM과 LiDAR 기반의 LiDAR SLAM이 널리 사용됩니다.

Visual SLAM

카메라로 촬영한 연속 영상을 분석해 특징점이나 픽셀의 움직임을 추적하고 지도와 카메라 위치를 추정합니다. 단안 카메라, 스테레오 카메라, RGB-D 카메라 등 사용하는 카메라 구성에 따라 거리와 축척을 추정하는 방식이 달라집니다.

  • 장점: 풍부한 영상 특징과 색상 정보 활용, 비교적 작은 센서로 구성 가능
  • 단점: 조명 변화와 모션 블러, 특징이 적은 장면에 취약하며 영상 처리 연산량이 큼

Tesla 공식 홈페이지 자료

Tesla 공식 홈페이지 자료

Visual SLAM은 실내 이동 로봇, 드론, 증강현실 기기처럼 카메라 영상을 이용해 장치의 이동 경로와 주변 구조를 함께 추정해야 하는 분야에서 활용됩니다.

LiDAR SLAM

LiDAR로 연속해서 측정한 거리 데이터를 정합하여 지도를 만들고 위치를 추정합니다. MechaShip처럼 회전형 2D LiDAR를 사용하면 수평면의 360도 거리 스캔을 활용할 수 있지만, 모든 LiDAR가 360도 시야각을 제공하는 것은 아닙니다.

  • 장점: 물체까지의 거리를 직접 측정하며 조명 변화의 영향을 카메라보다 적게 받음
  • 단점: 카메라보다 색상과 문자 같은 외형 정보를 얻기 어렵고, 센서 방식에 따라 가격·시야각·햇빛과 반사 물질의 영향이 다름

삼성 공식 홈페이지 자료

삼성 공식 홈페이지 자료

회전형 LiDAR를 사용하는 일부 로봇 청소기는 주변 거리 정보를 이용해 실내 지도를 만들고 위치를 추정합니다.

이처럼 Visual SLAM과 LiDAR SLAM은 사용하는 센서와 환경에 따라 장단점이 뚜렷하며, 용도에 맞게 선택해야 합니다.

SLAM Toolbox

SLAM Toolbox는 LiDAR와 오도메트리를 이용해 2D 지도를 만들고 위치를 추정하는 패키지입니다. gmapping, cartographer, karto, hector 등의 다양한 SLAM 패키지들을 대체하기 위해 고안된 ROS 패키지입니다. 추정 속도가 빠르고 세부 조정 없이도 비교적 준수한 성능을 보인다는 평가가 있어 인기 있는 패키지 입니다.

SLAM 패키지의 성능은 LiDAR 측정 범위와 주기, 오도메트리 정확도, 이동 속도, 주변 구조와 파라미터 설정에 따라 달라집니다. SLAM Toolbox도 모든 환경에서 기본 설정만으로 정확한 지도를 보장하지 않으므로 실제 시험장에서 결과를 확인하며 이동 거리, 회전량, Loop Closure 관련 파라미터를 조정해야 합니다.

SLAM Toolbox에 대해 보다 자세한 내용이 궁금하다면 아래 링크를 참고하시기 바랍니다.

SLAM Toolbox Documentation

의존성 설치하기

SLAM Toolbox와 지도 저장 도구를 설치합니다.

sudo apt install ros-jazzy-slam-toolbox ros-jazzy-nav2-map-server

실행하기

# 로봇에서 실행합니다.
ros2 launch mechaship_bringup mechaship_bringup.launch.py
# Ubuntu PC에서 실행합니다.
ros2 launch mechaship_slam slam_toolbox.launch.py

slam_toolbox.launch.py는 RF2O와 EKF도 함께 실행합니다. 다음 명령으로 지도 토픽과 TF 연결을 확인합니다.

ros2 topic echo /map --once
ros2 run tf2_ros tf2_echo map base_footprint

RViz를 실행하고 다음과 같이 설정합니다.

  1. Fixed Framemap으로 설정합니다.
  2. Map 표시를 추가하고 토픽을 /map으로 설정합니다.
  3. LaserScan 표시를 추가하고 토픽을 /scan으로 설정합니다.
  4. 선박을 천천히 움직이며 LiDAR 스캔이 지도 위의 벽이나 고정 구조물과 계속 겹치는지 확인합니다.

SLAM 실행 예시

지도가 완성되면 다음 명령으로 지도를 저장합니다.

ros2 run nav2_map_server map_saver_cli -f mechaship_map

현재 폴더에 mechaship_map.yaml과 지도 이미지 파일이 생성됐는지 확인합니다.