사무실 안내·순찰 로봇 핵심 노드 상세설계서 작성 예시

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는 설정 파일에 정의된 순찰 지점을 순서대로 이동하고, 각 지점의 도착 여부와 대기시간을 관리한다.

주요 목적은 다음과 같다.

  1. 순찰 지점 목록을 설정 파일에서 불러온다.
  2. 순찰 시작 조건을 검사한다.
  3. 현재 순찰 지점을 Nav2 이동 목표로 전송한다.
  4. Nav2 이동 결과를 확인한다.
  5. 이동 성공 시 다음 순찰 지점으로 전환한다.
  6. 이동 실패 시 설정된 횟수만큼 재시도한다.
  7. 마지막 지점 완료 시 순찰 횟수를 증가시킨다.
  8. 지정된 반복 횟수만큼 순찰을 수행한다.
  9. 이상 이벤트 발생 시 이동을 일시정지한다.
  10. 배터리가 부족하면 순찰을 종료하고 대기 위치로 복귀한다.
  11. 비상정지 입력이 발생하면 현재 이동을 즉시 취소한다.
  12. 현재 상태를 원격 PC GUI에 전송한다.

5. 선행 조건

patrol_manager 실행 전 다음 조건이 충족되어야 한다.

  1. 터틀봇3 Bringup이 정상 실행되어야 한다.
  2. LiDAR 데이터가 정상 발행되어야 한다.
  3. 로봇의 오도메트리 데이터가 정상 발행되어야 한다.
  4. 지도 서버가 실행되어야 한다.
  5. AMCL 위치 추정이 완료되어야 한다.
  6. Nav2 서버가 활성화되어야 한다.
  7. 로봇의 초기 위치가 설정되어야 한다.
  8. 순찰 지점 설정 파일이 존재해야 한다.
  9. 터틀봇3와 원격 PC가 동일한 ROS 2 네트워크에 연결되어야 한다.
  10. 원격 PC와 터틀봇3의 ROS_DOMAIN_ID가 동일해야 한다.

6. 입력 인터페이스

6.1 입력 목록

구분인터페이스명자료형설명
서비스/patrol_manager/startstd_srvs/srv/Trigger순찰 시작 요청
서비스/patrol_manager/stopstd_srvs/srv/Trigger순찰 중지 요청
서비스/patrol_manager/pausestd_srvs/srv/Trigger사용자 순찰 일시정지 요청
서비스/patrol_manager/resumestd_srvs/srv/Trigger순찰 재개 요청
토픽/operation_modestd_msgs/msg/String현재 로봇 운용 모드
토픽/battery_statesensor_msgs/msg/BatteryState배터리 잔량 및 전압
토픽/anomaly_eventturtlebot3_patrol_msgs/msg/AnomalyEvent이상 이벤트
토픽/emergency_stopstd_msgs/msg/Bool비상정지 상태
액션 결과/navigate_to_posenav2_msgs/action/NavigateToPoseNav2 이동 결과
TF/tf, /tf_statictf2_msgs/msg/TFMessage로봇 위치 및 좌표 변환

6.2 순찰 시작 서비스

서비스명은 다음과 같다.

/patrol_manager/start

서비스 형식은 다음과 같다.

std_srvs/srv/Trigger

순찰 시작 요청을 수신하면 다음 항목을 검사한다.

  1. 현재 상태가 IDLE, STOPPED 또는 COMPLETED인지 확인한다.
  2. 비상정지 상태가 해제되어 있는지 확인한다.
  3. 운용 모드가 순찰 허용 모드인지 확인한다.
  4. 배터리가 순찰 시작 기준 이상인지 확인한다.
  5. Nav2 액션 서버가 사용 가능한지 확인한다.
  6. 순찰 지점이 1개 이상 등록되어 있는지 확인한다.
  7. AMCL 위치가 정상인지 확인한다.

모든 조건이 정상인 경우 서비스 응답은 다음과 같다.

success: true
message: "Patrol started"

조건이 만족되지 않는 경우 서비스 응답은 다음과 같다.

