1.1 문서 목적
본 문서는 터틀봇3 버거를 이용한 실내 자율 순찰 시스템의 핵심 노드인 patrol_manager의 상세설계를 정의한다.
patrol_manager는 설정 파일에 등록된 순찰 지점을 순서대로 이동하며 다음 기능을 수행한다.
- 순찰 시작, 중지, 일시정지 및 재개
- Nav2 이동 목표 전송
- 현재 순찰 지점 관리
- 순찰 반복 횟수 관리
- 이동 실패 재시도
- 이상 이벤트 발생 시 일시정지
- 배터리 부족 시 대기 위치 복귀
- 비상정지 처리
- 원격 PC GUI에 순찰 상태 전송
본 설계서는 ROS 2 노드의 클래스 구조, 토픽, 서비스, 액션, 파라미터, 상태 전이, 예외 처리 및 단위시험 항목을 포함한다.
2. 적용 시스템
2.1 대상 로봇
| 항목 | 내용 |
|---|---|
| 로봇 | TurtleBot3 Burger |
| 구동 방식 | 차동 구동형 모바일 로봇 |
| 주행 제어 | ROS 2 Navigation2 |
| 위치 추정 | AMCL |
| 지도 | SLAM으로 작성된 2차원 지도 |
| 거리 센서 | 2D LiDAR |
| 로봇 제어 컴퓨터 | 터틀봇3 내부 SBC |
| 사용자 인터페이스 | 원격 PC GUI |
| 통신 방식 | 무선 네트워크 기반 ROS 2 DDS 통신 |
2.2 시스템 실행 구성
터틀봇3 내부 SBC에서는 다음 프로그램을 실행한다.
- TurtleBot3 Bringup
- LiDAR 드라이버
- OpenCR 통신 노드
- Nav2
- AMCL
patrol_manager
원격 PC에서는 다음 프로그램을 실행한다.
- 순찰 제어 GUI
- RViz2
- 지도 및 로봇 위치 표시
- 순찰 시작, 중지, 일시정지 및 재개 명령 전송
- 순찰 상태 및 오류 로그 표시
patrol_manager는 네트워크가 일시적으로 끊기더라도 현재 상태를 유지할 수 있도록 터틀봇3 내부 SBC에서 실행하는 것을 기본으로 한다.
3. 모듈명
3.1 노드명
patrol_manager
3.2 패키지명
turtlebot3_patrol
3.3 실행 파일명
patrol_manager_node
3.4 네임스페이스
단일 로봇을 운용하는 경우 기본 네임스페이스를 사용한다.
/patrol_manager
다중 로봇 운용 시 로봇별 네임스페이스를 적용한다.
/tb3_01/patrol_manager
/tb3_02/patrol_manager
4. 목적
patrol_manager는 설정 파일에 정의된 순찰 지점을 순서대로 이동하고, 각 지점의 도착 여부와 대기시간을 관리한다.
주요 목적은 다음과 같다.
- 순찰 지점 목록을 설정 파일에서 불러온다.
- 순찰 시작 조건을 검사한다.
- 현재 순찰 지점을 Nav2 이동 목표로 전송한다.
- Nav2 이동 결과를 확인한다.
- 이동 성공 시 다음 순찰 지점으로 전환한다.
- 이동 실패 시 설정된 횟수만큼 재시도한다.
- 마지막 지점 완료 시 순찰 횟수를 증가시킨다.
- 지정된 반복 횟수만큼 순찰을 수행한다.
- 이상 이벤트 발생 시 이동을 일시정지한다.
- 배터리가 부족하면 순찰을 종료하고 대기 위치로 복귀한다.
- 비상정지 입력이 발생하면 현재 이동을 즉시 취소한다.
- 현재 상태를 원격 PC GUI에 전송한다.
5. 선행 조건
patrol_manager 실행 전 다음 조건이 충족되어야 한다.
- 터틀봇3 Bringup이 정상 실행되어야 한다.
- LiDAR 데이터가 정상 발행되어야 한다.
- 로봇의 오도메트리 데이터가 정상 발행되어야 한다.
- 지도 서버가 실행되어야 한다.
- AMCL 위치 추정이 완료되어야 한다.
- Nav2 서버가 활성화되어야 한다.
- 로봇의 초기 위치가 설정되어야 한다.
- 순찰 지점 설정 파일이 존재해야 한다.
- 터틀봇3와 원격 PC가 동일한 ROS 2 네트워크에 연결되어야 한다.
- 원격 PC와 터틀봇3의
ROS_DOMAIN_ID가 동일해야 한다.
6. 입력 인터페이스
6.1 입력 목록
| 구분 | 인터페이스명 | 자료형 | 설명 |
|---|---|---|---|
| 서비스 | /patrol_manager/start | std_srvs/srv/Trigger | 순찰 시작 요청 |
| 서비스 | /patrol_manager/stop | std_srvs/srv/Trigger | 순찰 중지 요청 |
| 서비스 | /patrol_manager/pause | std_srvs/srv/Trigger | 사용자 순찰 일시정지 요청 |
| 서비스 | /patrol_manager/resume | std_srvs/srv/Trigger | 순찰 재개 요청 |
| 토픽 | /operation_mode | std_msgs/msg/String | 현재 로봇 운용 모드 |
| 토픽 | /battery_state | sensor_msgs/msg/BatteryState | 배터리 잔량 및 전압 |
| 토픽 | /anomaly_event | turtlebot3_patrol_msgs/msg/AnomalyEvent | 이상 이벤트 |
| 토픽 | /emergency_stop | std_msgs/msg/Bool | 비상정지 상태 |
| 액션 결과 | /navigate_to_pose | nav2_msgs/action/NavigateToPose | Nav2 이동 결과 |
| TF | /tf, /tf_static | tf2_msgs/msg/TFMessage | 로봇 위치 및 좌표 변환 |
6.2 순찰 시작 서비스
서비스명은 다음과 같다.
/patrol_manager/start
서비스 형식은 다음과 같다.
std_srvs/srv/Trigger
순찰 시작 요청을 수신하면 다음 항목을 검사한다.
- 현재 상태가
IDLE,STOPPED또는COMPLETED인지 확인한다. - 비상정지 상태가 해제되어 있는지 확인한다.
- 운용 모드가 순찰 허용 모드인지 확인한다.
- 배터리가 순찰 시작 기준 이상인지 확인한다.
- Nav2 액션 서버가 사용 가능한지 확인한다.
- 순찰 지점이 1개 이상 등록되어 있는지 확인한다.
- AMCL 위치가 정상인지 확인한다.
모든 조건이 정상인 경우 서비스 응답은 다음과 같다.
success: true
message: "Patrol started"
조건이 만족되지 않는 경우 서비스 응답은 다음과 같다.
success: false
message: "Patrol start rejected: low battery"
6.3 순찰 중지 서비스
서비스명은 다음과 같다.
/patrol_manager/stop
순찰 중지 요청을 수신하면 다음 작업을 수행한다.
- 현재 Nav2 목표를 취소한다.
- 대기 타이머를 중지한다.
- 재시도 횟수를 초기화한다.
- 순찰 실행 상태를 해제한다.
- 상태를
STOPPED로 변경한다. - 중지 이벤트를 발행한다.
6.4 순찰 일시정지 서비스
서비스명은 다음과 같다.
/patrol_manager/pause
순찰 일시정지 요청을 수신하면 다음 작업을 수행한다.
- 현재 Nav2 목표를 취소한다.
- 현재 순찰 지점 번호를 유지한다.
- 순찰 횟수를 유지한다.
- 상태를
PAUSED_USER로 변경한다. - 일시정지 이벤트를 발행한다.
6.5 순찰 재개 서비스
서비스명은 다음과 같다.
/patrol_manager/resume
재개 요청을 수신하면 다음 조건을 검사한다.
- 현재 상태가
PAUSED_USER또는PAUSED_ANOMALY인지 확인한다. - 이상 이벤트가 해제되었는지 확인한다.
- 비상정지가 해제되었는지 확인한다.
- 배터리가 복귀 기준 이상인지 확인한다.
- Nav2 액션 서버가 사용 가능한지 확인한다.
조건이 정상인 경우 현재 순찰 지점을 다시 목표로 전송한다.
6.6 운용 모드 입력
토픽명은 다음과 같다.
/operation_mode
허용되는 값은 다음과 같다.
| 운용 모드 | 설명 |
|---|---|
IDLE | 대기 모드 |
MANUAL | 수동 조작 모드 |
PATROL | 일반 순찰 모드 |
NIGHT_PATROL | 야간 순찰 모드 |
RETURN_HOME | 대기 위치 복귀 모드 |
EMERGENCY | 비상정지 모드 |
순찰 시작이 허용되는 모드는 다음과 같다.
PATROL
NIGHT_PATROL
6.7 배터리 상태 입력
토픽명은 다음과 같다.
/battery_state
사용 필드는 다음과 같다.
| 필드 | 사용 목적 |
|---|---|
percentage | 배터리 잔량 판단 |
voltage | 배터리 전압 이상 판단 |
power_supply_status | 충전 상태 확인 |
percentage 값이 0.0~1.0 범위로 수신되는 경우 백분율로 변환한다.
battery_percentage = percentage × 100.0
배터리 잔량 정보가 제공되지 않는 경우 전압을 이용한 별도 환산 로직을 적용할 수 있다.
6.8 이상 이벤트 입력
토픽명은 다음과 같다.
/anomaly_event
메시지 형식은 다음과 같이 정의한다.
string event_id
string event_type
uint8 severity
bool active
string description
builtin_interfaces/Time detected_time
severity 값은 다음과 같이 정의한다.
| 값 | 등급 | 처리 |
|---|---|---|
| 0 | 정보 | 로그만 저장 |
| 1 | 주의 | GUI 알림 |
| 2 | 경고 | 순찰 일시정지 |
| 3 | 위험 | 즉시 정지 및 관리자 확인 |
| 4 | 긴급 | 비상정지 처리 |
6.9 비상정지 입력
토픽명은 다음과 같다.
/emergency_stop
메시지 값이 true이면 다음 작업을 즉시 수행한다.
- 현재 Nav2 목표를 취소한다.
- 순찰 타이머를 중지한다.
- 속도 명령이 계속 발생하지 않도록 상태를 변경한다.
- 상태를
EMERGENCY_STOP으로 변경한다. - 순찰 재개 요청을 거부한다.
- 비상정지 이벤트를 원격 GUI에 발행한다.
7. 출력 인터페이스
7.1 출력 목록
| 구분 | 인터페이스명 | 자료형 | 설명 |
|---|---|---|---|
| 액션 목표 | /navigate_to_pose | nav2_msgs/action/NavigateToPose | Nav2 이동 목표 |
| 토픽 | /patrol_manager/status | turtlebot3_patrol_msgs/msg/PatrolStatus | 현재 순찰 상태 |
| 토픽 | /patrol_manager/current_point | turtlebot3_patrol_msgs/msg/PatrolPointStatus | 현재 순찰 지점 |
| 토픽 | /patrol_manager/event | turtlebot3_patrol_msgs/msg/PatrolEvent | 순찰 이벤트 |
| 토픽 | /patrol_manager/log | std_msgs/msg/String | GUI 표시용 로그 |
| 토픽 | /return_home/request | std_msgs/msg/Bool | 대기 위치 복귀 요청 |
| 토픽 | /cmd_vel | geometry_msgs/msg/Twist | 비상정지 시 정지 명령 |
7.2 Nav2 이동 목표
Nav2 액션 서버명은 다음과 같다.
/navigate_to_pose
액션 형식은 다음과 같다.
nav2_msgs/action/NavigateToPose
목표 메시지 설정은 다음과 같다.
goal.pose.header.frame_id = "map"
goal.pose.header.stamp = 현재 시각
goal.pose.pose.position.x = 순찰 지점 x 좌표
goal.pose.pose.position.y = 순찰 지점 y 좌표
goal.pose.pose.position.z = 0.0
goal.pose.pose.orientation = yaw를 quaternion으로 변환한 값
7.3 순찰 상태 메시지
토픽명은 다음과 같다.
/patrol_manager/status
메시지 형식은 다음과 같이 정의한다.
std_msgs/Header header
string state
bool patrol_active
bool paused
bool emergency_stop
int32 current_index
int32 total_points
int32 completed_cycles
int32 target_cycles
int32 retry_count
float32 battery_percentage
string current_goal_id
string last_result
string status_message
원격 GUI는 이 메시지를 이용하여 다음 정보를 표시한다.
- 현재 순찰 상태
- 현재 순찰 지점
- 전체 순찰 지점 개수
- 완료한 순찰 횟수
- 목표 순찰 횟수
- 현재 재시도 횟수
- 배터리 잔량
- 마지막 이동 결과
- 오류 메시지
7.4 현재 순찰 지점 메시지
토픽명은 다음과 같다.
/patrol_manager/current_point
메시지 형식은 다음과 같이 정의한다.
std_msgs/Header header
string point_id
int32 point_index
float64 x
float64 y
float64 yaw
float32 wait_time_sec
string point_state
point_state 값은 다음과 같다.
PENDING
MOVING
ARRIVED
WAITING
FAILED
SKIPPED
7.5 순찰 이벤트 메시지
토픽명은 다음과 같다.
/patrol_manager/event
메시지 형식은 다음과 같이 정의한다.
std_msgs/Header header
string event_type
string point_id
string event_code
string description
uint8 severity
event_type 값은 다음과 같다.
PATROL_STARTED
PATROL_STOPPED
PATROL_PAUSED
PATROL_RESUMED
GOAL_SENT
GOAL_REACHED
GOAL_FAILED
GOAL_RETRY
POINT_SKIPPED
CYCLE_COMPLETED
PATROL_COMPLETED
LOW_BATTERY
RETURN_HOME_REQUESTED
ANOMALY_DETECTED
ANOMALY_CLEARED
EMERGENCY_STOPPED
8. 순찰 지점 설정
8.1 순찰 지점 파일
순찰 지점은 YAML 파일로 관리한다.
기본 파일 경로는 다음과 같다.
turtlebot3_patrol/config/patrol_points.yaml
8.2 순찰 지점 파일 형식
patrol_points:
- id: "P01"
frame_id: "map"
x: 1.20
y: 0.50
yaw: 0.00
wait_time_sec: 5.0
- id: "P02"
frame_id: "map"
x: 2.80
y: 0.50
yaw: 1.57
wait_time_sec: 8.0
- id: "P03"
frame_id: "map"
x: 2.80
y: 2.20
yaw: 3.14
wait_time_sec: 5.0
- id: "P04"
frame_id: "map"
x: 1.20
y: 2.20
yaw: -1.57
wait_time_sec: 10.0
home_point:
id: "HOME"
frame_id: "map"
x: 0.30
y: 0.30
yaw: 0.00
8.3 순찰 지점 자료구조
struct PatrolPoint
{
std::string id;
std::string frame_id;
double x;
double y;
double yaw;
double wait_time_sec;
};
8.4 순찰 지점 검증
설정 파일을 불러올 때 다음 항목을 검사한다.
patrol_points항목이 존재하는지 확인한다.- 순찰 지점이 1개 이상인지 확인한다.
- 각 지점에
id,x,y,yaw가 존재하는지 확인한다. - 순찰 지점 ID가 중복되지 않는지 확인한다.
wait_time_sec가 0 이상인지 확인한다.frame_id가 비어 있으면map을 기본값으로 사용한다.home_point가 존재하는지 확인한다.- 잘못된 값이 존재하면 노드 초기화를 실패 처리한다.
9. 내부 변수
| 변수명 | 자료형 | 초기값 | 설명 |
|---|---|---|---|
patrol_points_ | std::vector<PatrolPoint> | 빈 목록 | 전체 순찰 위치 목록 |
home_point_ | PatrolPoint | 기본값 | 대기 위치 |
current_index_ | int | 0 | 현재 순찰 위치 번호 |
completed_cycles_ | int | 0 | 완료한 순찰 횟수 |
retry_count_ | int | 0 | 현재 지점 이동 재시도 횟수 |
patrol_active_ | bool | false | 순찰 실행 상태 |
paused_by_anomaly_ | bool | false | 이상 이벤트에 의한 일시정지 |
paused_by_user_ | bool | false | 사용자 요청에 의한 일시정지 |
emergency_stop_active_ | bool | false | 비상정지 상태 |
low_battery_active_ | bool | false | 배터리 부족 상태 |
current_goal_id_ | std::string | 빈 문자열 | 현재 이동 목표 ID |
current_state_ | PatrolState | IDLE | 현재 상태 |
operation_mode_ | std::string | IDLE | 현재 운용 모드 |
battery_percentage_ | double | 100.0 | 현재 배터리 잔량 |
last_nav_result_ | std::string | 빈 문자열 | 마지막 Nav2 이동 결과 |
goal_in_progress_ | bool | false | Nav2 목표 수행 여부 |
waiting_at_point_ | bool | false | 순찰 지점 대기 상태 |
anomaly_event_id_ | std::string | 빈 문자열 | 현재 이상 이벤트 ID |
patrol_start_time_ | rclcpp::Time | 0 | 순찰 시작 시각 |
point_arrival_time_ | rclcpp::Time | 0 | 순찰 지점 도착 시각 |
last_status_publish_time_ | rclcpp::Time | 0 | 마지막 상태 발행 시각 |
nav_goal_handle_ | 액션 목표 핸들 | null | 현재 Nav2 목표 핸들 |
wait_timer_ | ROS 2 Timer | null | 순찰 지점 대기 타이머 |
status_timer_ | ROS 2 Timer | null | 상태 주기 발행 타이머 |
battery_check_timer_ | ROS 2 Timer | null | 배터리 상태 검사 타이머 |
10. 파라미터
| 파라미터 | 자료형 | 기본값 | 설명 |
|---|---|---|---|
patrol_points_file | 문자열 | config/patrol_points.yaml | 순찰 지점 설정 파일 |
default_wait_time_sec | 실수 | 5.0 | 지점별 대기시간이 없을 때 적용 |
max_retry_count | 정수 | 2 | 이동 실패 최대 재시도 횟수 |
retry_delay_sec | 실수 | 2.0 | 이동 재시도 전 대기시간 |
low_battery_threshold | 실수 | 30.0 | 순찰 종료 및 복귀 기준 |
critical_battery_threshold | 실수 | 15.0 | 즉시 이동 중지 기준 |
start_battery_threshold | 실수 | 40.0 | 순찰 시작 허용 기준 |
continue_on_failure | 불리언 | true | 실패 후 다음 지점 이동 여부 |
patrol_repeat_count | 정수 | 0 | 0이면 무한 반복 |
allowed_operation_mode | 문자열 배열 | PATROL, NIGHT_PATROL | 순찰 허용 모드 |
nav_action_name | 문자열 | /navigate_to_pose | Nav2 액션 서버명 |
nav_server_wait_sec | 실수 | 5.0 | 액션 서버 연결 대기시간 |
goal_response_timeout_sec | 실수 | 5.0 | 목표 수락 응답 제한시간 |
navigation_timeout_sec | 실수 | 120.0 | 지점 이동 제한시간 |
status_publish_rate_hz | 실수 | 2.0 | 상태 메시지 발행 주기 |
battery_check_rate_hz | 실수 | 1.0 | 배터리 검사 주기 |
auto_resume_after_anomaly | 불리언 | false | 이상 해제 후 자동 재개 여부 |
return_home_on_stop | 불리언 | false | 사용자 중지 시 대기 위치 복귀 여부 |
return_home_on_complete | 불리언 | true | 순찰 완료 후 대기 위치 복귀 여부 |
publish_zero_velocity_on_emergency | 불리언 | true | 비상정지 시 정지 속도 발행 여부 |
zero_velocity_publish_count | 정수 | 10 | 비상정지 시 정지 명령 반복 횟수 |
use_sim_time | 불리언 | false | 시뮬레이션 시간 사용 여부 |
10.1 파라미터 파일 예시
patrol_manager:
ros__parameters:
patrol_points_file: "/home/ubuntu/turtlebot3_ws/src/turtlebot3_patrol/config/patrol_points.yaml"
default_wait_time_sec: 5.0
max_retry_count: 2
retry_delay_sec: 2.0
start_battery_threshold: 40.0
low_battery_threshold: 30.0
critical_battery_threshold: 15.0
continue_on_failure: true
patrol_repeat_count: 0
allowed_operation_mode:
- "PATROL"
- "NIGHT_PATROL"
nav_action_name: "/navigate_to_pose"
nav_server_wait_sec: 5.0
goal_response_timeout_sec: 5.0
navigation_timeout_sec: 120.0
status_publish_rate_hz: 2.0
battery_check_rate_hz: 1.0
auto_resume_after_anomaly: false
return_home_on_stop: false
return_home_on_complete: true
publish_zero_velocity_on_emergency: true
zero_velocity_publish_count: 10
11. 상태 정의
11.1 상태 목록
enum class PatrolState
{
IDLE,
VALIDATING,
NAVIGATING,
WAITING,
PAUSED_USER,
PAUSED_ANOMALY,
RETRY_WAIT,
RETURNING_HOME,
COMPLETED,
STOPPED,
ERROR,
EMERGENCY_STOP
};
11.2 상태별 설명
| 상태 | 설명 |
|---|---|
IDLE | 순찰 시작 전 대기 상태 |
VALIDATING | 순찰 시작 조건 검사 상태 |
NAVIGATING | 현재 순찰 지점으로 이동 중 |
WAITING | 순찰 지점 도착 후 대기 중 |
PAUSED_USER | 사용자 요청으로 일시정지 |
PAUSED_ANOMALY | 이상 이벤트로 일시정지 |
RETRY_WAIT | 이동 실패 후 재시도 대기 |
RETURNING_HOME | 대기 위치로 복귀 중 |
COMPLETED | 설정된 순찰 횟수 완료 |
STOPPED | 사용자 요청으로 순찰 중지 |
ERROR | 복구할 수 없는 오류 발생 |
EMERGENCY_STOP | 비상정지 상태 |
11.3 상태 전이
| 현재 상태 | 발생 조건 | 다음 상태 |
|---|---|---|
IDLE | 순찰 시작 요청 | VALIDATING |
VALIDATING | 시작 조건 정상 | NAVIGATING |
VALIDATING | 시작 조건 실패 | IDLE |
NAVIGATING | 목표 도착 성공 | WAITING |
NAVIGATING | 이동 실패 및 재시도 가능 | RETRY_WAIT |
NAVIGATING | 이동 실패 및 재시도 초과 | NAVIGATING 또는 ERROR |
WAITING | 대기시간 완료 | NAVIGATING |
NAVIGATING | 이상 이벤트 발생 | PAUSED_ANOMALY |
WAITING | 이상 이벤트 발생 | PAUSED_ANOMALY |
NAVIGATING | 사용자 일시정지 | PAUSED_USER |
WAITING | 사용자 일시정지 | PAUSED_USER |
PAUSED_USER | 재개 요청 | NAVIGATING |
PAUSED_ANOMALY | 이상 해제 및 재개 승인 | NAVIGATING |
| 모든 순찰 상태 | 배터리 부족 | RETURNING_HOME |
| 모든 상태 | 비상정지 발생 | EMERGENCY_STOP |
RETURNING_HOME | 대기 위치 도착 | STOPPED 또는 COMPLETED |
WAITING | 목표 순찰 횟수 완료 | COMPLETED |
| 모든 순찰 상태 | 중지 요청 | STOPPED |
12. 클래스 설계
12.1 클래스명
class PatrolManager : public rclcpp::Node
12.2 주요 멤버 함수
| 함수명 | 설명 |
|---|---|
declareParameters() | ROS 2 파라미터 선언 |
loadParameters() | 파라미터 값 읽기 |
loadPatrolPoints() | YAML 순찰 지점 파일 읽기 |
validatePatrolPoints() | 순찰 지점 데이터 검증 |
createInterfaces() | 토픽, 서비스, 액션 및 타이머 생성 |
handleStartRequest() | 순찰 시작 서비스 처리 |
handleStopRequest() | 순찰 중지 서비스 처리 |
handlePauseRequest() | 순찰 일시정지 서비스 처리 |
handleResumeRequest() | 순찰 재개 서비스 처리 |
validateStartConditions() | 순찰 시작 조건 검사 |
sendCurrentGoal() | 현재 순찰 지점을 Nav2 목표로 전송 |
sendGoal() | 지정 위치를 Nav2 목표로 전송 |
handleGoalResponse() | Nav2 목표 수락 여부 처리 |
handleGoalFeedback() | Nav2 이동 피드백 처리 |
handleGoalResult() | Nav2 이동 결과 처리 |
handleNavigationSuccess() | 이동 성공 처리 |
handleNavigationFailure() | 이동 실패 처리 |
scheduleRetry() | 이동 재시도 예약 |
startPointWait() | 순찰 지점 대기 시작 |
handlePointWaitComplete() | 순찰 지점 대기 완료 처리 |
advanceToNextPoint() | 다음 순찰 지점으로 전환 |
completePatrolCycle() | 순찰 1회 완료 처리 |
checkPatrolCompletion() | 전체 순찰 완료 여부 확인 |
cancelCurrentGoal() | 현재 Nav2 목표 취소 |
requestReturnHome() | 대기 위치 복귀 요청 |
sendHomeGoal() | 대기 위치 Nav2 목표 전송 |
handleBatteryState() | 배터리 상태 저장 |
checkBatteryCondition() | 배터리 부족 여부 검사 |
handleAnomalyEvent() | 이상 이벤트 처리 |
handleEmergencyStop() | 비상정지 처리 |
publishStatus() | 현재 순찰 상태 발행 |
publishCurrentPoint() | 현재 순찰 지점 발행 |
publishEvent() | 순찰 이벤트 발행 |
publishLog() | GUI용 로그 발행 |
changeState() | 순찰 상태 변경 |
publishZeroVelocity() | 비상정지용 정지 명령 발행 |
13. 초기화 처리
노드가 시작되면 다음 순서로 초기화한다.
- 노드명을
patrol_manager로 설정한다. - ROS 2 파라미터를 선언한다.
- 파라미터 값을 읽는다.
- 순찰 지점 YAML 파일을 읽는다.
- 순찰 지점 데이터를 검증한다.
- 대기 위치 데이터를 검증한다.
- Nav2 액션 클라이언트를 생성한다.
- 서비스 서버를 생성한다.
- 입력 토픽 구독자를 생성한다.
- 상태 및 이벤트 발행자를 생성한다.
- 상태 발행 타이머를 생성한다.
- 배터리 검사 타이머를 생성한다.
- 내부 변수를 초기화한다.
- 현재 상태를
IDLE로 설정한다. - 초기 상태 메시지를 발행한다.
순찰 지점 설정 파일을 읽을 수 없거나 필수 데이터가 누락된 경우 상태를 ERROR로 설정하고 순찰 시작 요청을 거부한다.
14. 순찰 시작 처리 절차
14.1 시작 요청 처리
/patrol_manager/start서비스 요청을 수신한다.- 현재 상태가 시작 가능한 상태인지 확인한다.
- 상태를
VALIDATING으로 변경한다. - 비상정지 상태를 확인한다.
- 현재 운용 모드를 확인한다.
- 배터리 잔량을 확인한다.
- 순찰 지점 목록을 확인한다.
- Nav2 액션 서버 연결 상태를 확인한다.
- AMCL 위치 추정 상태를 확인한다.
- 모든 조건이 정상이면 내부 변수를 초기화한다.
current_index_를 0으로 설정한다.completed_cycles_를 0으로 설정한다.retry_count_를 0으로 설정한다.patrol_active_를true로 설정한다.- 순찰 시작 시각을 저장한다.
PATROL_STARTED이벤트를 발행한다.- 첫 번째 순찰 지점을 Nav2 목표로 전송한다.
- 상태를
NAVIGATING으로 변경한다.
14.2 시작 조건 검사
다음 조건 중 하나라도 만족하지 않으면 순찰 시작을 거부한다.
emergency_stop_active_ == true
operation_mode_가 허용된 모드가 아님
battery_percentage_ < start_battery_threshold
patrol_points_.empty() == true
Nav2 액션 서버 연결 실패
현재 상태가 ERROR
현재 순찰이 이미 실행 중
15. 순찰 지점 이동 처리
15.1 현재 목표 선택
현재 목표는 다음과 같이 선택한다.
const PatrolPoint & target = patrol_points_.at(current_index_);
현재 지점 ID를 저장한다.
current_goal_id_ = target.id;
15.2 Nav2 목표 전송
- 현재 순찰 지점 데이터를 읽는다.
PoseStamped메시지를 생성한다.- 좌표계는 순찰 지점의
frame_id를 사용한다. - 기본 좌표계는
map으로 설정한다. x,y좌표를 설정한다.yaw값을 quaternion으로 변환한다.- 목표 전송 시각을 저장한다.
- 목표 상태를
MOVING으로 발행한다. - Nav2 액션 서버에 목표를 전송한다.
- 상태를
NAVIGATING으로 변경한다.
15.3 목표 수락 처리
Nav2가 목표를 수락한 경우 다음 작업을 수행한다.
goal_in_progress_ = true
last_nav_result_ = "ACCEPTED"
Nav2가 목표를 거부한 경우 이동 실패 처리 절차를 수행한다.
15.4 이동 피드백 처리
Nav2 피드백에서 다음 정보를 사용할 수 있다.
- 현재 위치
- 남은 거리
- 예상 남은 시간
- 복구 동작 횟수
원격 GUI 표시를 위해 다음 정보를 상태 메시지에 포함할 수 있다.
distance_remaining
estimated_time_remaining
number_of_recoveries
복구 동작 횟수가 비정상적으로 증가하면 경고 로그를 발행한다.
15.5 이동 성공 처리
Nav2 결과가 SUCCEEDED이면 다음 작업을 수행한다.
goal_in_progress_를false로 설정한다.retry_count_를 0으로 초기화한다.- 도착 시각을 기록한다.
- 현재 지점 상태를
ARRIVED로 발행한다. GOAL_REACHED이벤트를 발행한다.- 현재 지점의 대기시간을 확인한다.
- 대기시간이 0보다 크면 상태를
WAITING으로 변경한다. - 대기 타이머를 시작한다.
- 대기시간이 0이면 즉시 다음 지점으로 전환한다.
16. 순찰 지점 대기 처리
순찰 지점에 도착한 후 다음 절차를 수행한다.
- 로봇 이동을 정지 상태로 유지한다.
- 현재 지점 상태를
WAITING으로 발행한다. - 지점별
wait_time_sec를 읽는다. - 값이 없으면
default_wait_time_sec를 사용한다. - 대기 타이머를 시작한다.
- 대기 중 이상 이벤트와 비상정지 입력을 계속 확인한다.
- 대기시간이 완료되면 다음 순찰 지점으로 전환한다.
대기 도중 이상 이벤트가 발생하면 대기 타이머의 남은 시간을 별도로 저장하지 않고, 순찰 재개 시 현재 지점 이동부터 다시 수행하는 것을 기본으로 한다.
17. 다음 순찰 지점 전환
다음 순찰 지점은 다음과 같이 결정한다.
current_index_++;
current_index_가 순찰 지점 개수보다 작은 경우 다음 지점으로 이동한다.
if (current_index_ < static_cast<int>(patrol_points_.size()))
{
sendCurrentGoal();
}
current_index_가 순찰 지점 개수 이상이면 순찰 1회를 완료한 것으로 처리한다.
if (current_index_ >= static_cast<int>(patrol_points_.size()))
{
completePatrolCycle();
}
18. 순찰 횟수 관리
마지막 순찰 지점의 대기까지 완료하면 다음 작업을 수행한다.
completed_cycles_를 1 증가시킨다.CYCLE_COMPLETED이벤트를 발행한다.- 목표 순찰 횟수를 확인한다.
patrol_repeat_count가 0이면 무한 반복한다.
if (patrol_repeat_count_ == 0)
{
current_index_ = 0;
sendCurrentGoal();
}
completed_cycles_가 설정된 반복 횟수보다 작은 경우 첫 번째 지점부터 다시 시작한다.
if (completed_cycles_ < patrol_repeat_count_)
{
current_index_ = 0;
sendCurrentGoal();
}
목표 반복 횟수에 도달한 경우 다음 작업을 수행한다.
patrol_active_를false로 설정한다.- 상태를
COMPLETED로 변경한다. PATROL_COMPLETED이벤트를 발행한다.return_home_on_complete가true이면 대기 위치로 복귀한다.
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가 최신 순찰 상태를 다시 수신한다.
- 모든 단위시험과 통합시험을 통과한다.