통합 테스트 및 시뮬레이션 테스트 기초
통합 테스트의 필요성
통합 테스트(Integration Test)는 개별 노드나 라이브러리 단위의 기능 시험을 넘어, 여러 구성 요소가 함께 동작할 때 요구된 기능을 제대로 수행하는지 검증하기 위한 시험이다. 로봇 소프트웨어는 다양한 센서 데이터, 제어 알고리즘, 통신, 프로세스 간 상호 작용이 복잡하게 얽혀 있기 때문에, 통합 테스트 없이는 시스템 전체의 안정성을 보장하기 어렵다.
예컨대 자율주행 로봇의 경우, 라이다(LiDAR)나 카메라 센서로부터 주기적으로 들어오는 메시지가 제대로 해석되어야 하고, 이를 바탕으로 경로 계획(Path Planning)이 정상적으로 수행되어야 하며, 최종적으로 하위 제어 노드가 물리적 모터를 적절히 구동해야 한다. 각각의 노드가 단위 테스트(Unit Test)를 통과했다고 하더라도, 상호 간 메시지 형식이 불일치하거나, 타이밍 문제로 데이터가 정상적으로 연동되지 않으면 시스템 전체가 오작동할 수 있다. 이런 문제점을 조기에 발견하려면 통합 테스트가 필수적이다.
ROS2 환경에서의 통합 테스트는 주로 다음과 같은 형태로 진행된다.
컬렉션 형태 테스트: 노드 여러 개를 동시에 띄우고, 서로 간 트랜스포트 레이어(예: DDS)를 통해 메시지를 주고받게 하여 의도한 대로 시스템이 동작하는지 확인한다.
테스트 노드 추가: 실제 환경에서 얻기 힘든 메시지를 인위적으로 퍼블리시(publish)하는 노드를 만들어 두고, 다른 노드들이 이를 어떻게 처리하는지를 검사한다.
메시지 레코딩/리플레이: 이전에 로거(logger)로 기록한 실제 센서 데이터를 재생(replay)하여, 특정 동작 조건에서의 시스템 반응을 반복적으로 점검한다.
이런 통합 테스트 환경은 로컬에서 개발자가 직접 구성하기도 하지만, CI/CD(지속적 통합/지속적 배포) 시스템에서 자동으로 수행되도록 설정하기도 한다.
ROS2 통합 테스트 방법 개요
ROS2에서 통합 테스트를 수행할 때는 다음과 같은 절차를 거친다.
테스트 대상 시스템 구성 테스트하려는 노드들과 관련 설정 파일(예: 파라미터, 맵, URDF 등)을 준비한다.
테스트 실행 환경 준비 보통 다음 두 가지 방식 중 하나를 선택한다.
로컬 개발 환경에서 직접 실행
Docker 등 컨테이너 환경이나 원격 서버(CI/CD)에서 실행
테스트 시나리오 정의
원하는 입력(토픽 퍼블리시, 서비스 호출, 액션 요청 등)을 어떻게 줄 것인지 명세한다.
예상 결과(출력 토픽, 상태 변화 등)와 검증 기준을 설정한다.
테스트 코드 및 스크립트 작성
ROS2의
launch_testing모듈을 활용하여 자동화된 테스트 시퀀스를 구성한다.Python 또는 C++ 기반 GTest/pytest 등을 이용하여 결과를 검증한다.
테스트 수행 및 로그 분석
$ colcon test와 같은 빌드 툴을 활용하여 일괄적으로 테스트를 돌린다.실패한 테스트 케이스를 찾아 원인을 분석하고, 필요시 디버깅을 진행한다.
통합 테스트를 위한 주요 요소
ROS2 통합 테스트를 체계적으로 진행하기 위해서는 다음과 같은 요소들이 필요하다.
테스트 노드(Test Node): 실제 센서 대신 가짜(또는 기록된) 메시지를 퍼블리시해 주거나, 특정 입력을 만들어 주는 노드가 있다면 여러 상황에 대한 테스트를 빠르게 진행할 수 있다. 예시 코드 구조(간단히):
시스템 상태 모니터링: 여러 노드가 동시에 동작하다 보면, 토픽 메시지의 타이밍 지연, QoS 불일치, 서비스 호출 실패 등이 누적되기 쉽다. 이를 적시에 발견하려면 노드별 로그, 토픽 메시지 모니터링 도구가 필요하다. rqt_graph, rqt_topic, ros2 topic echo, ros2 topic hz 등을 통해 토픽 상태와 주기를 확인할 수 있다.
테스트 자동화 스크립트: 단발성 테스트가 아니라면, 빌드 시 자동으로 테스트를 돌려주는 환경이 필요하다. colcon test로 구동되는 단위 테스트(Unit Test)뿐 아니라, 여러 노드를 띄우는 통합 테스트 역시 자동화하려면 launch_testing 스크립트를 구성해야 한다.
예를 들어, launch_testing 기반의 간단한 예시는 다음과 같은 형태로 작성할 수 있다.
시뮬레이션 테스트 개요
물리적인 로봇 하드웨어를 매번 구동하기에는 비용과 시간이 많이 소요되며, 실제 환경에서 발생할 수 있는 위험 요소를 제어하기도 쉽지 않다. 따라서 소프트웨어 수준에서 충분히 검증하기 위해서, 로봇 운영체제와 연동할 수 있는 시뮬레이터를 활용한다. 이를 통해 다양한 시나리오(장애물 배치, 환경 조명, 움직이는 객체 등)를 가상으로 구성하고, 로봇이 문제 없이 동작하는지 검증할 수 있다.
ROS2에서 대표적으로 사용되는 시뮬레이터는 다음과 같다.
Gazebo:
가장 널리 쓰이는 로봇 시뮬레이터 중 하나로, ROS(ROS2) 공식 지원 패키지가 잘 마련되어 있음
물리 엔진(ODE, DART, Bullet 등)을 지원하며, 3D 모델링과 센서 시뮬레이션이 다양함
URDF/Xacro 등의 로봇 모델 파일을 불러와 로봇을 가상 공간에 배치해 구동할 수 있음
Ignition Gazebo (Fortress, Garden 등):
Gazebo 클래식(Gazebo-Classic)의 후속으로, 물리 엔진, 렌더링, 센서 플러그인 등이 모듈화되어 차세대 시뮬레이터로 거론됨
ROS2와 점차 연동되는 패키지들이 늘어나고 있음
Webots:
다양한 로봇 모델 예제를 제공하고, ROS2 연동 패키지가 공식 지원됨
물리 엔진을 기반으로 센서, 액추에이터가 충실히 재현되어 있어, 교육용부터 연구용까지 폭넓게 사용 가능
NVIDIA Isaac Sim:
Isaac SDK 기반의 높은 물리 시뮬레이션 정확도와 3D 그래픽 렌더링을 제공
ROS2를 지원하는 연결 패키지가 있어, 시뮬레이션 환경에서 센서 입력과 제어 신호를 교환 가능
시뮬레이션 환경 구축
시뮬레이션 테스트를 위해서는 다음 과정을 거쳐야 한다.
로봇 모델 정의:
URDF 또는 Xacro 파일로 로봇 구조, 조인트(Joint), 링크(Link), 센서 등을 정의한다.
Gazebo나 Webots, Ignition Gazebo 등에서 사용할 플러그인(센서, 제어, 물리 엔진 설정)을 포함시킨다.
시뮬레이터 설치 및 패키지 구성:
예를 들어 Gazebo의 경우,
$ sudo apt install ros-humble-gazebo-ros-pkgs등의 명령으로 ROS2용 Gazebo 패키지를 설치한다.시뮬레이터에 맞는 ROS2 브리징 패키지(예:
ros2_control,gazebo_ros2_control등)를 프로젝트 내에 추가한다.
시나리오 설정:
환경(world) 파일을 통해 지형(평지, 경사면, 계단 등), 장애물, 조명 등을 구성한다.
특정 이동 경로, 물체 배치, 자율주행에서의 가상 장애물(차량, 사람 모델) 등을 다양하게 배치해 둔다.
시뮬레이션 구동 및 노드 연동:
$ ros2 launch <pkg_name> <launch_file>형태로 시뮬레이션을 실행한다.시뮬레이터가 로봇 모델, 센서 토픽, 제어 명령 토픽 등을 ROS2 노드들과 서로 교환하면서 가상 환경에서 움직이게 된다.
테스트 자동화:
시나리오별로 반복 가능하도록
launch_testing혹은 CI 파이프라인 스크립트를 구성한다.시뮬레이터 실행 → 가상 센서 데이터 발행 → 자율주행 노드 반응 → 최종 결과 검증 과정을 자동으로 수행한다.
시뮬레이션 데이터의 활용
시뮬레이션을 통해 발생하는 데이터(센서 측정값, 경로 추종 정보 등)는 실제 하드웨어 테스트 이전에 소프트웨어 품질을 높이는 데 중요한 역할을 한다.
센서 값 재현:
가령 라이다(LiDAR) 센서를 시뮬레이션하면, 실제 환경에서 발생할 수 있는 노이즈(noise), 스캔 범위, 조밀도 등을 가상으로 만들어 낼 수 있다. 이를 통해 필터링, SLAM, 경로 계획 알고리즘 등의 성능을 미리 검증할 수 있다.
에러 주입 테스트:
일부러 극한 상황(센서 오작동, 통신 지연, CPU 부하 등)을 가정하고, 시뮬레이션에서 에러나 지연을 발생시키는 식으로 테스트한다. 이 과정을 통해 예외 처리가 올바르게 이루어지는지 점검한다.
로그 분석 및 시각화:
ROS2의 $ros2 bag record를 활용해 시뮬레이션 시 발생하는 토픽 메시지를 기록해 둘 수 있다. 또한 $ ros2 bag play로 재생하면서, 특정 구간에서 로봇 동작이 적절했는지 반복 분석할 수 있다.
시뮬레이션 통합 테스트 전략
시뮬레이션 환경에서의 통합 테스트는 다음과 같은 전략을 취한다.
크게는 시스템 레벨 시나리오 테스트:
로봇이 특정 환경(맵)에서 여러 태스크(예: 집-사무실 왕복, 장애물 회피)를 수행하도록 구동하고, 안전하게 목표점에 도달하는지, 특정 시간 안에 달성했는지 등을 확인한다.
부분 모듈 집중 테스트:
SLAM, Navigation Stack, 센서 Fusion 등 특정 모듈을 집중 점검할 때도 시뮬레이션을 활용한다. 가상 센서 입력을 의도적으로 변경하면서 해당 모듈이 잘 대응하는지 본다.
테스트 자동화 및 도커 컨테이너 활용:
GitHub Actions, GitLab CI 등과 연계하여, 새 코드를 머지(Merge)하기 전 자동으로 시뮬레이션 테스트를 수행하도록 설정한다. 로컬 PC가 아니라 클라우드 서버에서 시뮬레이터와 ROS2 노드를 띄우기 위해 Docker 컨테이너를 구성하기도 한다.
자동화된 시뮬레이션 테스트 구성
시뮬레이션 환경을 이용한 통합 테스트 역시 사람이 수동으로 실행하는 대신, CI 파이프라인이나 스크립트에서 자동으로 돌려볼 수 있도록 구성하는 편이 효율적이다. 예컨대 Gazebo나 Ignition Gazebo를 이용해 다음과 같은 프로세스를 구현할 수 있다.
시뮬레이터 실행:
$ ros2 launch <시뮬레이터 관련 패키지> <시뮬레이션.launch.py>명령으로 환경을 띄우거나,IncludeLaunchDescription를 통해 Python 스크립트에서 시뮬레이션을 자동으로 구동.
가상 센서 데이터 및 제어 노드 구동:
테스트하려는 자율주행 노드, SLAM 노드, 제어 노드 등 전체 구성요소를 함께 올린다.
종속 파라미터나 맵 파일, URDF 경로 등을 정확히 지정한다.
테스트 입력 주입:
가상의 장애물 생성, 특정 이동 경로 요청, 센서 노이즈 추가 등을 통해 실제 시나리오를 재현한다.
ROS2 액션, 서비스, 토픽 퍼블리시 등을 활용하여 테스트 노드를 통해 입력을 주입한다.
결과 검증:
예: 목적지 $p_{\text{goal}}$에 일정 시간 $t_{\max}$ 이내 도달해야 한다.
이를 프로그래밍적으로 확인하기 위해서는 아래처럼 상태 토픽을 주기적으로 모니터링한다.
위치 토픽에서 로봇의 현재 위치 $p_{\text{current}}$를 구함
$|| p_{\text{current}} - p_{\text{goal}} || \leq \epsilon$ (어느 정도 허용 오차 $\epsilon$)인지 검사
예외 발생 시 로그나 exit code를 반환하여 CI 파이프라인에서 빌드 실패로 인식할 수 있도록 한다.
로그 및 결과 보고:
$ colcon test결과 리포트, JUnit XML, 혹은 기타 테스트 리포트를 자동으로 생성한다.실패 케이스가 발견되면 해당 시뮬레이션 기록($ros2 bag$)을 저장해두고, 사후 분석에 활용한다.
이 같은 과정을 코드 레벨에서 좀 더 구체화하기 위해서는 launch_testing 스크립트와 아래와 같은 구조를 갖출 수 있다.
Hardware-In-The-Loop(HIL) 테스트
통합 테스트와 시뮬레이션 테스트를 한 단계 더 발전시키려면, 실제 하드웨어 일부 또는 전부를 연결하는 HIL(Hardware-In-The-Loop) 테스트 방식을 활용할 수 있다.
컨트롤러 HIL
모터 드라이버나 센서 보드는 실제 장치를 사용하되, 로봇이나 환경은 시뮬레이션으로 구성
예: 실제 IMU 센서만 사용하고, 라이다나 카메라 등은 가상 센서를 활용
HIL의 장점
물리 장치를 전부 구비하기 어려운 경우(비싼 센서, 대규모 환경 필요)에도 일부 현장성(하드웨어 특성)을 반영 가능
순수 시뮬레이션과 실제 완전한 필드 테스트 중간 단계로, 위험성과 비용을 절감하면서 정확도 높은 시험 수행
구현 방식
로봇 컨트롤러(예: MCU, FPGA, 제어보드)가 생성하는 신호를 시뮬레이터로 전달하고, 시뮬레이터는 가상 환경에서 움직임을 계산해 다시 센서 신호를 컨트롤러에 입력하는 구조
ROS2 메시지로는 가짜 센서 토픽과 실제 하드웨어에서 나온 제어 토픽, 혹은 반대로 실제 센서 입력과 가짜 제어 신호 등을 혼합하여 구성
시뮬레이션 테스트 시 주의사항
물리 엔진 차이 시뮬레이션의 물리 엔진(ODE, Bullet, DART 등)에 따라 결과가 약간씩 다를 수 있다. 따라서 특정 엔진에 종속된 동작(마찰계수, 조인트 제한 등)이 있으면, 실제 환경에서 같은 결과가 나오는지 별도 검증이 필요하다.
센서 플러그인 한계 Gazebo의 카메라 플러그인, 라이다 플러그인 등은 실제 센서의 노이즈나 에러 특성을 100% 일치시킬 수 없을 때가 많다. 필요한 경우 노이즈 모델을 직접 추가하거나, 정량적 측정을 통해 보정값을 반영해야 한다.
시뮬레이션 성능 문제 시뮬레이션이 복잡해질수록 CPU/GPU 부하가 커지고, 토픽 전송 지연이 발생할 수 있다. 이는 실제 로봇보다 더 나쁜 성능을 야기할 수도 있고, 반대로 더 좋은 성능(느린 시뮬레이션 속도)으로 과소평가될 수도 있다. 테스트 시에는 충분한 시스템 리소스가 확보되도록 주의한다.
간단 예시 흐름도
아래는 시뮬레이션 테스트 파이프라인의 단순 개념 흐름도 예시이다(mermaid 사용).
가상 환경에서의 자율주행 테스트 예시
자율주행 로봇의 시뮬레이션 테스트를 예로 들면, ROS2 Navigation2(네비게이션 스택)를 이용하는 경우가 대표적이다. 다음은 전체적인 절차 예시다.
로봇 모델 준비
URDF/Xacro 기반으로 이동 로봇 모델을 정의.
센서(예: Lidar, Depth Camera 등)와 조인트(휠, 서스펜션 등)을 시뮬레이터에서 인식할 수 있도록 설정.
ROS2 Control 및 Diff Drive Controller(또는 Ackermann Controller) 등으로 바퀴 구동을 구현.
맵 및 시뮬레이션 월드 파일 구성
2D 맵(pgm/yaml) 파일 또는 3D 월드(sdf) 파일에 장애물, 바닥, 벽 등을 적절히 설정한다.
$ ros2 launch <시뮬레이터_pkg> <world.launch.py>명령으로 해당 환경을 구동할 수 있게 한다.
Navigation2 스택 설정
$ ros2 launch nav2_bringup navigation_launch.py등의 패키지를 사용.Localization 방법(AMCL, SLAM), Global Planner, Local Planner, Costmap 파라미터 등을 원하는 대로 수정.
목표지점 설정
$ ros2 action send_goal /navigate_to_pose를 통해 임의의 좌표를 목표지점으로 설정한다.혹은 RViz2를 통해 GUI 상에서 목표지점을 클릭해 설정한다.
결과 검증
일정 시간 내 로봇이 목표지점에 도달했는지 확인한다.
토픽
/amcl_pose,/odom등을 모니터링하거나,$ ros2 topic echo /tf를 통해 로봇 위치 변화를 살핀다.계획된 경로
/plan이 정상적으로 생성되었는지, 장애물 회피가 원활히 수행되는지도 확인한다.
이 과정을 자동화하기 위해 launch_testing 또는 Python 스크립트에서 다음과 같은 테스트 시퀀스를 구축한다.
시뮬레이터와 로봇 bringup을 동시에 실행
가상의 목표 위치를 액션으로 전송
주기적으로 로봇의 위치를 폴링(Polling)하여 목표 지점 도달 여부 확인
일정 시간 이내 도달 성공 시 테스트 통과, 실패 시 실패 로그 출력
시뮬레이션 테스트 패키지 구조 예시
ROS2 프로젝트에서 시뮬레이션 테스트를 수행할 때, 패키지를 구성하는 예시(간략화)이다.
launch/sim_bringup.launch.py: Gazebo(또는 다른 시뮬레이터)와 로봇 URDF를 로드하고, 환경(world) 설정을 한다.launch/nav_bringup.launch.py: Navigation2, SLAM, TF 등 로봇 소프트웨어 스택을 구동한다.test/디렉터리에 있는 Python 스크립트에서는launch_testing를 활용하여 위 두 개의 launch 파일을 조합한 뒤, 목표 지점 설정, 로봇 위치 모니터링, 결과 검사 등을 자동화한다.
시뮬레이션 검증 결과 해석
시뮬레이션 테스트 결과가 통과했다고 해서, 실제 로봇 환경에서도 100% 동일한 결과가 나올 수 있는 것은 아니다. 다만 시뮬레이션에서 발생 가능한 문제(예: 노드 간 메시지 형식 불일치, 잘못된 파라미터 설정, 플래너 로직 버그 등)를 사전에 발견하고 해결할 수 있다는 점에서 큰 이점이 있다.
통합 테스트 관점: 하드웨어 없이도 노드 간 통신, launch 설정, QoS 세팅, TF 트리 구조 등을 한 번에 점검할 수 있음.
환경 재현: 실제로 복잡하거나 위험한 환경(사람이 붐비는 공간, 빛이 강하게 들어오는 곳 등)을 시뮬레이터에서 어느 정도 재현해본 뒤, 문제 없이 동작하면 실제 필드 테스트 비용과 실패 리스크를 낮출 수 있음.
이처럼 ROS2 기반 로봇 시스템 개발에서 통합 테스트와 시뮬레이션 테스트는 필수적인 품질 보증 단계이다.
Last updated