카테고리 없음

Py Tree - Composite

code911 2025. 3. 18. 19:58

Composites

Composites는 behavior tree에서 여러 자식 노드를 가질 수 있는 타입입니다. 이들은 트리가 실행(tick)될 때 경로를 지정하는 역할을 합니다. Composites는 behavior tree의 공장(Sequences와 Parallels)과 의사결정자(Selectors)라고 볼 수 있습니다.

PyTree Composites

복합 행동들은 일반적으로 자식 노드들을 관리하고 실행 방식과 결과 반환에 특정 로직을 적용합니다. 하지만 그들 자체는 실제로 작업을 수행하지 않습니다. 필요한 검사나 작업은 비복합체 행동들에서 수행해야 합니다.

대부분의 원하는 기능은 세 가지 복합체(Selector, Sequence, Parallel)의 조합으로 구현할 수 있습니다. 사실, 이것이 바로 behavior tree가 매력적인 이유입니다 - 복잡한 의사결정 로직을 단 세 가지 기본 요소로 분해하기 때문입니다. 자신만의 커스텀 복합체를 만들 수도 있지만, 그렇게 하기 전에 신중하게 생각해야 합니다. 대부분의 경우, 기존 복합체의 조합으로 충분하며, 새로운 복합체를 추가하면 트리 로직의 복잡성만 증가시키게 됩니다. 이로 인해 설계, 검토 및 디버깅이 어려워집니다.

예를 들어, 설계 세션은 종종 화이트보드에 스케치된 그래프를 중심으로 진행됩니다. 이러한 그래프가 단 다섯 가지 요소(Selectors, Sequences, Parallels, Decorators 및 Behaviours)로 구성되면 로직을 한눈에 이해하기 쉽습니다. 기본 요소의 수를 두 배로 늘리면 코드를 분석하는 것과 다를 바 없게 됩니다.

새로운 복합체를 서브클래싱하거나 만들 필요가 없습니다.

이 라이브러리에 있는 세 가지 복합체의 기본 작동 모드는 다음과 같습니다:

  • Selector: 계단식 우선순위에 따라 자식 노드를 실행합니다
  • Sequence: 자식 노드를 순차적으로 실행합니다
  • Parallel: 자식 노드를 동시에 실행합니다

이 라이브러리는 각 복합체의 기본적인 특성을 깨뜨리지 않고 어떻게 구현되는지에 대한 유연성을 제공합니다. Selector와 Sequence는 메모리 유무(자식이 RUNNING 상태일 때 재개 또는 재설정)로 구성될 수 있으며, Parallel의 결과는 모든 자식이 완료될 때까지 기다리거나, 하나, 전체 또는 일부가 성공할 때 구성될 수 있습니다.

각 복합체의 문서에 있는 관련 데모 프로그램 링크를 따라가보세요.

###############

 

Selector (선택자)

Selector는 의사결정자 역할을 합니다.

복사
selector → 높은 우선순위 → 중간 우선순위 → 낮은 우선순위

Selector는 자식 행동들을 순서대로 실행하며, 하나가 성공(SUCCESS)할 때까지 진행합니다. 자식 중 하나가 성공하면 Selector는 RUNNING 또는 SUCCESS를 반환하고, 모든 자식이 실패하면 FAILURE를 반환합니다. 보통 선택자는 우선순위를 선택하는 수단으로 사용됩니다. 각 자식과 그 하위 트리는 점점 낮아지는 우선순위 경로를 나타냅니다.

주의사항:

  • 낮은 우선순위에서 높은 우선순위 분기로 전환할 때, 이전에 실행 중이던 낮은 우선순위 분기에 stop(INVALID) 신호가 전송됩니다. 이 신호는 해당 자식의 하위 트리로 전파됩니다. 행동들은 이를 적절히 처리하고 정리해야 합니다.
  • 메모리로 구성된 경우, 이전 틱에서 자식이 RUNNING을 반환했다면 높은 우선순위 검사를 건너뜁니다. 즉, 우선순위가 한 번 잠기면 완료될 때까지 실행되며, 트리의 다른 위치에서 더 높은 우선순위에 의해 중단되는 경우에만 중단될 수 있습니다.

매개변수:

  • memory (bool): 이전 틱에서 RUNNING 상태였다면, RUNNING 자식으로 재개할지 여부
  • name (str): 복합체 행동 이름
  • children ([Behaviour]): 추가할 자식 목록

Sequence

Sequence는 behavior tree의 생산라인과 같습니다.

복사
시퀀스 → 가드 → 액션1 → 액션2 → 액션3

Sequence는 각 자식이 SUCCESS를 반환하는 한 순차적으로 각 자식을 틱합니다. 어떤 자식이 FAILURE나 RUNNING을 반환하면 시퀀스는 중단되고 부모는 이 자식의 결과를 채택합니다. 마지막 자식에 도달하면 해당 결과를 반환합니다.

주의사항:

  • 시퀀스는 RUNNING 상태인 자식을 만나면 멈추며, 남은 행동들은 틱되지 않습니다.
  • 메모리로 구성되고 이전 틱에서 자식이 RUNNING을 반환했다면, 이전의 모든 행동을 건너뛰고 직접 실행 중인 행동으로 진행합니다. 메모리가 있는 구성은 오래 실행되는 일련의 작업을 진행할 때 유용합니다. 메모리가 없는 구성은 항상 확인하고 싶은 조건부 가드를 작업 앞에 배치할 때 유용합니다.

매개변수:

  • name (str): 복합체 행동 이름
  • memory (bool): 이전 틱에서 RUNNING 상태였다면, RUNNING 자식으로 재개할지 여부
  • children (Optional[Sequence[Behaviour]]): 추가할 자식 목록

Parallel

Parallel은 일종의 개념적인 동시성을 가능하게 합니다.

복사
병렬(SuccessOnSelected(⚡,[B1,B2])) → B1, B2, B3

Parallel은 자신이 틱될 때마다 모든 자식을 틱합니다. 그러나 병렬성은 단지 개념적인 것입니다. 실제로는 자식들이 순차적으로 틱되지만, 트리와 병렬의 관점에서는 모든 자식이 한 번에 틱된 것처럼 보입니다.

이 병렬성은 실제로 여러 스레드나 프로세스를 시작하는 것이 아닙니다. 일부 행동은 백그라운드에서 스레드나 프로세스를 시작하거나 기존 스레드/프로세스에 연결할 수 있습니다. 그러나 행동 자체는 단지 이를 모니터링하며, 항상 단일 스레드 작업에서만 틱합니다.

반환 정책:

  • 어떤 자식이 FAILURE를 반환하면 Parallel은 FAILURE를 반환합니다.
  • SuccessOnAll 정책: 모든 자식이 SUCCESS를 반환할 때만 SUCCESS를 반환합니다.
  • SuccessOnOne 정책: 적어도 하나의 자식이 SUCCESS를 반환하고 다른 자식들이 RUNNING이면 SUCCESS를 반환합니다.
  • SuccessOnSelected 정책: 지정된 자식 하위 집합이 SUCCESS를 반환할 때만 SUCCESS를 반환합니다.

SuccessOnAll과 SuccessOnSelected 정책은 동기화되도록 구성될 수 있으며, 이 경우 SUCCESS로 틱된 자식은 정책 기준이 충족되거나 자식 중 하나가 FAILURE 상태를 반환할 때까지 후속 틱에서 건너뜁니다.

SuccessOnSelected 정책이 있는 Parallel은 setup()과 tick() 메서드에서 선택된 자식 집합이 실제로 이 병렬의 자식 집합의 부분집합인지 확인합니다.