Retry의 재시도 카운터 관리 (Retry’s Retry Counter Management)
1. 개요
Retry 데코레이터의 재시도 카운터 관리는 자식 노드의 실패 횟수를 추적하고, 최대 재시도 횟수에 도달하였는지를 판정하는 내부 상태 관리 메커니즘이다. 카운터의 증가, 리셋, halt 시 초기화 등의 생명주기를 정확히 관리하는 것이 Retry 데코레이터의 올바른 동작을 보장하는 핵심 요소이다.
2. 카운터의 생명주기
2.1 초기 상태
Retry 데코레이터가 최초로 tick되는 시점에서 카운터는 0으로 시작한다.
k_0 = 0
증가 조건
자식이 FAILURE를 반환할 때마다 카운터가 1 증가한다.
k_{t+1} = k_t + 1 \quad \text{if } s_{\text{child}}(t) = \text{FAILURE}
자식이 SUCCESS나 RUNNING을 반환하는 경우에는 카운터가 변하지 않는다.
2.2 리셋 시점
| 시점 | 조건 | 리셋 후 상태 |
|---|---|---|
| 자식 SUCCESS | 재시도 성공 | k \leftarrow 0, Retry=SUCCESS |
| 카운터 = N | 재시도 소진 | k \leftarrow 0, Retry=FAILURE |
| halt() 호출 | 외부 중단 | k \leftarrow 0, 상태=IDLE |
2.3 카운터와 Retry 반환 상태의 관계
| 카운터 k | 자식 반환 | Retry 반환 | 카운터 변화 |
|---|---|---|---|
| k < N | FAILURE | RUNNING | k \leftarrow k + 1 |
| k \geq N | FAILURE | FAILURE | k \leftarrow 0 |
| 임의 | SUCCESS | SUCCESS | k \leftarrow 0 |
| 임의 | RUNNING | RUNNING | 변화 없음 |
3. halt() 시의 카운터 초기화
Retry가 외부에서 halt될 때(예: ReactiveSequence의 조건 실패), 카운터를 반드시 0으로 리셋하여야 한다.
void halt() override
{
try_count_ = 0; // 필수
DecoratorNode::halt();
}
3.1 halt 미초기화에 의한 오류
[시행 1] k=0→1→2 (3회 중 2회 실패 후 halt)
[시행 2] k=2→3 (1회만 시도 후 FAILURE → 잘못된 동작!)
halt 시 카운터를 초기화하지 않으면, 다음 시행에서 이전의 카운터 값이 잔존하여 재시도 횟수가 부족해진다.
4. 동작 흐름 예시 (num_attempts=3)
4.1 회차에서 성공
Tick 1: Child → FAILURE, k=1 → Retry=RUNNING
Tick 2: Child → FAILURE, k=2 → Retry=RUNNING
Tick 3: Child → SUCCESS, k 리셋 → Retry=SUCCESS
4.2 회 모두 실패
Tick 1: Child → FAILURE, k=1 → Retry=RUNNING
Tick 2: Child → FAILURE, k=2 → Retry=RUNNING
Tick 3: Child → FAILURE, k=3 → Retry=FAILURE
4.3 비동기 자식의 경우
Tick 1: Child → RUNNING → Retry=RUNNING (k=0)
Tick 2: Child → RUNNING → Retry=RUNNING (k=0)
Tick 3: Child → FAILURE, k=1 → Retry=RUNNING
Tick 4: Child → RUNNING → Retry=RUNNING (k=1)
Tick 5: Child → SUCCESS, k 리셋 → Retry=SUCCESS
자식이 RUNNING 동안에는 카운터가 변하지 않는다.
5. 카운터 값의 외부 노출
디버깅 목적으로 현재 재시도 카운터를 블랙보드에 기록할 수 있다.
BT::NodeStatus tick() override
{
// ... 재시도 로직
setOutput("current_attempt", try_count_);
// ...
}
6. Repeat 카운터와의 비교
| 특성 | Repeat 카운터 | Retry 카운터 |
|---|---|---|
| 증가 트리거 | 자식 SUCCESS | 자식 FAILURE |
| 성공 시 | 카운터 증가 | 카운터 리셋 |
| 실패 시 | 카운터 리셋 (반복 중단) | 카운터 증가 |
| 완료 조건 | k = N (SUCCESS) | k = N (FAILURE) |
7. 설계 시 고려 사항
7.1 카운터의 원자성
단일 스레드 tick 환경에서 카운터 갱신은 자연스럽게 원자적이다. 다중 스레드 환경에서는 카운터에 대한 동기화가 필요하나, BehaviorTree.CPP의 tick은 단일 스레드에서 실행되므로 동기화 문제는 발생하지 않는다.
7.2 지속적 상태 정보 제공
Retry의 현재 시도 횟수를 로깅하거나 UI에 표시하면, 운용자가 재시도 진행 상황을 실시간으로 파악할 수 있다.
8. 참고 문헌
- Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
- BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/
| 버전 | 날짜 | 변경 사항 |
|---|---|---|
| v0.1 | 2026-04-04 | 초안 작성 |