success: false
message: "Patrol start rejected: low battery"

6.3 순찰 중지 서비스

서비스명은 다음과 같다.

/patrol_manager/stop

순찰 중지 요청을 수신하면 다음 작업을 수행한다.

  1. 현재 Nav2 목표를 취소한다.
  2. 대기 타이머를 중지한다.
  3. 재시도 횟수를 초기화한다.
  4. 순찰 실행 상태를 해제한다.
  5. 상태를 STOPPED로 변경한다.
  6. 중지 이벤트를 발행한다.

6.4 순찰 일시정지 서비스

서비스명은 다음과 같다.

/patrol_manager/pause

순찰 일시정지 요청을 수신하면 다음 작업을 수행한다.

  1. 현재 Nav2 목표를 취소한다.
  2. 현재 순찰 지점 번호를 유지한다.
  3. 순찰 횟수를 유지한다.
  4. 상태를 PAUSED_USER로 변경한다.
  5. 일시정지 이벤트를 발행한다.

6.5 순찰 재개 서비스

서비스명은 다음과 같다.

/patrol_manager/resume

재개 요청을 수신하면 다음 조건을 검사한다.

  1. 현재 상태가 PAUSED_USER 또는 PAUSED_ANOMALY인지 확인한다.
  2. 이상 이벤트가 해제되었는지 확인한다.
  3. 비상정지가 해제되었는지 확인한다.
  4. 배터리가 복귀 기준 이상인지 확인한다.
  5. 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이면 다음 작업을 즉시 수행한다.

  1. 현재 Nav2 목표를 취소한다.
  2. 순찰 타이머를 중지한다.
  3. 속도 명령이 계속 발생하지 않도록 상태를 변경한다.
  4. 상태를 EMERGENCY_STOP으로 변경한다.
  5. 순찰 재개 요청을 거부한다.
  6. 비상정지 이벤트를 원격 GUI에 발행한다.

7. 출력 인터페이스

7.1 출력 목록

구분인터페이스명자료형설명
액션 목표/navigate_to_posenav2_msgs/action/NavigateToPoseNav2 이동 목표
토픽/patrol_manager/statusturtlebot3_patrol_msgs/msg/PatrolStatus현재 순찰 상태
토픽/patrol_manager/current_pointturtlebot3_patrol_msgs/msg/PatrolPointStatus현재 순찰 지점
토픽/patrol_manager/eventturtlebot3_patrol_msgs/msg/PatrolEvent순찰 이벤트
토픽/patrol_manager/logstd_msgs/msg/StringGUI 표시용 로그
토픽/return_home/requeststd_msgs/msg/Bool대기 위치 복귀 요청
토픽/cmd_velgeometry_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 순찰 지점 검증

설정 파일을 불러올 때 다음 항목을 검사한다.

  1. patrol_points 항목이 존재하는지 확인한다.
  2. 순찰 지점이 1개 이상인지 확인한다.
  3. 각 지점에 id, x, y, yaw가 존재하는지 확인한다.
  4. 순찰 지점 ID가 중복되지 않는지 확인한다.
  5. wait_time_sec가 0 이상인지 확인한다.
  6. frame_id가 비어 있으면 map을 기본값으로 사용한다.
  7. home_point가 존재하는지 확인한다.
  8. 잘못된 값이 존재하면 노드 초기화를 실패 처리한다.

9. 내부 변수

