나무 모양보다 상태가 전파되는 규칙을 읽는다
Behavior Tree는 조건과 행동의 실행 순서·분기를 구성하는 방법이다. leaf는 실제 조건 확인이나 행동 요청을 맡는 끝 노드이며, 제어 노드는 여러 자식의 결과를 조합한다. tick은 트리가 현재 상태를 확인하고 다음 처리를 진행하도록 호출하는 한 번의 실행 요청이다. 일반적인 실행 결과 SUCCESS, FAILURE, RUNNING은 각각 해당 노드의 조건 통과·실패·진행 중을 나타낸다. 시작 전 IDLE이나 버전·노드별 다른 상태도 있으므로 세 단어가 모든 상태의 목록이라는 뜻은 아니다.
Sequence는 순서대로 자식을 확인해 성공한 다음 자식으로 진행하고, 진행 중이면 전체도 RUNNING, 실패하면 전체도 FAILURE를 반환하는 구조다. 모두 성공하면 SUCCESS다. Fallback은 실패한 후보 다음의 대안을 확인하며 성공 또는 진행 중인 후보를 만나면 그 결과를 반환한다. 모두 실패하면 FAILURE다. 이것은 프로그램의 단순 if문과 비슷한 역할도 하지만 오래 걸리는 행동의 상태를 여러 tick에 걸쳐 관리한다는 차이가 있다.
이 개념 설명은 BehaviorTree.CPP 4.5.2 Sequence와 Fallback 공개 구현을 대조했다. 해당 버전을 현재 Jazzy 환경에 설치하거나 실행한 것은 아니다. 동기 Sequence, ReactiveSequence 등은 자식을 다시 확인하는 규칙이 다르므로 이름을 생략하고 모든 트리가 똑같이 전제를 감시한다고 말하지 않는다.
앞서 통과한 조건이 계속 감시되는지는 별도 계약이다
교육용 Sequence를 Ready→Navigate→VerifyTask로 정하자. Ready는 센서·TF·과업의 준비 조건, Navigate는 주행 Action을 요청하는 leaf, VerifyTask는 작업 결과를 확인하는 leaf다. 이름은 설명용이며 그대로 로딩되는 Nav2 plugin 목록이 아니다. 이 예의 Sequence는 Navigate가 RUNNING이면 다음 tick에도 그 자식부터 이어 간다. 먼저 통과한 Ready를 매번 다시 확인하는 구조는 아니다.
그림 M18.04-1. 각 칸은 서로 다른 역할/근거다. 나란히 비교할 항목이며 위아래가 시간 순서를 뜻하지 않는다. 직접 제작한 개념도이며 본문의 조건과 함께 읽는다.
Navigate가 진행 중인 동안 센서가 끊겨도 이 순서만으로 Ready의 실패가 다시 평가된다고 볼 수 없다. 필요한 지속 감시는 별도 감시 계층이나 적절한 reactive 제어 노드와 취소·halt 처리로 구성해야 한다. halt는 트리 노드의 실행 중단 요청이지 곧바로 모터가 정지했다는 관측은 아니다. 실행 중인 Action의 취소와 실제 적용 상태를 연결해야 한다.
blackboard는 목표·경로·오류 같은 데이터를 트리 노드들이 공유하는 저장 공간이다. 값이 있다는 사실만으로 최신이거나 현재 목표의 결과인 것은 아니다. 목표 ID와 버전, frame·시각 및 자료 출처를 함께 관리한다. 지난 목표의 SUCCESS나 이미 바뀐 경로를 새 과업의 결과로 재사용하지 않는다. Jazzy BT Navigator의 트리 선택과 과업 인터페이스도 이런 실행 맥락 안에서 해석한다.
BT 결과와 Action 상태를 명시적으로 연결한다
ROS 2 Action 설계는 목표 수락, 실행, 취소 중과 최종 성공·중단·취소를 구분한다. goal ID는 어느 요청의 사건인지 구별하는 식별자다. 피드백은 진행 정보이며 최종 결과가 아니다. 현재 목표까지 거리가 작다는 피드백을 받았다고 terminal SUCCEEDED를 받은 것으로 채우지 않는다. 서버가 광고됐다는 사실도 현재 goal을 수락했다는 뜻이 아니다.
본문의 교육용 Navigate adapter 정책은 ACCEPTED/EXECUTING/CANCELING에서 RUNNING을 반환하고, 같은 goal ID의 terminal SUCCEEDED는 SUCCESS, ABORTED 또는 CANCELED는 FAILURE로 반환한다고 정한다. 이는 모든 Nav2 leaf의 내부 구현이 반드시 같다는 주장이 아니다. 또한 상위 mission 기록에는 취소와 오류를 별도로 남긴다. BT의 FAILURE 하나로 사용자의 중단 의도와 시스템 결함이 같아지는 것은 아니다.
합성 goal g7의 사건을 보자. tick 0에서 Ready가 SUCCESS이고 Navigate가 요청을 보내 수락 뒤 EXECUTING이다. Sequence는 RUNNING이고 VerifyTask는 아직 호출하지 않는다. tick 1에서 distance_to_goal=0.1 m 피드백이 왔지만 최종 결과는 없으므로 그대로 RUNNING이다. 이 leaf는 피드백 숫자만으로 도착을 새로 판정하지 않는다는 정책이다.
tick 2에서 취소 요청이 수락되어 CANCELING이 됐다. 아직 최종 취소 완료가 아니므로 leaf와 Sequence는 RUNNING이다. tick 3에서 같은 g7의 terminal CANCELED가 도착하면 leaf와 Sequence는 FAILURE이고 VerifyTask는 호출하지 않는다. mission 기록은 CANCELED로 남긴다. 별도 cancel_latch를 유지해 상위 재시도 분기가 같은 목표를 다시 요청하지 못하도록 한다. 이 latch는 본문이 정한 과업 정책이며 ROS가 모든 BT에 자동 제공하는 기능이라고 쓰지 않는다.
취소 결과가 네트워크 문제로 아직 없으면 취소 요청·수락과 결과 미상을 기록한다. 결과를 임의로 SUCCESS나 CANCELED로 만들지 않는다. 취소가 끝나도 실제 정지·잔여 명령·구동 상태는 필요한 관측으로 확인한다. 새 목표를 시작할 때에는 현재 상태·지도·자료와 목표 버전을 재확인하고 이전 목표의 결과와 섞지 않는다.
Waypoint 도착과 그곳에서의 작업을 구분한다
waypoint는 순서대로 방문할 목표 pose다. Jazzy FollowWaypoints 정의는 PoseStamped 배열, 시작 인덱스와 반복 관련 입력, 현재 waypoint 피드백 및 missed_waypoints 결과를 구분한다. 다른 버전의 필드 모양을 복사하지 않고 사용하는 분기의 실제 정의를 확인한다. 피드백의 현재 인덱스는 그 waypoint의 작업 성공률이 아니다.
Jazzy Waypoint Follower는 위치 도착 뒤 task executor plugin으로 작업을 수행할 수 있다. 사진을 찍거나 물건을 확인하는 과업은 pose 도착과 다른 결과다. plugin이 요청을 보냈는지, 작업 결과를 검증했는지 및 실패·미상을 어떤 방식으로 반환하는지 정해야 한다. 존재하지 않는 관측을 작업 성공으로 만들지 않는다.
한 번 처리하는 목록의 인덱스를 0,1,2로 주자. 0은 navigation 성공과 task 성공, 1은 navigation 성공이나 task 실패, 2는 navigation 실패로 task를 수행하지 않았다. stop_on_failure=false라는 입력에서 다음 waypoint로 계속 진행한 로그다. navigation 성공은 2/3이지만 두 단계가 모두 성공한 waypoint는 0 하나라 1/3이다. 2의 task 미수행을 별도의 task 성공으로 세거나 분모에서 지우지 않는다.
Jazzy 실제 처리 코드는 실패를 missed_waypoints에 담고, 계속 처리하는 설정에서는 목록을 끝냈을 때 성공 terminal을 반환할 수 있다. 따라서 바깥 Action의 SUCCEEDED만으로 모든 waypoint 작업이 성공했다고 읽으면 안 된다. 해당 결과의 missed 목록과 오류·작업 기록을 함께 해석한다. 본문 입력의 missed 인덱스는 1과 2이며 전체 필수 작업 완료는 아니다.
재시도와 중단을 과업의 의미에 맞춘다
모든 FAILURE를 Fallback의 '다시 Navigate'로 연결하면 취소된 명령까지 재실행할 수 있다. 사용자의 중단, TF 오류, 도착 실패와 사진 저장 실패는 같은 대안이 아니다. 실패 종류·재시도 횟수·현재 준비 조건·작업 ID를 확인해 분기하고 종료 이유와 남은 작업을 기록한다. task executor의 성공도 실제 증거와 연결되어야 한다.
다시 실행하면 중복 효과가 있는 작업은 특히 작업 ID와 이미 완료한 항목을 확인한다. 같은 사진 요청의 재처리와 물체를 한 번 더 놓는 행동은 결과가 다를 수 있다. 과업의 idempotency는 같은 요청을 반복해도 추가 효과가 생기지 않는 성질이며 모든 물리 동작이 이를 갖는다고 가정하지 않는다. 복구 후에는 어떤 단계부터 재개할지와 새 관측·현재 pose를 명시한다.
기존 1.4 ROS 2 Jazzy 통신 모델과 6.4 안전 배포 감독기를 연결해 통신·감독과 과업 결과를 나누자. 아래 활동은 사건표를 읽는 연습이며 실제 BT와 waypoint 실행·실물 작업의 성공을 증명하지 않는다.