19. 이동 실패 처리
19.1 이동 실패 조건
다음 Nav2 결과를 이동 실패로 처리한다.
ABORTED
CANCELED
UNKNOWN
목표 수락 거부
이동 제한시간 초과
Nav2 서버 연결 해제
사용자 일시정지, 이상 이벤트 및 비상정지에 의한 목표 취소는 일반 이동 실패 횟수에 포함하지 않는다.
19.2 이동 실패 처리 절차
이동 실패 발생
↓
실패 원인 확인
↓
사용자 중지 또는 비상정지인가?
├─ 예 → 재시도하지 않음
└─ 아니오
↓
재시도 횟수 증가
↓
최대 재시도 이하인가?
├─ 예 → 재시도 대기 후 현재 목표 재전송
└─ 아니오
↓
실패 로그 저장
↓
continue_on_failure 확인
├─ true → 다음 지점 이동
└─ false → 순찰 종료 및 ERROR 전환
19.3 재시도 처리
이동 실패 시 다음과 같이 재시도 횟수를 증가시킨다.
retry_count_++;
재시도 횟수가 최대 재시도 횟수 이하이면 다음 작업을 수행한다.
- 상태를
RETRY_WAIT로 변경한다. GOAL_RETRY이벤트를 발행한다.retry_delay_sec동안 대기한다.- 동일한 순찰 지점을 다시 Nav2 목표로 전송한다.
판단 조건은 다음과 같다.
if (retry_count_ <= max_retry_count_)
{
scheduleRetry();
}
19.4 최대 재시도 초과 처리
최대 재시도 횟수를 초과하면 다음 작업을 수행한다.
- 현재 지점 상태를
FAILED로 발행한다. GOAL_FAILED이벤트를 발행한다.- 실패 원인과 시각을 로그로 저장한다.
retry_count_를 0으로 초기화한다.continue_on_failure값을 확인한다.
continue_on_failure가 true이면 현재 지점을 건너뛰고 다음 지점으로 이동한다.
continue_on_failure가 false이면 순찰을 종료하고 상태를 ERROR로 변경한다.
20. 이상 이벤트 처리
20.1 이상 이벤트 발생
severity가 2 이상이고 active가 true이면 다음 작업을 수행한다.
- 이상 이벤트 ID를 저장한다.
paused_by_anomaly_를true로 설정한다.- 현재 Nav2 목표를 취소한다.
- 대기 타이머를 중지한다.
- 현재 순찰 지점 번호를 유지한다.
- 재시도 횟수를 유지한다.
- 상태를
PAUSED_ANOMALY로 변경한다. ANOMALY_DETECTED이벤트를 발행한다.- 원격 GUI에 관리자 확인 필요 상태를 표시한다.
20.2 이상 이벤트 해제
동일한 이상 이벤트 ID에 대해 active가 false로 수신되면 다음 작업을 수행한다.
paused_by_anomaly_를false로 설정한다.- 이상 이벤트 ID를 초기화한다.
ANOMALY_CLEARED이벤트를 발행한다.auto_resume_after_anomaly값을 확인한다.
auto_resume_after_anomaly가 true이면 현재 순찰 지점부터 자동 재개한다.
auto_resume_after_anomaly가 false이면 관리자의 재개 요청을 기다린다.
21. 배터리 부족 처리
21.1 순찰 시작 배터리 기준
배터리 잔량이 start_battery_threshold보다 낮으면 순찰 시작을 허용하지 않는다.
기본값은 다음과 같다.
40.0%
21.2 순찰 중 배터리 부족
순찰 중 배터리 잔량이 low_battery_threshold 이하가 되면 다음 작업을 수행한다.
low_battery_active_를true로 설정한다.- 현재 Nav2 목표를 취소한다.
- 순찰 지점 대기 타이머를 중지한다.
LOW_BATTERY이벤트를 발행한다.- 순찰 실행 상태를 해제한다.
- 상태를
RETURNING_HOME으로 변경한다. - 대기 위치를 Nav2 목표로 전송한다.
기본값은 다음과 같다.
30.0%
21.3 위험 배터리 처리
배터리 잔량이 critical_battery_threshold 이하가 되면 다음 작업을 수행한다.
- 현재 Nav2 목표를 즉시 취소한다.
- 로봇 정지 명령을 발행한다.
- 자동 복귀를 시도하지 않는다.
- 상태를
ERROR로 변경한다. - 원격 GUI에 긴급 충전 요청을 표시한다.
기본값은 다음과 같다.
15.0%
배터리가 위험 수준인 경우 대기 위치까지 이동하는 것보다 현재 위치에서 정지하는 것을 우선한다.
22. 대기 위치 복귀 처리
22.1 복귀 발생 조건
다음 조건에서 대기 위치 복귀를 수행한다.
- 배터리 부족
- 순찰 완료
- 관리자 복귀 명령
- 설정에 따른 순찰 중지 후 복귀
22.2 복귀 처리 절차
- 현재 Nav2 목표를 취소한다.
- 순찰 실행 상태를 해제한다.
- 상태를
RETURNING_HOME으로 변경한다. /return_home/request에true를 발행한다.- 설정 파일의
home_point를 읽는다. - 대기 위치를 Nav2 목표로 전송한다.
- 대기 위치 도착 여부를 확인한다.
- 도착하면 상태를
STOPPED또는COMPLETED로 변경한다. - 복귀 완료 이벤트를 발행한다.
대기 위치 복귀가 실패하면 설정된 max_retry_count만큼 재시도한다.
복귀 재시도까지 실패하면 상태를 ERROR로 변경하고 원격 GUI에 수동 이동 요청을 표시한다.
23. 비상정지 처리
23.1 비상정지 우선순위
비상정지는 모든 명령과 상태보다 우선한다.
이벤트 처리 우선순위는 다음과 같다.
비상정지
배터리 위험
배터리 부족
이상 이벤트
사용자 중지
사용자 일시정지
Nav2 이동 결과
순찰 지점 대기 완료
23.2 비상정지 절차
/emergency_stop에서true를 수신한다.emergency_stop_active_를true로 설정한다.- 현재 Nav2 목표를 취소한다.
- 모든 내부 타이머를 중지한다.
patrol_active_를false로 설정한다.- 상태를
EMERGENCY_STOP으로 변경한다. /cmd_vel에 0 속도 명령을 반복 발행한다.EMERGENCY_STOPPED이벤트를 발행한다.- 순찰 시작 및 재개 요청을 거부한다.
정지 명령은 다음과 같다.
linear.x = 0.0
linear.y = 0.0
linear.z = 0.0
angular.x = 0.0
angular.y = 0.0
angular.z = 0.0
23.3 비상정지 해제
/emergency_stop에서 false를 수신해도 자동으로 순찰을 재개하지 않는다.
비상정지 해제 후 다음 절차를 수행한다.
emergency_stop_active_를false로 설정한다.- 상태를
STOPPED로 변경한다. - 관리자가 로봇 상태를 확인한다.
- 관리자가 순찰 시작 요청을 다시 전송한다.
- 첫 번째 순찰 지점부터 새 순찰을 시작한다.
24. 사용자 중지 처리
순찰 중지 요청이 발생하면 다음 작업을 수행한다.
- 현재 Nav2 목표를 취소한다.
- 대기 타이머를 중지한다.
patrol_active_를false로 설정한다.paused_by_user_를false로 설정한다.paused_by_anomaly_를false로 설정한다.retry_count_를 0으로 초기화한다.- 상태를
STOPPED로 변경한다. PATROL_STOPPED이벤트를 발행한다.
return_home_on_stop이 true이면 대기 위치 복귀 절차를 수행한다.
25. 원격 PC GUI 연동
25.1 GUI 기능
원격 PC GUI는 다음 기능을 제공한다.
- 순찰 시작
- 순찰 중지
- 순찰 일시정지
- 순찰 재개
- 현재 로봇 위치 표시
- 순찰 지점 표시
- 현재 목표 지점 강조
- 순찰 상태 표시
- 완료한 순찰 횟수 표시
- 배터리 잔량 표시
- 이상 이벤트 표시
- Nav2 이동 실패 표시
- 비상정지 상태 표시
- 로그 표시
25.2 GUI 명령 연결
| GUI 버튼 | 호출 인터페이스 |
|---|---|
| 순찰 시작 | /patrol_manager/start |
| 순찰 중지 | /patrol_manager/stop |
| 일시정지 | /patrol_manager/pause |
| 순찰 재개 | /patrol_manager/resume |
| 비상정지 | /emergency_stop에 true 발행 |
| 비상정지 해제 | /emergency_stop에 false 발행 |
25.3 GUI 상태 표시
GUI는 /patrol_manager/status를 구독하여 상태를 표시한다.
상태별 표시 문구는 다음과 같다.
| 상태 | GUI 표시 |
|---|---|
IDLE | 순찰 대기 |
VALIDATING | 시작 조건 확인 중 |
NAVIGATING | 순찰 지점 이동 중 |
WAITING | 순찰 지점 점검 중 |
PAUSED_USER | 사용자 일시정지 |
PAUSED_ANOMALY | 이상 감지로 일시정지 |
RETRY_WAIT | 이동 재시도 대기 |
RETURNING_HOME | 대기 위치 복귀 중 |
COMPLETED | 순찰 완료 |
STOPPED | 순찰 중지 |
ERROR | 오류 발생 |
EMERGENCY_STOP | 비상정지 |
25.4 통신 단절 처리
원격 PC와 터틀봇3 사이의 네트워크가 끊어져도 patrol_manager는 로봇 내부에서 계속 실행된다.
통신 단절 시 처리 기준은 다음과 같다.
- GUI 상태 갱신이 중단된다.
- 현재 순찰은 로봇 내부에서 계속 수행한다.
- 비상정지와 배터리 부족 처리는 계속 수행한다.
- 네트워크가 복구되면 최신 상태를 GUI에 다시 전송한다.
- 상태 토픽은
transient_localQoS를 사용하여 늦게 연결된 GUI가 최신 상태를 수신하도록 한다.
26. QoS 설계
| 인터페이스 | Reliability | Durability | History |
|---|---|---|---|
/patrol_manager/status | Reliable | Transient Local | Keep Last 1 |
/patrol_manager/current_point | Reliable | Transient Local | Keep Last 1 |
/patrol_manager/event | Reliable | Volatile | Keep Last 50 |
/patrol_manager/log | Reliable | Volatile | Keep Last 100 |
/battery_state | Reliable | Volatile | Keep Last 10 |
/anomaly_event | Reliable | Volatile | Keep Last 20 |
/emergency_stop | Reliable | Transient Local | Keep Last 1 |
/operation_mode | Reliable | Transient Local | Keep Last 1 |
/cmd_vel | Reliable | Volatile | Keep Last 10 |
27. 콜백 및 실행 구조
27.1 콜백 그룹
상태 변경 충돌을 방지하기 위해 콜백 그룹을 구분한다.
| 콜백 그룹 | 유형 | 포함 기능 |
|---|---|---|
state_callback_group_ | Mutually Exclusive | 시작, 중지, 일시정지, 재개 |
nav_callback_group_ | Reentrant | Nav2 목표 응답, 피드백, 결과 |
safety_callback_group_ | Mutually Exclusive | 배터리, 이상 이벤트, 비상정지 |
timer_callback_group_ | Mutually Exclusive | 상태 발행, 배터리 검사, 대기 타이머 |
27.2 Executor
다음 Executor 사용을 기본으로 한다.
rclcpp::executors::MultiThreadedExecutor
상태를 변경하는 모든 함수에서는 mutex를 사용하여 내부 변수의 동시 접근을 방지한다.
std::mutex state_mutex_;
28. 주요 처리 의사코드
28.1 순찰 시작
bool PatrolManager::startPatrol()
{
std::lock_guard<std::mutex> lock(state_mutex_);
changeState(PatrolState::VALIDATING);
if (!validateStartConditions()) {
changeState(PatrolState::IDLE);
return false;
}
current_index_ = 0;
completed_cycles_ = 0;
retry_count_ = 0;
patrol_active_ = true;
paused_by_user_ = false;
paused_by_anomaly_ = false;
patrol_start_time_ = now();
publishEvent("PATROL_STARTED", "", "Patrol started", 0);
sendCurrentGoal();
return true;
}
28.2 현재 순찰 지점 전송
void PatrolManager::sendCurrentGoal()
{
if (!patrol_active_) {
return;
}
if (current_index_ < 0 ||
current_index_ >= static_cast<int>(patrol_points_.size())) {
changeState(PatrolState::ERROR);
return;
}
const auto & point = patrol_points_.at(current_index_);
current_goal_id_ = point.id;
retry_count_ = std::max(retry_count_, 0);
publishCurrentPoint(point, "MOVING");
publishEvent("GOAL_SENT", point.id, "Navigation goal sent", 0);
sendGoal(point);
changeState(PatrolState::NAVIGATING);
}
28.3 이동 성공
void PatrolManager::handleNavigationSuccess()
{
goal_in_progress_ = false;
retry_count_ = 0;
point_arrival_time_ = now();
const auto & point = patrol_points_.at(current_index_);
publishCurrentPoint(point, "ARRIVED");
publishEvent("GOAL_REACHED", point.id, "Patrol point reached", 0);
startPointWait(point.wait_time_sec);
}
28.4 이동 실패
void PatrolManager::handleNavigationFailure(
const std::string & reason)
{
goal_in_progress_ = false;
last_nav_result_ = reason;
if (emergency_stop_active_ ||
paused_by_user_ ||
paused_by_anomaly_ ||
!patrol_active_) {
return;
}
retry_count_++;
if (retry_count_ <= max_retry_count_) {
changeState(PatrolState::RETRY_WAIT);
publishEvent(
"GOAL_RETRY",
current_goal_id_,
"Retry navigation: " + std::to_string(retry_count_),
1);
scheduleRetry();
return;
}
publishCurrentPoint(
patrol_points_.at(current_index_),
"FAILED");
publishEvent(
"GOAL_FAILED",
current_goal_id_,
reason,
2);
retry_count_ = 0;
if (continue_on_failure_) {
advanceToNextPoint();
} else {
patrol_active_ = false;
changeState(PatrolState::ERROR);
}
}
28.5 다음 지점 이동
void PatrolManager::advanceToNextPoint()
{
current_index_++;
if (current_index_ < static_cast<int>(patrol_points_.size())) {
sendCurrentGoal();
return;
}
completePatrolCycle();
}
28.6 순찰 1회 완료
void PatrolManager::completePatrolCycle()
{
completed_cycles_++;
publishEvent(
"CYCLE_COMPLETED",
"",
"Patrol cycle completed",
0);
if (patrol_repeat_count_ == 0 ||
completed_cycles_ < patrol_repeat_count_) {
current_index_ = 0;
sendCurrentGoal();
return;
}
patrol_active_ = false;
changeState(PatrolState::COMPLETED);
publishEvent(
"PATROL_COMPLETED",
"",
"All patrol cycles completed",
0);
if (return_home_on_complete_) {
requestReturnHome();
}
}
29. 로그 설계
29.1 로그 레벨
| 로그 레벨 | 사용 조건 |
|---|---|
DEBUG | 내부 상태, 인덱스, 타이머 정보 |
INFO | 순찰 시작, 목표 전송, 도착, 순찰 완료 |
WARN | 이동 재시도, 배터리 부족 접근, 이상 이벤트 |
ERROR | 목표 실패, 설정 파일 오류, Nav2 연결 실패 |
FATAL | 노드 실행을 계속할 수 없는 초기화 오류 |
29.2 주요 로그 형식
[PATROL][START] cycle=0 point=P01
[PATROL][GOAL_SENT] index=0 id=P01 x=1.20 y=0.50 yaw=0.00
[PATROL][ARRIVED] index=0 id=P01
[PATROL][RETRY] index=1 id=P02 retry=1 reason=ABORTED
[PATROL][FAILED] index=1 id=P02 reason=TIMEOUT
[PATROL][CYCLE_COMPLETED] completed_cycles=1
[PATROL][LOW_BATTERY] battery=29.5
[PATROL][RETURN_HOME] id=HOME
[PATROL][EMERGENCY_STOP] source=/emergency_stop
29.3 로그 저장 항목
다음 항목을 파일 로그 또는 rosbag에 저장할 수 있다.
- 순찰 시작 및 종료 시각
- 각 지점 목표 전송 시각
- 각 지점 도착 시각
- 지점별 이동 소요시간
- 이동 실패 원인
- 재시도 횟수
- 이상 이벤트 발생 시각
- 배터리 부족 발생 시각
- 대기 위치 복귀 결과
- 비상정지 발생 시각
30. 파일 구성
turtlebot3_patrol/
├── CMakeLists.txt
├── package.xml
├── include/
│ └── turtlebot3_patrol/
│ └── patrol_manager.hpp
├── src/
│ ├── patrol_manager.cpp
│ └── patrol_manager_main.cpp
├── config/
│ ├── patrol_manager.yaml
│ └── patrol_points.yaml
├── launch/
│ ├── patrol_manager.launch.py
│ └── turtlebot3_patrol_system.launch.py
├── test/
│ ├── test_patrol_manager.cpp
│ ├── test_patrol_points.cpp
│ └── test_patrol_state.cpp
└── README.md
31. Launch 설계
31.1 Launch 파일
파일명은 다음과 같다.
patrol_manager.launch.py
31.2 Launch 구성 예시
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os
def generate_launch_description():
package_share = get_package_share_directory('turtlebot3_patrol')
default_param_file = os.path.join(
package_share,
'config',
'patrol_manager.yaml'
)
param_file_arg = DeclareLaunchArgument(
'params_file',
default_value=default_param_file
)
patrol_manager_node = Node(
package='turtlebot3_patrol',
executable='patrol_manager_node',
name='patrol_manager',
output='screen',
parameters=[
LaunchConfiguration('params_file')
],
respawn=True,
respawn_delay=3.0
)
return LaunchDescription([
param_file_arg,
patrol_manager_node
])
32. 실행 절차
32.1 터틀봇3 내부 SBC
터틀봇3 Bringup을 실행한다.
export TURTLEBOT3_MODEL=burger
export ROS_DOMAIN_ID=30
ros2 launch turtlebot3_bringup robot.launch.py
Nav2를 실행한다.
ros2 launch turtlebot3_navigation2 navigation2.launch.py \
use_sim_time:=False \
map:=$HOME/maps/patrol_map.yaml
순찰 관리 노드를 실행한다.
ros2 launch turtlebot3_patrol patrol_manager.launch.py
32.2 원격 PC
원격 PC에 동일한 ROS Domain ID를 설정한다.
export TURTLEBOT3_MODEL=burger
export ROS_DOMAIN_ID=30
RViz2를 실행한다.
ros2 launch turtlebot3_navigation2 rviz2.launch.py
GUI 프로그램을 실행한다.
ros2 run turtlebot3_patrol_gui patrol_gui
33. 서비스 시험 명령
순찰 시작 명령은 다음과 같다.
ros2 service call /patrol_manager/start std_srvs/srv/Trigger "{}"
순찰 중지 명령은 다음과 같다.
ros2 service call /patrol_manager/stop std_srvs/srv/Trigger "{}"
순찰 일시정지 명령은 다음과 같다.
ros2 service call /patrol_manager/pause std_srvs/srv/Trigger "{}"
순찰 재개 명령은 다음과 같다.
ros2 service call /patrol_manager/resume std_srvs/srv/Trigger "{}"
34. 토픽 시험 명령
운용 모드를 순찰 모드로 설정한다.
ros2 topic pub --once /operation_mode std_msgs/msg/String \
"{data: 'PATROL'}"
이상 이벤트를 발생시킨다.
ros2 topic pub --once /anomaly_event \
turtlebot3_patrol_msgs/msg/AnomalyEvent \
"{
event_id: 'ANOMALY_001',
event_type: 'PERSON_DETECTED',
severity: 2,
active: true,
description: 'Unknown person detected'
}"
이상 이벤트를 해제한다.
ros2 topic pub --once /anomaly_event \
turtlebot3_patrol_msgs/msg/AnomalyEvent \
"{
event_id: 'ANOMALY_001',
event_type: 'PERSON_DETECTED',
severity: 2,
active: false,
description: 'Anomaly cleared'
}"
비상정지를 발생시킨다.
ros2 topic pub --once /emergency_stop std_msgs/msg/Bool \
"{data: true}"
비상정지를 해제한다.
ros2 topic pub --once /emergency_stop std_msgs/msg/Bool \
"{data: false}"
순찰 상태를 확인한다.
ros2 topic echo /patrol_manager/status
35. 단위시험 항목
35.1 순찰 지점 파일 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 정상 파일 읽기 | 유효한 YAML 파일 | 모든 순찰 지점 로드 |
| 파일 없음 | 존재하지 않는 경로 | 노드 상태 ERROR |
| 순찰 지점 없음 | 빈 목록 | 순찰 시작 거부 |
| 필수 좌표 누락 | x 또는 y 없음 | 설정 오류 처리 |
| 중복 ID | 동일 ID 2개 | 설정 오류 처리 |
| 잘못된 대기시간 | 음수 값 | 설정 오류 처리 |
| 대기 위치 누락 | home_point 없음 | 복귀 기능 비활성 또는 초기화 실패 |
35.2 순찰 시작 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 정상 순찰 시작 | 모드 정상, 배터리 정상 | 첫 지점 목표 전송 |
| 잘못된 운용 모드 | MANUAL | 시작 요청 거부 |
| 배터리 부족 | 시작 기준 미만 | 시작 요청 거부 |
| 비상정지 상태 | 비상정지 활성 | 시작 요청 거부 |
| Nav2 미실행 | 액션 서버 없음 | 시작 요청 거부 |
| 순찰 중 재시작 | 이미 실행 중 | 중복 시작 거부 |
35.3 순찰 지점 전환 시험
| 시험 항목 | 시험 내용 | 예상 결과 |
|---|---|---|
| 첫 순찰 지점 선택 | 순찰 시작 | P01 선택 |
| 다음 순찰 지점 전환 | P01 도착 및 대기 완료 | P02 선택 |
| 마지막 지점 처리 | 마지막 지점 완료 | 순찰 횟수 증가 |
| 첫 지점 복귀 | 다음 순찰 반복 | P01 재선택 |
| 지점 대기시간 | 지점 도착 | 설정 시간 동안 WAITING |
| 대기시간 0 | 지점 도착 | 즉시 다음 지점 이동 |
35.4 순찰 횟수 시험
| 시험 항목 | 설정 | 예상 결과 |
|---|---|---|
| 1회 순찰 | patrol_repeat_count=1 | 1회 후 완료 |
| 3회 순찰 | patrol_repeat_count=3 | 3회 후 완료 |
| 무한 순찰 | patrol_repeat_count=0 | 중지 전까지 반복 |
| 순찰 횟수 증가 | 마지막 지점 완료 | completed_cycles_ 증가 |
35.5 이동 실패 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 1회 이동 실패 | 재시도 가능 | 동일 목표 재전송 |
| 최대 재시도 이하 | 실패 2회 | 재시도 수행 |
| 최대 재시도 초과 | 실패 3회 이상 | 실패 로그 저장 |
| 실패 후 계속 | continue_on_failure=true | 다음 지점 이동 |
| 실패 후 종료 | continue_on_failure=false | 상태 ERROR |
| 사용자 취소 | 일시정지 요청 | 실패 횟수 증가 없음 |
| 이동 제한시간 초과 | 제한시간 초과 | 이동 실패 처리 |
35.6 이상 이벤트 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 이상 이벤트 발생 | severity=2, active=true | 순찰 일시정지 |
| 위험 이벤트 발생 | severity=3 | 목표 취소 및 관리자 확인 |
| 정보 이벤트 발생 | severity=0 | 로그만 저장 |
| 이상 이벤트 해제 | active=false | 재개 가능 상태 |
| 관리자 재개 요청 | 이상 해제 후 resume | 현재 지점 재전송 |
| 자동 재개 | 자동 재개 활성 | 이상 해제 후 자동 이동 |
35.7 배터리 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 배터리 정상 | 80% | 순찰 계속 |
| 시작 기준 미만 | 35% | 순찰 시작 거부 |
| 복귀 기준 이하 | 29% | 순찰 종료 및 복귀 |
| 위험 기준 이하 | 14% | 즉시 정지 |
| 복귀 중 목표 성공 | 대기 위치 도착 | STOPPED |
| 복귀 중 목표 실패 | 최대 재시도 초과 | ERROR |
35.8 비상정지 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 이동 중 비상정지 | true 수신 | 목표 즉시 취소 |
| 대기 중 비상정지 | true 수신 | 대기 타이머 중지 |
| 비상정지 상태 시작 요청 | start 호출 | 요청 거부 |
| 비상정지 해제 | false 수신 | 자동 재개하지 않음 |
| 정지 속도 발행 | 비상정지 발생 | 0 속도 반복 발행 |
35.9 사용자 제어 시험
| 시험 항목 | 입력 조건 | 예상 결과 |
|---|---|---|
| 순찰 일시정지 | pause 호출 | 현재 목표 취소 |
| 일시정지 후 재개 | resume 호출 | 현재 지점 재전송 |
| 순찰 중지 | stop 호출 | 상태 STOPPED |
| 중지 후 재시작 | start 호출 | 첫 지점부터 시작 |
| 완료 후 재시작 | start 호출 | 순찰 횟수 초기화 |
35.10 원격 GUI 시험
| 시험 항목 | 시험 내용 | 예상 결과 |
|---|---|---|
| 상태 표시 | 상태 토픽 구독 | 현재 상태 표시 |
| 현재 지점 표시 | 지점 토픽 구독 | 현재 목표 강조 |
| 배터리 표시 | 상태 메시지 확인 | 배터리 잔량 표시 |
| 이동 실패 표시 | 실패 이벤트 발생 | GUI 경고 표시 |
| 비상정지 표시 | 비상정지 발생 | 긴급 상태 표시 |
| GUI 재접속 | 실행 중 GUI 재시작 | 최신 상태 즉시 수신 |
| 네트워크 복구 | 통신 단절 후 재연결 | 상태 갱신 재개 |
36. 통합시험 시나리오
36.1 정상 순찰 시나리오
- 터틀봇3 Bringup을 실행한다.
- Nav2와 AMCL을 실행한다.
- 초기 위치를 설정한다.
- 운용 모드를
PATROL로 설정한다. - GUI에서 순찰 시작 버튼을 누른다.
- 첫 번째 순찰 지점으로 이동하는지 확인한다.
- 지점 도착 후 설정된 시간 동안 대기하는지 확인한다.
- 다음 지점으로 이동하는지 확인한다.
- 마지막 지점 완료 후 순찰 횟수가 증가하는지 확인한다.
- 설정된 반복 횟수 완료 후 대기 위치로 복귀하는지 확인한다.
36.2 이동 실패 시나리오
- 순찰을 시작한다.
- 현재 목표 앞에 장애물을 배치한다.
- Nav2가 복구 동작을 수행하는지 확인한다.
- 이동 실패 결과가 발생하는지 확인한다.
- 동일 지점을 재시도하는지 확인한다.
- 최대 재시도 초과 후 다음 지점으로 이동하는지 확인한다.
- 실패 이벤트가 GUI에 표시되는지 확인한다.
36.3 이상 이벤트 시나리오
- 순찰 중 이상 이벤트를 발생시킨다.
- 현재 Nav2 목표가 취소되는지 확인한다.
- 상태가
PAUSED_ANOMALY로 변경되는지 확인한다. - GUI에 이상 이벤트가 표시되는지 확인한다.
- 이상 이벤트를 해제한다.
- 관리자 재개 요청을 전송한다.
- 중단된 순찰 지점부터 다시 이동하는지 확인한다.
36.4 배터리 부족 시나리오
- 순찰을 시작한다.
- 배터리 잔량을 복귀 기준 이하로 입력한다.
- 현재 순찰 목표가 취소되는지 확인한다.
- 상태가
RETURNING_HOME으로 변경되는지 확인한다. - 대기 위치가 Nav2 목표로 전송되는지 확인한다.
- 대기 위치 도착 후 순찰이 종료되는지 확인한다.
36.5 비상정지 시나리오
- 터틀봇3가 순찰 지점으로 이동하도록 한다.
- GUI에서 비상정지 버튼을 누른다.
- Nav2 목표가 즉시 취소되는지 확인한다.
- 로봇이 정지하는지 확인한다.
- 상태가
EMERGENCY_STOP으로 변경되는지 확인한다. - 비상정지를 해제한다.
- 자동으로 이동하지 않는지 확인한다.
- 새 순찰 시작 요청 후 첫 지점부터 이동하는지 확인한다.
37. 완료 기준
patrol_manager는 다음 조건을 모두 만족하면 개발 완료로 판단한다.
- YAML 파일에서 순찰 지점을 정상적으로 불러온다.
- 원격 PC GUI에서 순찰 시작과 중지가 가능하다.
- 첫 번째 지점부터 마지막 지점까지 순서대로 이동한다.
- 각 지점에서 설정된 시간 동안 대기한다.
- 마지막 지점 완료 후 순찰 횟수가 증가한다.
- 지정된 횟수만큼 순찰을 반복한다.
- 이동 실패 시 설정된 횟수만큼 재시도한다.
- 최대 재시도 초과 시 설정에 따라 다음 지점으로 이동하거나 순찰을 종료한다.
- 이상 이벤트 발생 시 현재 이동을 중지하고 순찰을 일시정지한다.
- 이상 이벤트 해제 후 관리자 요청으로 순찰을 재개한다.
- 배터리 부족 시 현재 순찰을 종료하고 대기 위치로 복귀한다.
- 위험 배터리 상태에서는 현재 위치에서 즉시 정지한다.
- 비상정지 발생 시 모든 순찰 동작을 즉시 중지한다.
- 비상정지 해제 후 자동으로 순찰을 재개하지 않는다.
- 원격 PC GUI에서 현재 상태, 현재 지점, 배터리 및 오류를 확인할 수 있다.
- 네트워크 재연결 후 GUI가 최신 순찰 상태를 다시 수신한다.
- 모든 단위시험과 통합시험을 통과한다.