변수명자료형초기값설명
patrol_points_std::vector<PatrolPoint>빈 목록전체 순찰 위치 목록
home_point_PatrolPoint기본값대기 위치
current_index_int0현재 순찰 위치 번호
completed_cycles_int0완료한 순찰 횟수
retry_count_int0현재 지점 이동 재시도 횟수
patrol_active_boolfalse순찰 실행 상태
paused_by_anomaly_boolfalse이상 이벤트에 의한 일시정지
paused_by_user_boolfalse사용자 요청에 의한 일시정지
emergency_stop_active_boolfalse비상정지 상태
low_battery_active_boolfalse배터리 부족 상태
current_goal_id_std::string빈 문자열현재 이동 목표 ID
current_state_PatrolStateIDLE현재 상태
operation_mode_std::stringIDLE현재 운용 모드
battery_percentage_double100.0현재 배터리 잔량
last_nav_result_std::string빈 문자열마지막 Nav2 이동 결과
goal_in_progress_boolfalseNav2 목표 수행 여부
waiting_at_point_boolfalse순찰 지점 대기 상태
anomaly_event_id_std::string빈 문자열현재 이상 이벤트 ID
patrol_start_time_rclcpp::Time0순찰 시작 시각
point_arrival_time_rclcpp::Time0순찰 지점 도착 시각
last_status_publish_time_rclcpp::Time0마지막 상태 발행 시각
nav_goal_handle_액션 목표 핸들null현재 Nav2 목표 핸들
wait_timer_ROS 2 Timernull순찰 지점 대기 타이머
status_timer_ROS 2 Timernull상태 주기 발행 타이머
battery_check_timer_ROS 2 Timernull배터리 상태 검사 타이머

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정수00이면 무한 반복
allowed_operation_mode문자열 배열PATROL, NIGHT_PATROL순찰 허용 모드
nav_action_name문자열/navigate_to_poseNav2 액션 서버명
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. 초기화 처리

노드가 시작되면 다음 순서로 초기화한다.

  1. 노드명을 patrol_manager로 설정한다.
  2. ROS 2 파라미터를 선언한다.
  3. 파라미터 값을 읽는다.
  4. 순찰 지점 YAML 파일을 읽는다.
  5. 순찰 지점 데이터를 검증한다.
  6. 대기 위치 데이터를 검증한다.
  7. Nav2 액션 클라이언트를 생성한다.
  8. 서비스 서버를 생성한다.
  9. 입력 토픽 구독자를 생성한다.
  10. 상태 및 이벤트 발행자를 생성한다.
  11. 상태 발행 타이머를 생성한다.
  12. 배터리 검사 타이머를 생성한다.
  13. 내부 변수를 초기화한다.
  14. 현재 상태를 IDLE로 설정한다.
  15. 초기 상태 메시지를 발행한다.

순찰 지점 설정 파일을 읽을 수 없거나 필수 데이터가 누락된 경우 상태를 ERROR로 설정하고 순찰 시작 요청을 거부한다.

14. 순찰 시작 처리 절차

14.1 시작 요청 처리

  1. /patrol_manager/start 서비스 요청을 수신한다.
  2. 현재 상태가 시작 가능한 상태인지 확인한다.
  3. 상태를 VALIDATING으로 변경한다.
  4. 비상정지 상태를 확인한다.
  5. 현재 운용 모드를 확인한다.
  6. 배터리 잔량을 확인한다.
  7. 순찰 지점 목록을 확인한다.
  8. Nav2 액션 서버 연결 상태를 확인한다.
  9. AMCL 위치 추정 상태를 확인한다.
  10. 모든 조건이 정상이면 내부 변수를 초기화한다.
  11. current_index_를 0으로 설정한다.
  12. completed_cycles_를 0으로 설정한다.
  13. retry_count_를 0으로 설정한다.
  14. patrol_active_true로 설정한다.
  15. 순찰 시작 시각을 저장한다.
  16. PATROL_STARTED 이벤트를 발행한다.
  17. 첫 번째 순찰 지점을 Nav2 목표로 전송한다.
  18. 상태를 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 목표 전송

  1. 현재 순찰 지점 데이터를 읽는다.
  2. PoseStamped 메시지를 생성한다.
  3. 좌표계는 순찰 지점의 frame_id를 사용한다.
  4. 기본 좌표계는 map으로 설정한다.
  5. x, y 좌표를 설정한다.
  6. yaw 값을 quaternion으로 변환한다.
  7. 목표 전송 시각을 저장한다.
  8. 목표 상태를 MOVING으로 발행한다.
  9. Nav2 액션 서버에 목표를 전송한다.
  10. 상태를 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이면 다음 작업을 수행한다.

  1. goal_in_progress_false로 설정한다.
  2. retry_count_를 0으로 초기화한다.
  3. 도착 시각을 기록한다.
  4. 현재 지점 상태를 ARRIVED로 발행한다.
  5. GOAL_REACHED 이벤트를 발행한다.
  6. 현재 지점의 대기시간을 확인한다.
  7. 대기시간이 0보다 크면 상태를 WAITING으로 변경한다.
  8. 대기 타이머를 시작한다.
  9. 대기시간이 0이면 즉시 다음 지점으로 전환한다.

