1291.63 장기 실행 행동의 관리 복잡도
행동 트리(Behavior Tree, BT)의 실행 모델에서 개별 노드는 틱(Tick) 신호를 수신할 때마다 Success, Failure, 또는 Running 중 하나의 상태를 반환한다. 단일 틱 내에 완료되지 않는 행동은 Running 상태를 반환하여 후속 틱에서 계속 실행될 것임을 부모 노드에 통지한다. 로봇 시스템에서 경로 추종(Path Following), 물체 파지(Grasping), 지도 작성(Mapping) 등 실세계의 물리적 작업은 다수의 틱에 걸쳐 수행되는 장기 실행 행동(Long-Running Action)에 해당하며, 이러한 행동의 관리는 행동 트리 설계에서 상당한 복잡도를 수반한다.
1. Running 상태의 전파와 트리 순회 제약
행동 트리에서 액션 노드가 Running 상태를 반환하면, 해당 상태는 부모 노드를 거쳐 루트 노드까지 상향 전파된다. 시퀀스(Sequence) 노드의 경우 자식 노드가 Running을 반환하면 자신도 Running을 반환하고, 다음 틱에서는 해당 자식 노드부터 실행을 재개한다. 이 메커니즘은 장기 실행 행동의 연속성을 보장하지만, 동시에 트리의 나머지 분기에 대한 순회를 차단하는 효과를 발생시킨다.
비반응형(Non-Reactive) 시퀀스 노드인 SequenceWithMemory에서 특정 자식 노드가 Running을 반환하면, 해당 노드의 좌측에 이미 성공한 형제 노드들은 재평가되지 않는다. 이는 실행 효율의 관점에서는 유리하지만, Running 상태가 지속되는 동안 환경 조건의 변화에 반응하지 못하는 문제를 야기한다. 반면, 리액티브 시퀀스(ReactiveSequence) 노드는 매 틱마다 첫 번째 자식부터 재평가하므로 반응성을 확보하지만, 장기 실행 행동 이전의 조건 노드가 실패를 반환할 경우 진행 중인 행동이 즉시 중단되는 부작용이 수반된다.
2. 비동기 행동의 생명주기 관리
로봇 시스템에서 장기 실행 행동은 통상적으로 비동기적(Asynchronous)으로 처리된다. ROS2 환경에서 액션 노드는 일반적으로 ROS2 액션 클라이언트(Action Client)를 통해 외부 서비스에 비동기 요청을 전송하고, 후속 틱에서 결과를 폴링(Polling)하는 방식으로 구현된다. BehaviorTree.CPP 라이브러리에서는 StatefulActionNode를 제공하여 onStart(), onRunning(), onHalted() 세 가지 콜백을 통해 장기 실행 행동의 생명주기를 관리한다.
이러한 비동기 행동의 관리에서 다음의 복잡도가 발생한다.
첫째, 행동 취소(Halt)의 정확한 처리이다. 행동 트리의 반응적 특성으로 인해 장기 실행 행동은 완료 이전에 취소될 수 있다. 상위 제어 노드의 판단에 의해 현재 실행 중인 서브트리가 중단될 때, Running 상태에 있는 모든 액션 노드는 halt() 콜백을 수신한다. 이 콜백에서 외부 서비스에 대한 취소 요청 전송, 로봇 하드웨어의 안전한 정지, 블랙보드 상태의 정리 등 적절한 마무리 절차가 수행되어야 한다. 취소 처리의 부적절한 구현은 리소스 누수(Resource Leak), 로봇의 불안정 상태 잔존, 또는 후속 행동의 오동작으로 직결된다.
둘째, 부분 완료 상태의 처리이다. 장기 실행 행동이 중간에 취소된 후 동일 행동이 재실행될 때, 이전 실행에서 달성된 부분적 진전을 어떻게 취급할 것인지의 문제가 발생한다. 예를 들어, 경로 추종 행동이 목표까지의 70% 지점에서 취소된 후 재실행될 경우, 처음부터 다시 시작할 것인지 또는 중단 지점부터 재개할 것인지를 결정해야 한다. 행동 트리의 기본 구조에서는 이러한 부분 완료 상태의 보존과 복원을 위한 내장 메커니즘이 제공되지 않으므로, 블랙보드를 통한 수동 관리가 필요하다.
셋째, 타임아웃 관리이다. 장기 실행 행동이 예상 시간을 초과하여 Running 상태를 반환하는 경우에 대한 처리가 필요하다. 행동 트리 자체에는 시간 기반 제약을 부과하는 내장 메커니즘이 존재하지 않으며, 타임아웃 데코레이터(Timeout Decorator)를 상위에 배치하거나 액션 노드 내부에 타이머 논리를 구현하여 대응해야 한다.
3. 다중 장기 실행 행동의 동시 관리
로봇 시스템의 실제 임무에서는 다수의 장기 실행 행동이 동시에 수행되어야 하는 경우가 빈번하다. 이동 로봇이 경로를 추종하면서 동시에 주변 환경을 감시하고, 특정 조건 발생 시 경고를 발생시키는 시나리오가 이에 해당한다. 행동 트리에서는 병렬(Parallel) 노드를 통해 다수의 자식 노드를 동시에 실행할 수 있으나, 다수의 자식 노드가 각각 Running 상태를 유지하는 경우 다음의 관리 복잡도가 발생한다.
첫째, 동기화 문제이다. 병렬로 실행되는 장기 실행 행동들 간의 진행 상태를 동기화해야 하는 경우, 블랙보드를 통한 간접적 통신에 의존해야 한다. 이는 경쟁 조건(Race Condition)이나 데이터 불일치의 위험을 수반한다.
둘째, 부분 실패 처리이다. 병렬로 실행되는 행동 중 일부가 실패하였을 때, 나머지 실행 중인 행동들에 대한 처리 정책을 결정해야 한다. 병렬 노드의 성공/실패 임계값(Threshold) 설정에 따라 동작이 달라지며, 실패한 행동의 보상(Compensation) 논리를 별도로 구현해야 하는 경우도 존재한다.
4. 테스트 및 디버깅의 어려움
장기 실행 행동의 비결정론적 실행 시간과 비동기적 특성은 행동 트리의 테스트 및 디버깅 과정에서 추가적인 복잡도를 야기한다. 단위 테스트에서 장기 실행 행동을 검증하기 위해서는 다수의 틱에 걸친 상태 변화를 시뮬레이션해야 하며, 취소 시나리오와 타임아웃 시나리오를 체계적으로 재현할 수 있는 테스트 환경이 필요하다.
디버깅 측면에서는 장기 실행 행동이 Running 상태를 유지하는 동안 트리의 다른 분기에서 발생하는 조건 변화와의 상호 작용을 추적해야 하므로, 시간 축을 포함한 트리 실행 이력의 시각화 도구가 필수적이다. BehaviorTree.CPP에서 제공하는 Groot 시각화 도구는 이러한 실행 이력을 검사할 수 있는 기능을 제공하나, 대규모 트리에서 다수의 장기 실행 행동이 상호 작용하는 복잡한 시나리오의 분석에는 여전히 상당한 노력이 요구된다.
참고 문헌
- Colledanchise, M., & Ögren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
- Faconti, D., & Aurys, M. (2022). BehaviorTree.CPP Documentation. https://www.behaviortree.dev/
- Iovino, M., Scukins, E., Styrud, H., Ögren, P., & Smith, C. (2022). “A Survey of Behavior Trees in Robotics and AI.” Robotics and Autonomous Systems, 154, 104096.
- Macenski, S., Martín, F., White, R., & Clavero, J. G. (2020). “The Marathon 2: A Navigation System.” Proceedings of the IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS).