1295.52 ReactiveSequence 노드의 심화 분석
1. ReactiveSequence의 본질
ReactiveSequence는 행동 트리(Behavior Tree)의 제어 노드 중 하나로, 일반 Sequence 노드에 매 Tick 재평가(re-evaluation) 메커니즘을 추가한 반응형 제어 노드이다. 일반 Sequence가 이전 Tick에서 SUCCESS를 반환한 자식을 건너뛰고 진행 중인 자식부터 Tick을 전파하는 반면, ReactiveSequence는 매 Tick마다 첫 번째 자식부터 순차적으로 재평가한다. 이 재평가 메커니즘은 행동의 실행 도중에도 전제 조건(precondition)의 유효성을 지속적으로 검증하는 구조적 기반을 제공한다.
2. 일반 Sequence와의 근본적 차이
일반 Sequence 노드는 메모리(memory)를 가진다. 즉, 이전 Tick에서 자식 C_i가 SUCCESS를 반환하였으면, 다음 Tick에서는 C_i를 건너뛰고 C_{i+1}부터 Tick을 전파한다. 이 메모리 메커니즘은 이미 성공한 자식을 반복 실행하지 않음으로써 효율성을 확보한다.
ReactiveSequence는 이 메모리를 제거한다. 매 Tick에서 항상 첫 번째 자식 C_1부터 평가를 시작한다. 따라서 이전 Tick에서 C_1이 SUCCESS를 반환하였더라도, 다음 Tick에서 C_1이 다시 평가되며 이번에 FAILURE를 반환할 수 있다. 이 경우 C_1 이후의 모든 자식, 특히 RUNNING 상태였던 행동 노드에 Halt가 전파된다.
| 특성 | Sequence | ReactiveSequence |
|---|---|---|
| 재평가 시작점 | 마지막 RUNNING 자식 | 항상 첫 번째 자식 |
| 메모리 | 있음 | 없음 |
| 조건 재검사 | 없음 (통과 후 건너뜀) | 매 Tick 재검사 |
| Halt 발생 조건 | 부모로부터의 Halt | 선행 자식 FAILURE 시 후행 자식 Halt |
3. ReactiveSequence의 의미론적 해석
ReactiveSequence의 자식 배치는 다음의 의미론을 가진다.
ReactiveSequence
├── C₁ (전제 조건 1)
├── C₂ (전제 조건 2)
├── ...
├── Cₙ₋₁ (전제 조건 n-1)
└── Cₙ (주 행동)
C_1부터 C_{n-1}까지는 주 행동 C_n의 실행을 위한 전제 조건을 표현한다. ReactiveSequence는 “C_1이고 C_2이고 … C_{n-1}인 동안 C_n을 수행하라“는 의미를 구조적으로 표현한다. 어느 한 전제 조건이라도 위반되면 주 행동에 즉시 Halt가 전파되어 행동이 중단된다.
이를 논리적으로 표현하면, ReactiveSequence는 다음의 불변 조건(invariant)을 매 Tick에서 강제한다.
\forall t : C_n(t) = \text{RUNNING} \implies \bigwedge_{i=1}^{n-1} C_i(t) = \text{SUCCESS}
즉, 주 행동이 실행 중(RUNNING)인 모든 시점에서, 모든 전제 조건이 SUCCESS를 반환하여야 한다. 이 불변 조건이 위반되는 순간 주 행동은 Halt된다.
자식 노드의 역할 구분
ReactiveSequence에서 자식 노드는 그 위치에 따라 역할이 명확히 구분된다.
조건 자식 (선행 위치)
ReactiveSequence의 앞부분에 배치되는 조건 노드(Condition Node)는 매 Tick에서 재평가된다. 이 조건 노드는 다음의 특성을 충족하여야 한다.
- 즉시 완료:
SUCCESS또는FAILURE만 반환하고RUNNING을 반환하지 않아야 한다. - 무부작용(side-effect free): 블랙보드나 외부 상태를 변경하지 않아야 한다.
- 경량 연산: 매 Tick에서 반복 평가되므로 연산 비용이 낮아야 한다.
조건 자식이 RUNNING을 반환하면 ReactiveSequence는 후속 자식을 평가하지 않으므로, 조건 자식에서의 RUNNING 반환은 사실상 행동의 차단을 의미한다.
행동 자식 (후행 위치)
ReactiveSequence의 마지막에 배치되는 행동 노드(Action Node)는 RUNNING을 반환하며 다수의 Tick에 걸쳐 실행되는 장기 실행 행동(long-running action)이다. 이 행동 노드는 선행 조건이 모두 SUCCESS인 동안에만 실행이 허용되며, 선행 조건 중 하나라도 FAILURE가 되면 Halt를 수신한다.
행동 자식에게 Halt가 호출되면, 해당 행동은 진행 중인 작업을 안전하게 정리(cleanup)하여야 한다. Halt 처리의 안전성은 ReactiveSequence 패턴의 신뢰성에 직결된다.
다중 조건과 다중 행동의 배치
ReactiveSequence에 복수의 조건과 복수의 행동을 배치하는 것이 가능하다.
다중 조건
ReactiveSequence
├── IsRobotOperational // 조건 1
├── IsPathClear // 조건 2
├── IsBatteryAboveThreshold // 조건 3
└── NavigateToGoal // 주 행동
조건은 순차적으로 평가되며, 앞선 조건이 FAILURE를 반환하면 이후 조건은 평가되지 않는다(단축 평가, short-circuit evaluation). 따라서 가장 빈번하게 위반되는 조건이나 가장 빠르게 평가되는 조건을 앞에 배치하면 평가 효율이 향상된다.
다중 행동의 주의점
ReactiveSequence
├── IsConditionMet // 조건
├── Action_A // 행동 1
└── Action_B // 행동 2
이 구조에서 Action_A가 RUNNING을 반환하면 Action_B는 Tick을 수신하지 않는다. Action_A가 SUCCESS를 반환하면 Action_B가 Tick을 수신하지만, 다음 Tick에서 Action_A가 다시 평가된다. Action_A가 상태를 가지지 않는(stateless) 행동이면 다시 SUCCESS를 반환하여 Action_B가 계속 실행될 수 있다. 그러나 Action_A가 상태를 가지는(stateful) 행동이면 재평가 시 예기치 않은 동작을 유발할 수 있다. 따라서 ReactiveSequence에서 복수의 RUNNING 가능 행동을 순차 배치하는 것은 일반적으로 권장되지 않는다.
Tick 흐름의 상세 추적
다음의 ReactiveSequence를 기준으로 Tick 흐름을 추적한다.
ReactiveSequence
├── IsSafe // 조건 노드
├── HasGoal // 조건 노드
└── MoveToGoal // 행동 노드
정상 실행 흐름
Tick 1: IsSafe → SUCCESS, HasGoal → SUCCESS, MoveToGoal → RUNNING
ReactiveSequence → RUNNING
Tick 2: IsSafe → SUCCESS, HasGoal → SUCCESS, MoveToGoal → RUNNING
ReactiveSequence → RUNNING
Tick 3: IsSafe → SUCCESS, HasGoal → SUCCESS, MoveToGoal → SUCCESS
ReactiveSequence → SUCCESS
매 Tick에서 IsSafe와 HasGoal이 재평가되고, 두 조건이 모두 SUCCESS이므로 MoveToGoal이 계속 Tick을 수신한다.
조건 위반 시 흐름
Tick 1: IsSafe → SUCCESS, HasGoal → SUCCESS, MoveToGoal → RUNNING
ReactiveSequence → RUNNING
Tick 2: IsSafe → FAILURE
→ MoveToGoal.halt() 호출 (RUNNING 상태였으므로)
ReactiveSequence → FAILURE
Tick 2에서 IsSafe가 FAILURE를 반환하면, HasGoal과 MoveToGoal은 평가되지 않는다. 이전 Tick에서 RUNNING이었던 MoveToGoal에 Halt가 전파된다. ReactiveSequence는 FAILURE를 반환한다.
조건 복원 시 흐름
Tick 3: IsSafe → SUCCESS, HasGoal → SUCCESS, MoveToGoal → RUNNING
ReactiveSequence → RUNNING
Tick 3에서 IsSafe가 다시 SUCCESS를 반환하면, MoveToGoal은 새로 시작된다. 이전의 진행 상태는 Halt에 의해 정리되었으므로, MoveToGoal은 처음부터 실행을 재개한다. 이전 진행 상태를 복원하려면, 행동 노드가 블랙보드에 진행 상태를 저장하고 재시작 시 이를 읽어들이는 별도의 메커니즘을 구현하여야 한다.
ReactiveFallback과의 구조적 대칭
ReactiveSequence와 ReactiveFallback은 구조적으로 대칭적인 관계에 있다.
| 특성 | ReactiveSequence | ReactiveFallback |
|---|---|---|
| 기반 노드 | Sequence | Fallback |
| 재평가 | 매 Tick 첫 자식부터 | 매 Tick 첫 자식부터 |
| 성공 조건 | 모든 자식 SUCCESS | 하나의 자식 SUCCESS |
| 실패 조건 | 하나의 자식 FAILURE | 모든 자식 FAILURE |
| 의미론 | “조건이 유지되는 동안 행동” | “우선순위에 따른 행동 선택” |
| Halt 발생 | 선행 조건 FAILURE 시 | 상위 자식 SUCCESS 시 |
ReactiveSequence는 AND 의미론(모든 조건 충족)을, ReactiveFallback은 OR 의미론(하나의 조건 충족)을 표현한다. 두 노드 모두 매 Tick 재평가라는 공통 메커니즘을 통해 환경 변화에 대한 즉각적 반응성을 확보한다.
ReactiveSequence의 반응 지연 분석
ReactiveSequence의 조건 위반에 대한 반응 지연은 Tick 주기에 의해 결정된다. 조건이 위반되더라도 다음 Tick이 도달하기 전까지는 이를 감지할 수 없으므로, 최대 반응 지연은 하나의 Tick 주기에 해당한다.
\Delta t_{response} \leq T_{tick}
Tick 주기 T_{tick}이 10ms이면, 조건 위반 후 최대 10ms 이내에 행동이 Halt된다. 안전 요구 사항이 이 지연을 허용하지 않는 경우, Tick 주기를 단축하거나 하드웨어 수준의 안전 메커니즘을 병행하여야 한다.
4. 행동 트리 이론에서의 위치
ReactiveSequence는 Colledanchise와 Ögren이 제시한 반응형 행동 트리(Reactive Behavior Tree)의 핵심 구성 요소이다. 고전적 행동 트리에서는 Sequence와 Fallback만이 제어 노드로 사용되었으나, 반응형 변형이 도입됨으로써 환경 변화에 대한 즉각적 적응이 가능해졌다. ReactiveSequence는 특히 전제 조건의 지속적 보장(continuous guarantee of preconditions)이라는 개념을 행동 트리에 구조적으로 내재시킨 것으로, 로봇의 안전성과 적응성을 동시에 확보하는 이론적 기반이 된다.
Michele Colledanchise와 Petter Ögren의 저서 Behavior Trees in Robotics and AI: An Introduction(CRC Press, 2018)에서 ReactiveSequence의 형식적 정의와 특성이 상세히 논의되어 있다.