16. 순찰 지점 대기 처리

순찰 지점에 도착한 후 다음 절차를 수행한다.

  1. 로봇 이동을 정지 상태로 유지한다.
  2. 현재 지점 상태를 WAITING으로 발행한다.
  3. 지점별 wait_time_sec를 읽는다.
  4. 값이 없으면 default_wait_time_sec를 사용한다.
  5. 대기 타이머를 시작한다.
  6. 대기 중 이상 이벤트와 비상정지 입력을 계속 확인한다.
  7. 대기시간이 완료되면 다음 순찰 지점으로 전환한다.

대기 도중 이상 이벤트가 발생하면 대기 타이머의 남은 시간을 별도로 저장하지 않고, 순찰 재개 시 현재 지점 이동부터 다시 수행하는 것을 기본으로 한다.

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. 순찰 횟수 관리

마지막 순찰 지점의 대기까지 완료하면 다음 작업을 수행한다.

  1. completed_cycles_를 1 증가시킨다.
  2. CYCLE_COMPLETED 이벤트를 발행한다.
  3. 목표 순찰 횟수를 확인한다.

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();
}

목표 반복 횟수에 도달한 경우 다음 작업을 수행한다.

  1. patrol_active_false로 설정한다.
  2. 상태를 COMPLETED로 변경한다.
  3. PATROL_COMPLETED 이벤트를 발행한다.
  4. return_home_on_completetrue이면 대기 위치로 복귀한다.

19. 이동 실패 처리

19.1 이동 실패 조건

다음 Nav2 결과를 이동 실패로 처리한다.

ABORTED
CANCELED
UNKNOWN
목표 수락 거부
이동 제한시간 초과
Nav2 서버 연결 해제

사용자 일시정지, 이상 이벤트 및 비상정지에 의한 목표 취소는 일반 이동 실패 횟수에 포함하지 않는다.

19.2 이동 실패 처리 절차

이동 실패 발생
    ↓
실패 원인 확인
    ↓
사용자 중지 또는 비상정지인가?
    ├─ 예 → 재시도하지 않음
    └─ 아니오
         ↓
      재시도 횟수 증가
         ↓
      최대 재시도 이하인가?
         ├─ 예 → 재시도 대기 후 현재 목표 재전송
         └─ 아니오
              ↓
           실패 로그 저장
              ↓
           continue_on_failure 확인
              ├─ true → 다음 지점 이동
              └─ false → 순찰 종료 및 ERROR 전환

19.3 재시도 처리

이동 실패 시 다음과 같이 재시도 횟수를 증가시킨다.

retry_count_++;

재시도 횟수가 최대 재시도 횟수 이하이면 다음 작업을 수행한다.

  1. 상태를 RETRY_WAIT로 변경한다.
  2. GOAL_RETRY 이벤트를 발행한다.
  3. retry_delay_sec 동안 대기한다.
  4. 동일한 순찰 지점을 다시 Nav2 목표로 전송한다.

판단 조건은 다음과 같다.

if (retry_count_ <= max_retry_count_)
{
  scheduleRetry();
}

19.4 최대 재시도 초과 처리

최대 재시도 횟수를 초과하면 다음 작업을 수행한다.

  1. 현재 지점 상태를 FAILED로 발행한다.
  2. GOAL_FAILED 이벤트를 발행한다.
  3. 실패 원인과 시각을 로그로 저장한다.
  4. retry_count_를 0으로 초기화한다.
  5. continue_on_failure 값을 확인한다.

continue_on_failuretrue이면 현재 지점을 건너뛰고 다음 지점으로 이동한다.

continue_on_failurefalse이면 순찰을 종료하고 상태를 ERROR로 변경한다.

20. 이상 이벤트 처리

20.1 이상 이벤트 발생

severity가 2 이상이고 activetrue이면 다음 작업을 수행한다.

  1. 이상 이벤트 ID를 저장한다.
  2. paused_by_anomaly_true로 설정한다.
  3. 현재 Nav2 목표를 취소한다.
  4. 대기 타이머를 중지한다.
  5. 현재 순찰 지점 번호를 유지한다.
  6. 재시도 횟수를 유지한다.
  7. 상태를 PAUSED_ANOMALY로 변경한다.
  8. ANOMALY_DETECTED 이벤트를 발행한다.
  9. 원격 GUI에 관리자 확인 필요 상태를 표시한다.

20.2 이상 이벤트 해제

동일한 이상 이벤트 ID에 대해 activefalse로 수신되면 다음 작업을 수행한다.

  1. paused_by_anomaly_false로 설정한다.
  2. 이상 이벤트 ID를 초기화한다.
  3. ANOMALY_CLEARED 이벤트를 발행한다.
  4. auto_resume_after_anomaly 값을 확인한다.

auto_resume_after_anomalytrue이면 현재 순찰 지점부터 자동 재개한다.

auto_resume_after_anomalyfalse이면 관리자의 재개 요청을 기다린다.

21. 배터리 부족 처리

21.1 순찰 시작 배터리 기준

배터리 잔량이 start_battery_threshold보다 낮으면 순찰 시작을 허용하지 않는다.

기본값은 다음과 같다.

40.0%

21.2 순찰 중 배터리 부족

순찰 중 배터리 잔량이 low_battery_threshold 이하가 되면 다음 작업을 수행한다.

  1. low_battery_active_true로 설정한다.
  2. 현재 Nav2 목표를 취소한다.
  3. 순찰 지점 대기 타이머를 중지한다.
  4. LOW_BATTERY 이벤트를 발행한다.
  5. 순찰 실행 상태를 해제한다.
  6. 상태를 RETURNING_HOME으로 변경한다.
  7. 대기 위치를 Nav2 목표로 전송한다.

기본값은 다음과 같다.

30.0%

21.3 위험 배터리 처리

배터리 잔량이 critical_battery_threshold 이하가 되면 다음 작업을 수행한다.

  1. 현재 Nav2 목표를 즉시 취소한다.
  2. 로봇 정지 명령을 발행한다.
  3. 자동 복귀를 시도하지 않는다.
  4. 상태를 ERROR로 변경한다.
  5. 원격 GUI에 긴급 충전 요청을 표시한다.

기본값은 다음과 같다.

15.0%

배터리가 위험 수준인 경우 대기 위치까지 이동하는 것보다 현재 위치에서 정지하는 것을 우선한다.

22. 대기 위치 복귀 처리

22.1 복귀 발생 조건

다음 조건에서 대기 위치 복귀를 수행한다.

  • 배터리 부족
  • 순찰 완료
  • 관리자 복귀 명령
  • 설정에 따른 순찰 중지 후 복귀

22.2 복귀 처리 절차

  1. 현재 Nav2 목표를 취소한다.
  2. 순찰 실행 상태를 해제한다.
  3. 상태를 RETURNING_HOME으로 변경한다.
  4. /return_home/requesttrue를 발행한다.
  5. 설정 파일의 home_point를 읽는다.
  6. 대기 위치를 Nav2 목표로 전송한다.
  7. 대기 위치 도착 여부를 확인한다.
  8. 도착하면 상태를 STOPPED 또는 COMPLETED로 변경한다.
  9. 복귀 완료 이벤트를 발행한다.

대기 위치 복귀가 실패하면 설정된 max_retry_count만큼 재시도한다.

복귀 재시도까지 실패하면 상태를 ERROR로 변경하고 원격 GUI에 수동 이동 요청을 표시한다.

23. 비상정지 처리

23.1 비상정지 우선순위

비상정지는 모든 명령과 상태보다 우선한다.

이벤트 처리 우선순위는 다음과 같다.

비상정지
배터리 위험
배터리 부족
이상 이벤트
사용자 중지
사용자 일시정지
Nav2 이동 결과
순찰 지점 대기 완료

23.2 비상정지 절차

  1. /emergency_stop에서 true를 수신한다.
  2. emergency_stop_active_true로 설정한다.
  3. 현재 Nav2 목표를 취소한다.
  4. 모든 내부 타이머를 중지한다.
  5. patrol_active_false로 설정한다.
  6. 상태를 EMERGENCY_STOP으로 변경한다.
  7. /cmd_vel에 0 속도 명령을 반복 발행한다.
  8. EMERGENCY_STOPPED 이벤트를 발행한다.
  9. 순찰 시작 및 재개 요청을 거부한다.

정지 명령은 다음과 같다.

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를 수신해도 자동으로 순찰을 재개하지 않는다.

비상정지 해제 후 다음 절차를 수행한다.

  1. emergency_stop_active_false로 설정한다.
  2. 상태를 STOPPED로 변경한다.
  3. 관리자가 로봇 상태를 확인한다.
  4. 관리자가 순찰 시작 요청을 다시 전송한다.
  5. 첫 번째 순찰 지점부터 새 순찰을 시작한다.

24. 사용자 중지 처리

순찰 중지 요청이 발생하면 다음 작업을 수행한다.

  1. 현재 Nav2 목표를 취소한다.
  2. 대기 타이머를 중지한다.
  3. patrol_active_false로 설정한다.
  4. paused_by_user_false로 설정한다.
  5. paused_by_anomaly_false로 설정한다.
  6. retry_count_를 0으로 초기화한다.
  7. 상태를 STOPPED로 변경한다.
  8. PATROL_STOPPED 이벤트를 발행한다.

return_home_on_stoptrue이면 대기 위치 복귀 절차를 수행한다.

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_stoptrue 발행
비상정지 해제/emergency_stopfalse 발행

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는 로봇 내부에서 계속 실행된다.

통신 단절 시 처리 기준은 다음과 같다.

  1. GUI 상태 갱신이 중단된다.
  2. 현재 순찰은 로봇 내부에서 계속 수행한다.
  3. 비상정지와 배터리 부족 처리는 계속 수행한다.
  4. 네트워크가 복구되면 최신 상태를 GUI에 다시 전송한다.
  5. 상태 토픽은 transient_local QoS를 사용하여 늦게 연결된 GUI가 최신 상태를 수신하도록 한다.

26. QoS 설계

인터페이스ReliabilityDurabilityHistory
/patrol_manager/statusReliableTransient LocalKeep Last 1
/patrol_manager/current_pointReliableTransient LocalKeep Last 1
/patrol_manager/eventReliableVolatileKeep Last 50
/patrol_manager/logReliableVolatileKeep Last 100
/battery_stateReliableVolatileKeep Last 10
/anomaly_eventReliableVolatileKeep Last 20
/emergency_stopReliableTransient LocalKeep Last 1
/operation_modeReliableTransient LocalKeep Last 1
/cmd_velReliableVolatileKeep Last 10

27. 콜백 및 실행 구조

27.1 콜백 그룹

상태 변경 충돌을 방지하기 위해 콜백 그룹을 구분한다.

콜백 그룹유형포함 기능
state_callback_group_Mutually Exclusive시작, 중지, 일시정지, 재개
nav_callback_group_ReentrantNav2 목표 응답, 피드백, 결과
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=11회 후 완료
3회 순찰patrol_repeat_count=33회 후 완료
무한 순찰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 정상 순찰 시나리오

  1. 터틀봇3 Bringup을 실행한다.
  2. Nav2와 AMCL을 실행한다.
  3. 초기 위치를 설정한다.
  4. 운용 모드를 PATROL로 설정한다.
  5. GUI에서 순찰 시작 버튼을 누른다.
  6. 첫 번째 순찰 지점으로 이동하는지 확인한다.
  7. 지점 도착 후 설정된 시간 동안 대기하는지 확인한다.
  8. 다음 지점으로 이동하는지 확인한다.
  9. 마지막 지점 완료 후 순찰 횟수가 증가하는지 확인한다.
  10. 설정된 반복 횟수 완료 후 대기 위치로 복귀하는지 확인한다.

36.2 이동 실패 시나리오

  1. 순찰을 시작한다.
  2. 현재 목표 앞에 장애물을 배치한다.
  3. Nav2가 복구 동작을 수행하는지 확인한다.
  4. 이동 실패 결과가 발생하는지 확인한다.
  5. 동일 지점을 재시도하는지 확인한다.
  6. 최대 재시도 초과 후 다음 지점으로 이동하는지 확인한다.
  7. 실패 이벤트가 GUI에 표시되는지 확인한다.

36.3 이상 이벤트 시나리오

  1. 순찰 중 이상 이벤트를 발생시킨다.
  2. 현재 Nav2 목표가 취소되는지 확인한다.
  3. 상태가 PAUSED_ANOMALY로 변경되는지 확인한다.
  4. GUI에 이상 이벤트가 표시되는지 확인한다.
  5. 이상 이벤트를 해제한다.
  6. 관리자 재개 요청을 전송한다.
  7. 중단된 순찰 지점부터 다시 이동하는지 확인한다.

36.4 배터리 부족 시나리오

  1. 순찰을 시작한다.
  2. 배터리 잔량을 복귀 기준 이하로 입력한다.
  3. 현재 순찰 목표가 취소되는지 확인한다.
  4. 상태가 RETURNING_HOME으로 변경되는지 확인한다.
  5. 대기 위치가 Nav2 목표로 전송되는지 확인한다.
  6. 대기 위치 도착 후 순찰이 종료되는지 확인한다.

36.5 비상정지 시나리오

  1. 터틀봇3가 순찰 지점으로 이동하도록 한다.
  2. GUI에서 비상정지 버튼을 누른다.
  3. Nav2 목표가 즉시 취소되는지 확인한다.
  4. 로봇이 정지하는지 확인한다.
  5. 상태가 EMERGENCY_STOP으로 변경되는지 확인한다.
  6. 비상정지를 해제한다.
  7. 자동으로 이동하지 않는지 확인한다.
  8. 새 순찰 시작 요청 후 첫 지점부터 이동하는지 확인한다.

37. 완료 기준

patrol_manager는 다음 조건을 모두 만족하면 개발 완료로 판단한다.

  1. YAML 파일에서 순찰 지점을 정상적으로 불러온다.
  2. 원격 PC GUI에서 순찰 시작과 중지가 가능하다.
  3. 첫 번째 지점부터 마지막 지점까지 순서대로 이동한다.
  4. 각 지점에서 설정된 시간 동안 대기한다.
  5. 마지막 지점 완료 후 순찰 횟수가 증가한다.
  6. 지정된 횟수만큼 순찰을 반복한다.
  7. 이동 실패 시 설정된 횟수만큼 재시도한다.
  8. 최대 재시도 초과 시 설정에 따라 다음 지점으로 이동하거나 순찰을 종료한다.
  9. 이상 이벤트 발생 시 현재 이동을 중지하고 순찰을 일시정지한다.
  10. 이상 이벤트 해제 후 관리자 요청으로 순찰을 재개한다.
  11. 배터리 부족 시 현재 순찰을 종료하고 대기 위치로 복귀한다.
  12. 위험 배터리 상태에서는 현재 위치에서 즉시 정지한다.
  13. 비상정지 발생 시 모든 순찰 동작을 즉시 중지한다.
  14. 비상정지 해제 후 자동으로 순찰을 재개하지 않는다.
  15. 원격 PC GUI에서 현재 상태, 현재 지점, 배터리 및 오류를 확인할 수 있다.
  16. 네트워크 재연결 후 GUI가 최신 순찰 상태를 다시 수신한다.
  17. 모든 단위시험과 통합시험을 통과한다.

Leave a Comment