A.2 ROS2 YASMIN
1. 로봇 행동 제어 아키텍처에서 상태 머신의 역할 및 기술적 필요성
로봇 시스템은 복잡하고 동적인 환경에서 부여된 임무를 자율적으로 수행하기 위해 계층적 또는 하이브리드 형태의 행동 제어 아키텍처(Behavior Control Architecture)를 채택한다. 이러한 아키텍처 내에서 인지(Perception), 계획(Planning), 제어(Control) 모듈은 상호 비동기적으로 데이터를 교환하며 작동한다. 상태 머신(State Machine)은 이 과정에서 필수적인 시스템 통합 및 논리 제어 메커니즘으로 기능한다.
1.1 상태 머신의 역할
유한 상태 머신(Finite State Machine, FSM)은 비동기적이고 복잡한 로봇 하위 시스템들의 실행 흐름을 조율하는 상위 수준의 작업 관리자(Task Executive) 역할을 수행한다. 로봇의 전체 임무를 유한한 개수의 이산적인 ’상태(State)’로 분할하고, 센서 데이터나 내부 연산 결과와 같은 특정 ‘이벤트(Event)’ 또는 ’조건’에 의해 상태 간의 ’전이(Transition)’를 수학적으로 정의하여 로봇의 행동 절차를 논리적으로 모델링한다.
1.2 기술적 필요성
로봇 소프트웨어 스택(ROS 2 등)에 상태 머신을 도입해야 하는 기술적 당위성은 다음과 같은 네 가지 측면에서 설명할 수 있다.
- 결정론적 제어 및 예측 가능성 확보: 상태 머신은 현재의 상태와 입력된 이벤트의 조합에 의해서만 다음 상태가 결정되는 구조를 갖는다. 이를 통해 예기치 않은 하드웨어 오류, 통신 지연 또는 센서 노이즈가 발생하더라도 시스템이 정의되지 않은 행동을 수행하는 것을 방지하고, 로봇의 반응을 수학적이고 결정론적으로 예측하고 통제할 수 있다.
- 비동기 이벤트 처리의 추상화: 분산 통신 프레임워크인 ROS 2 환경에서는 다수의 토픽(Topic), 서비스(Service), 액션(Action) 통신이 병렬 및 비동기적으로 발생한다. 상태 머신은 복잡한 비동기 콜백(Callback) 구조와 스레드 관리를 논리적인 전이 조건으로 추상화하여, 시스템 레벨의 교착 상태(Deadlock)나 경쟁 상태(Race Condition) 발생 위험을 최소화한다.
- 소프트웨어 아키텍처의 모듈화 및 재사용성: 로봇의 특정 행동(예: 객체 인식 대기, 목표점 이동, 그리퍼 제어)을 독립적인 상태 클래스로 캡슐화한다. 이는 소프트웨어의 결합도(Coupling)를 낮추고 응집도(Cohesion)를 높이는 객체 지향적 설계 원칙에 부합하며, 복잡한 자율 주행이나 매니퓰레이션 시나리오를 구성할 때 기 검증된 상태 모듈을 조합하여 재사용할 수 있게 한다.
- 시스템 가시성 및 추적성(Traceability) 향상: 로봇의 행동 알고리즘을 방향성 그래프(Directed Graph) 형태의 명시적인 자료구조로 매핑할 수 있다. 이는 런타임(Runtime) 환경에서 로봇의 현재 논리적 위치를 실시간으로 모니터링하고, 임무 실패 시 어느 상태 및 전이 과정에서 오류가 발생했는지 명확하게 추적하여 디버깅 효율을 극대화한다.
2. YASMIN의 학술적 정의 및 아키텍처 설계 원리
2.1 프레임워크의 학술적 및 기술적 정의
YASMIN(Yet Another State Machine IN ROS 2)은 ROS 2(Robot Operating System 2) 환경에서 자율 로봇의 절차적 임무 실행 논리를 제어하기 위해 고안된 경량 유한 상태 머신(Finite State Machine, FSM) 프레임워크이다. 본 프레임워크는 로봇의 복잡한 행동 절차를 이산적인 ‘상태(State)’ 집합과 방향성 있는 ‘전이(Transition)’ 네트워크로 추상화하여, 수학적 상태 전이 모델에 기반한 결정론적(Deterministic) 제어 시스템을 구축하는 소프트웨어 라이브러리로 기능한다.
2.2 핵심 설계 목적 (Design Objectives)
YASMIN의 아키텍처는 기존 ROS 생태계 내 상태 머신 도구(SMACH, SMACC2 등)가 지닌 언어적 편향성 및 시스템 오버헤드 한계를 극복하기 위해 다음 세 가지 목적을 중심으로 설계되었다.
- API 대칭성(Symmetry) 및 다중 언어 네이티브 지원: ROS 1의 SMACH가 Python에, ROS 2의 SMACC2가 C++에 심층적으로 종속된 것과 대조적으로, YASMIN은 C++17 및 Python 3 환경에서 논리적으로 동일한 네이티브 API를 제공한다. 이는 이기종 언어로 구성된 다중 노드 시스템(Multi-node System)에서 상태 머신 로직의 상호 운용성을 보장한다.
- 시스템 오버헤드 최소화 (Minimization of System Overhead): 복잡한 직교(Orthogonal) 컴포넌트 아키텍처를 배제하고, FSM의 본질적 요소인 상태와 전이에 집중한 경량화(Lightweight) 설계를 지향한다. 이를 통해 컴퓨팅 자원이 제한된 에지 디바이스(Edge Device) 환경에서도 메모리 점유와 CPU 부하 없이 실시간 처리를 지원한다.
- 학습 곡선(Learning Curve) 완화: 상태 정의, 출력값(Outcome) 선언, 블랙보드(Blackboard) 매핑으로 이어지는 직관적인 인터페이스 규격을 제공한다. 개발자가 ROS 2의 복잡한 비동기 통신 스택(Action, Service 등) 내부 구현에 얽매이지 않고 행동 논리 모델링 자체에 집중할 수 있도록 추상화 계층을 제공한다.
[구현 명세: C++ 및 Python API 대칭성 비교]
프레임워크의 설계 목적을 입증하는 단일 상태(State) 모듈의 최소 구현 코드이다. 두 이기종 언어 간의 구조적 대칭성이 객체 지향 수준에서 엄격하게 유지됨을 확인할 수 있다.
C++17 기반 상태 구현:
C++
#include <yasmin/state.hpp> class ExampleState : public yasmin::State { public: // 생성자를 통한 출력값 명시적 선언 ExampleState() : yasmin::State({"SUCCEEDED", "ABORTED"}) {} // execute 메서드 오버라이딩 std::string execute(yasmin::Blackboard& blackboard) override { // 비즈니스 로직 수행 후 출력값 반환 return "SUCCEEDED"; } };Python 3 기반 상태 구현:
Python
import yasmin class ExampleState(yasmin.State): def __init__(self): # 생성자를 통한 출력값 명시적 선언 super().__init__(outcomes=['SUCCEEDED', 'ABORTED']) # execute 메서드 오버라이딩 def execute(self, blackboard): # 비즈니스 로직 수행 후 출력값 반환 return 'SUCCEEDED'
2.3 핵심 아키텍처적 특성 (Architectural Characteristics)
YASMIN 프레임워크는 로봇 소프트웨어 공학의 모듈화(Modularity) 및 확장성(Scalability) 원칙을 준수하며, 시스템 통합 시 다음과 같은 4가지 구조적 이점을 제공한다.
- 미들웨어 의존성 분리 (Decoupling from Middleware): 코어 상태 연산 엔진은 ROS 2의 데이터 분배 서비스(DDS) 및 RMW(ROS Middleware) 계층과 논리적으로 분리되어 동작한다. 순수 상태 연산은 노드의 생명주기와 독립적으로 관리되며, 외부 통신(Topic, Action 등)이 필요한 경우에만 전용 래퍼(Wrapper) 상태를 통해 비동기적으로 결합하는 느슨한 결합(Loose Coupling) 패턴을 취한다.
- 계층적 상태 머신 (Hierarchical State Machine, HFSM) 구조 지원: 특정 상태 머신 자체를 다른 상위 상태 머신의 단일 ‘상태’ 노드로 캡슐화하는 중첩(Nesting) 아키텍처를 네이티브로 제공한다. 이는 대규모 자율 주행 및 매니퓰레이션 임무를 서브 태스크(Sub-task) 단위로 분할하여 추상화 수준을 통제하고, 기 검증된 모듈의 재사용성을 극대화한다.
- 통합형 블랙보드 패턴 (Integrated Blackboard Pattern): 상태 간 직접적인 데이터(포인터, 전역 변수 등) 전달을 배제하고, 각 상태 머신 계층별로 독립 할당되는 스레드 안전(Thread-safe)한 키-값(Key-Value) 기반 저장소를 내장한다. 인지(Perception) 모듈의 획득 데이터를 제어(Control) 모듈로 무결하게 전달하는 파이프라인 역할을 수행한다.
- ROS 2 실행 모델 (Execution Model) 동기화: ROS 2의 다중 스레드 실행기(Multi-Threaded Executor) 및 상호 배타적 콜백 그룹(Mutually Exclusive Callback Group) 아키텍처와 호환되도록 설계되었다. 블로킹(Blocking) 기반의 동기적 상태 전이와 이벤트(Event) 구동형 비동기 전이를 단일 프레임워크 내에서 스레드 충돌 없이 스케줄링할 수 있다.
2.4 기존 ROS 1/2 상태 머신 라이브러리(SMACH, SMACC 등)와의 구조적 제원 및 기능 비교
로봇 운영체제(ROS) 생태계에서 행동 제어 아키텍처를 구현하기 위해 개발된 주요 상태 머신 라이브러리들은 각기 다른 설계 철학과 구조적 제원을 지니고 있다. YASMIN의 기술적 포지셔닝을 명확히 하기 위해 기존의 대표적 라이브러리인 SMACH, SMACC/SMACC2와의 아키텍처 및 기능적 특성을 비교 분석한다.
2.4.1 SMACH (ROS 1)
SMACH(State Machine)는 ROS 1 환경에서 가장 널리 채택된 작업 수준(Task-level) 아키텍처 라이브러리이다.
- 구조적 특성: Python 언어 전용으로 개발되었으며, 상태(State), 컨테이너(Container), 사용자 데이터(Userdata)를 기반으로 하는 계층적 유한 상태 머신(HFSM) 구조를 갖는다. 동시성(Concurrency) 제어를 위한 Concurrence 컨테이너를 지원한다.
- 기술적 한계: ROS 1의 통신 스택에 강하게 결합되어 있어 ROS 2로의 완전하고 공식적인 포팅이 이루어지지 않았다. 또한 Python 인터프리터 언어의 특성상 실시간(Real-time) 제어가 요구되거나 연산 부하가 높은 C++ 기반의 하위 제어기와의 네이티브 통합 시 성능 오버헤드(Overhead) 및 직렬화/역직렬화(Serialization/Deserialization) 병목이 발생한다.
2.4.2 SMACC 및 SMACC2 (ROS 1 / ROS 2)
SMACC(ROS 1)와 이를 계승한 SMACC2(ROS 2)는 이벤트 구동형(Event-driven) 및 비동기적 행동 제어에 특화된 C++ 기반의 라이브러리이다.
- 구조적 특성: 상태 머신(State Machine), 직교(Orthogonals), 클라이언트(Clients), 컴포넌트(Components)라는 고도로 분리된 아키텍처를 채택하고 있다. 특히 하드웨어 인터페이스를 독립적인 직교 컴포넌트로 분리하여 상태 머신 논리와 로봇 하드웨어 간의 의존성을 소거한 것이 핵심 제원이다.
- 기술적 한계: C++ 템플릿 메타프로그래밍(Template Metaprogramming)을 광범위하게 사용하여 컴파일 시간이 길고 디버깅이 난해하다. 아키텍처가 방대하여 소규모 로봇 시스템이나 단일 노드 기반의 빠른 프로토타이핑(Prototyping)을 수행할 때 과도한 보일러플레이트(Boilerplate) 코드를 작성해야 하는 등 학습 곡선(Learning Curve)이 매우 높다.
2.4.3 YASMIN과의 아키텍처 및 제원 비교
YASMIN은 SMACH의 높은 직관성과 SMACC2의 ROS 2 호환성 및 성능적 이점을 절충하여 설계된 경량 프레임워크이다.
- API 및 언어 지원의 대칭성: SMACH가 Python에, SMACC2가 C++에 편중된 것과 대조적으로, YASMIN은 C++와 Python에 대해 구조적으로 대칭적인 네이티브 API를 제공한다. 이는 단일 로봇 시스템 내에서 이기종 언어로 작성된 노드 간의 상태 머신 통합을 용이하게 한다.
- 시스템 복잡도 및 아키텍처 풋프린트(Footprint): SMACC2의 복잡한 직교 아키텍처를 배제하고, FSM의 수학적 본질인 상태(State)와 전이(Transition)에 집중했다. 메모리 점유율이 낮고 연산 구조가 단순하여 시스템 자원이 제한적인 임베디드 환경(예: Raspberry Pi, 단일 보드 컴퓨터)에서의 운용에 적합하다.
- 데이터 공유 토폴로지: SMACH의 Userdata 포인터 전달 방식이나 SMACC2의 State Components 패턴 대신, 통합된 블랙보드(Blackboard) 패턴을 채택하여 상태 간 결합도를 낮추고 데이터 은닉성을 강화했다.
2.4.4 라이브러리별 핵심 제원 종합 비교표
| 비교 항목 | SMACH | SMACC2 | YASMIN |
|---|---|---|---|
| 대상 ROS 버전 | ROS 1 (ROS 2 비공식 지원) | ROS 2 | ROS 2 |
| 기본 지원 언어 | Python | C++ (17/20) | C++ (17), Python 3 |
| 주요 아키텍처 | 계층형 (Hierarchical) | 직교형 (Orthogonal) + 계층형 | 계층형 (Hierarchical) |
| 데이터 공유 메커니즘 | Userdata 맵핑 | State Components / Orthogonals | Blackboard 패턴 |
| 학습 곡선 / 복잡도 | 낮음 (Low) | 매우 높음 (Very High) | 보통 (Medium) |
| ROS 2 Action 통합 | 제한적 (비공식 포팅 의존) | 네이티브 지원 (Action Client/Server 깊은 통합) | 네이티브 래퍼(Wrapper) 지원 |
| 적합한 적용 도메인 | ROS 1 기반의 연구용 프로토타입 | 대규모, 하드웨어 복합 ROS 2 상용 시스템 | 다중 언어 환경, 경량화가 필요한 ROS 2 제어 시스템 |
3. YASMIN의 내부 소프트웨어 스택 및 ROS 2 생태계 통합 모델
YASMIN은 ROS 2의 분산 컴포넌트 아키텍처와 원활하게 연동되면서도, 상태 머신 자체의 논리적 독립성을 보장하기 위해 다층적(Multi-layered)이고 유연한 소프트웨어 스택을 갖추고 있다. 본 장에서는 YASMIN의 내부 동작 구조와 ROS 2 시스템 환경과의 통합 메커니즘을 규명한다.
3.1 코어 엔진과 미들웨어의 논리적 분리
YASMIN의 핵심 상태 추론 엔진(Core State Inference Engine)은 ROS 2의 데이터 분배 서비스(DDS) 미들웨어나 통신 계층에 직접적으로 종속되지 않도록 설계되었다.
- 상태의 생성, 블랙보드(Blackboard)를 통한 변수 연산, 조건부 전이(Transition) 검사와 같은 유한 상태 머신의 순수 논리 연산은 ROS 2 라이브러리(
rclcpp또는rclpy)와 무관한 독립적인 객체로 동작한다. - 이러한 미들웨어 종속성의 배제는 비즈니스 로직과 통신 계층을 분리하는 최신 로봇 소프트웨어 공학 패턴을 따른 것으로, YASMIN 코어 로직의 단위 테스트(Unit Test)를 용이하게 하고 타 프레임워크로의 이식성을 극대화한다.
3.2 ROS 2 실행 모델(Execution Model)과의 동기화 메커니즘
ROS 2 시스템 내에서 YASMIN 상태 머신을 구동하기 위해서는 로봇의 전역 제어 주기(Control Loop)에 맞추어 상태를 갱신해야 한다.
- 주기적 실행(Tick-based Execution): YASMIN은 ROS 2 노드의 타이머 콜백(Timer Callback)을 활용하여 상태 머신의
spin()또는process()메서드를 일정한 헤르츠(Hz)로 호출하는 동기식 폴링(Polling) 구조를 지원한다. - 스레드 안전성(Thread-Safety): 다수의 센서 데이터를 병렬로 처리하는 ROS 2의 다중 스레드 실행기(Multi-Threaded Executor) 환경에서 발생할 수 있는 데이터 경합(Data Race)을 방지하기 위해, 상태 갱신 및 블랙보드 접근 시 스레드 안전을 보장하는 상호 배제(Mutex) 메커니즘을 내부적으로 구현하고 있다.
3.3 표준 통신 인터페이스(Action, Service, Topic)의 네이티브 통합
상태 머신 내부의 제어 논리가 외부의 독립적인 로봇 컴포넌트(예: Nav2 내비게이션 스택, MoveIt2 매니퓰레이션 프레임워크)와 비동기적으로 상호작용할 수 있도록, YASMIN은 통신 래퍼(Wrapper) 패턴을 적용한 특화된 상태 클래스를 제공한다.
- 액션(Action) 통합: 자율 주행과 같이 장시간이 소요되는 선점형(Preemptable) 작업의 경우, YASMIN은
ActionClientState를 통해 행동을 제어한다. 액션 서버로 목표(Goal)를 전송한 후 대기 상태를 유지하며, 피드백(Feedback)을 수신하여 블랙보드를 갱신하고, 최종 결과(Result) 노드에 따라 ‘SUCCEEDED’, ‘ABORTED’ 등의 명시적 엣지(Edge)로 전이한다. - 서비스(Service) 및 토픽(Topic) 통합: 단발성 데이터 연산 요청이나 특정 센서의 이벤트 발생 대기를 위해
ServiceClientState및SubscriberState를 지원한다. 이는 ROS 2의 비동기 콜백을 상태 머신의 동기적 전이 조건으로 변환하여, 복잡한 콜백 지옥(Callback Hell)을 평면적인 상태 흐름으로 추상화한다.
3.4 생명주기 관리 노드(Lifecycle Node) 아키텍처 호환성
고신뢰성 및 상용 수준의 로봇 시스템 구축을 위해 YASMIN은 ROS 2의 rclcpp_lifecycle (생명주기 관리 노드) 규격과 결합할 수 있다.
- 상태 머신의 메모리 할당 및 초기화는 노드의
Unconfigured단계에서 수행된다. - 하위 컴포넌트와의 통신 연결 및 전이 활성화는
Active단계로 매핑된다. - 오류 발생 시 상태 머신의 즉각적인 정지 및 블랙보드 초기화를
Inactive또는Finalized단계와 연동하여, 시스템 전체의 결정론적 종료 및 재시작 절차를 안전하게 통제할 수 있다.
4. 상태(State) 인스턴스 및 상태 전이(Transition)의 논리적 정의와 구현
유한 상태 머신(FSM)의 핵심은 시스템의 연속적인 행위를 유한한 상태들의 집합과 그 사이의 전이 관계로 추상화하는 데 있다. YASMIN 프레임워크 내에서 상태와 전이는 로봇의 특정 절차적 행동과 제어 흐름을 결정짓는 최소 논리 단위로 정의되며, 객체 지향적(Object-Oriented) 인터페이스를 통해 시스템에 인스턴스화된다.
4.1 상태(State) 인스턴스의 아키텍처적 구조
YASMIN에서 하나의 상태(State) 인스턴스는 로봇이 수행해야 할 독립적이고 캡슐화된 작업(Task) 단위를 의미한다. 모든 사용자 정의 상태는 프레임워크가 제공하는 추상 기본 클래스를 상속받아 구현되며, 다음의 엄격한 생명주기 및 인터페이스 규약을 따른다.
- 출력값(Outcomes)의 명시적 선언: 각 상태는 생성 시점에 실행 완료 후 반환할 수 있는 논리적 결과들의 집합(예:
SUCCEEDED,ABORTED)을 사전에 선언해야 한다. 이는 코어 엔진과의 논리적 계약(Contract)으로 작용하며, 선언되지 않은 출력값이 반환될 경우 런타임 예외(Exception)를 발생시켜 시스템의 불안정성을 차단한다. - 비즈니스 로직의 캡슐화 (
execute메서드): 상태가 활성화되면 오버라이딩된 실행 함수가 호출된다. 이 메서드 내부에는 센서 연산이나 제어 명령 등 단일 책임 원칙(SRP)에 부합하는 로직만이 포함되어야 하며, 연산 종료 후 반드시 선언된 출력값 중 하나를 반환하여 제어권을 시스템에 넘겨야 한다.
[구현 명세: 사용자 정의 상태의 생명주기 및 로직 캡슐화]
다음은 블랙보드에서 목표를 확인하고 출력값을 반환하는 상태의 대칭적 구현 예시이다.
C++ 구현:
C++
#include <yasmin/state.hpp> #include <string> class TargetCheckState : public yasmin::State { public: // 생성자: 가능한 출력값 선언 TargetCheckState() : yasmin::State({"TARGET_FOUND", "TARGET_MISSING"}) {} // 실행 로직 오버라이딩 std::string execute(yasmin::Blackboard& blackboard) override { bool has_target = blackboard.has("target_pose"); if (has_target) { return "TARGET_FOUND"; } return "TARGET_MISSING"; } };Python 구현:
Python
import yasmin class TargetCheckState(yasmin.State): def __init__(self): # 생성자: 가능한 출력값 선언 super().__init__(outcomes=['TARGET_FOUND', 'TARGET_MISSING']) # 실행 로직 오버라이딩 def execute(self, blackboard): if blackboard.has('target_pose'): return 'TARGET_FOUND' return 'TARGET_MISSING'
4.2 상태 전이(Transition)의 수학적 모델링 및 결정론적 라우팅
상태 전이는 현재 활성화된 상태의 반환값에 따라 다음으로 제어권을 넘겨받을 상태를 결정하는 방향성 연관 관계(Directed Association)이다. YASMIN은 이러한 전이 규칙을 런타임에 동적으로 해석하지 않고, 초기화 단계에서 정적 라우팅 테이블(Static Routing Table)로 구성하여 결정론적 반응성을 보장한다.
- 전이 함수(Transition Function) 매핑: 상태 머신의 논리적 흐름은 수학적 매핑인 T: S \times O \rightarrow S'로 모델링된다. 여기서 S는 현재 활성화된 상태(Source State), O는 상태 S의 실행 결과로 반환된 출력값(Outcome), S'는 전이될 다음 상태(Target State)를 의미한다.
- 해시 기반(Hash-based) 결정론적 라우팅: 코어 엔진은 O가 반환되는 즉시 시간 복잡도 O(1)의 해시 테이블 탐색을 통해 S'를 도출하고 시스템의 논리적 커서를 즉각 이동시킨다.
[구현 명세: 방향성 그래프의 간선(Edge) 연결]
앞서 정의한
TargetCheckState의 반환값(O)에 따라 다음 상태(S')를 결정하는 T 매핑 코드는 다음과 같이 작성된다. 언어에 관계없이 API 명세가 완전히 동일하다.C++ API를 활용한 전이 매핑:
C++
// S: TARGET_CHECK, O: TARGET_FOUND -> S': MOVE_TO_TARGET sm->add_transition("TARGET_CHECK", "TARGET_FOUND", "MOVE_TO_TARGET"); // S: TARGET_CHECK, O: TARGET_MISSING -> S': WAIT_FOR_TARGET sm->add_transition("TARGET_CHECK", "TARGET_MISSING", "WAIT_FOR_TARGET");Python API를 활용한 전이 매핑:
Python
# S: TARGET_CHECK, O: TARGET_FOUND -> S': MOVE_TO_TARGET sm.add_transition('TARGET_CHECK', 'TARGET_FOUND', 'MOVE_TO_TARGET') # S: TARGET_CHECK, O: TARGET_MISSING -> S': WAIT_FOR_TARGET sm.add_transition('TARGET_CHECK', 'TARGET_MISSING', 'WAIT_FOR_TARGET')
4.3 종료 상태(Terminal State)의 정의 및 제어권 반환
상태 머신의 실행 흐름을 종결짓기 위해 전이 그래프의 말단(Leaf Node)에 해당하는 종료 상태가 정의되어야 한다. YASMIN에서는 별도의 특수한 종료 상태 객체를 요구하지 않으며, 전이 규칙의 유무로 이를 판단한다.
- 실행 루프 종결 조건: 런타임 엔진은 현재 활성화된 상태가 반환한 출력값(O)에 대응하는 대상 상태(S')가 라우팅 테이블에 존재하지 않을 경우, 내부 틱(Tick) 연산을 즉시 중단한다.
- 상위 계층으로의 제어 이양: 실행이 종료되면, 해당 출력값은 상태 머신 전체의 최종 출력값(Final Outcome)으로 취급된다. 계층적 상태 머신(HFSM) 구조일 경우 이 값은 부모 상태 머신으로 전달되며, 단일 상태 머신일 경우 로봇 애플리케이션의 메인 제어 루프로 시스템 제어권이 안전하게 반환된다.
5. 블랙보드(Blackboard) 디자인 패턴을 활용한 상태 간 메모리 및 데이터 공유 메커니즘
로봇의 복잡한 임무 수행 과정에서 인지(Perception) 모듈이 획득한 데이터(예: 타겟 객체의 3D 좌표)를 후속 제어(Control) 모듈이 활용하기 위해서는 상태 간의 무결한 데이터 교환이 필수적이다. YASMIN 프레임워크는 이를 위해 전역 변수 참조나 메모리 포인터 직접 전달 방식 대신 소프트웨어 공학의 ‘블랙보드(Blackboard)’ 디자인 패턴을 채택하였다.
5.1 블랙보드의 구조적 정의
블랙보드는 상태 머신 내의 상태 인스턴스들이 공통으로 접근할 수 있는 중앙 집중형 공유 메모리 저장소(Shared Data Repository)이다. 문자열 식별자(String Key)와 임의의 자료형을 가진 값(Value)을 매핑하는 동적 키-값(Key-Value) 테이블 구조로 구현된다. 내부적으로 C++의 std::any (또는 이와 유사한 타입 이레이저 기법)와 Python의 동적 타이핑 특성을 활용하여, 기본 자료형뿐만 아니라 복잡한 ROS 2 메시지(Message) 구조체까지 단일 컨테이너 내에 형변환 오류 없이 유연하게 적재한다.
5.2 데이터 결합도 최소화 및 모듈화 이점
기존의 직접적인 매개변수 전달 방식은 상태 클래스 간의 강한 코드 의존성(Tight Coupling)을 유발하여 시스템의 유지보수를 저해한다. 반면, 블랙보드 패턴 하에서 개별 상태 모듈은 데이터의 생산자(Producer) 또는 소비자(Consumer)로만 독립적으로 기능한다.
- 생산자 상태: 외부 센서 처리 결과나 내부 연산 산출물을 블랙보드의 특정 키(Key)에 할당 및 기록(Write)한다.
- 소비자 상태: 제어 루프를 실행하기 전, 블랙보드의 지정된 키에 질의하여 필요한 데이터를 읽어온다(Read).
이러한 간접 통신 아키텍처는 상태 모듈 간의 상호 참조를 논리적으로 단절시킨다. 결과적으로 개발자는 데이터의 흐름을 신경 쓰지 않고 단일 상태의 행동 논리에만 집중할 수 있으며, 기 개발된 상태 모듈을 수정 없이 새로운 작업 시나리오의 파이프라인에 즉각적으로 재조합(Reusability)할 수 있다.
5.3 계층적 스코프(Scope)와 변수 리매핑(Remapping)
계층적 유한 상태 머신(HFSM) 구조를 지원하는 YASMIN에서, 블랙보드 메모리 공간은 각 상태 머신의 토폴로지 계층별로 독립적으로 할당되어 생명주기를 같이한다.
- 최상위(부모) 상태 머신의 전역 블랙보드와 하위(자식) 상태 머신의 지역 블랙보드는 기본적으로 격리되어 있다. 이는 하위 서브 태스크에서 발생한 로컬 데이터가 상위 전역 공간을 오염시키거나 변수명 충돌(Naming Collision)을 일으키는 것을 원천적으로 방지한다.
- 부모 시스템과 자식 시스템 간의 데이터 교환이 필수적인 경우, 명시적인 입력/출력 데이터 포트 리매핑(Input/Output Data Port Remapping) 규칙을 선언해야 한다. 이를 통해 특정 데이터 키에 대해서만 접근 권한을 연결하는 엄격한 데이터 캡슐화(Encapsulation) 원칙을 준수한다.
5.4 다중 스레드 환경에서의 데이터 무결성 보장
ROS 2 운영 환경은 다중 콜백 그룹과 멀티 스레드 실행기(Multi-Threaded Executor)를 기반으로 비동기 연산을 수행하므로, 여러 콜백 스레드나 병렬 상태가 동시에 동일한 블랙보드 메모리 주소에 접근할 위험이 상존한다. 이를 통제하기 위해 YASMIN의 블랙보드 자료구조는 내부적으로 엄격한 스레드 안전(Thread-safe) 메커니즘을 내장하고 있다.
데이터의 읽기, 쓰기 및 키 검증 연산 발생 시 운영체제 수준의 상호 배제(Mutex) 또는 읽기-쓰기 잠금(Read-Write Lock) 알고리즘을 강제 적용하여, 런타임 중 데이터 경합(Data Race)으로 인한 메모리 접근 위반(Segmentation Fault)이나 논리적 제어 오류를 방지하고 연산의 원자성(Atomicity)을 보장한다.
5.5 블랙보드(Blackboard) 디자인 패턴을 활용한 상태 간 메모리 및 데이터 공유 메커니즘
로봇의 복잡한 임무 수행 과정에서 인지(Perception) 모듈이 획득한 데이터(예: 타겟 객체의 3D 좌표)를 후속 제어(Control) 모듈이 활용하기 위해서는 상태 간의 무결한 데이터 교환이 필수적이다. YASMIN 프레임워크는 이를 위해 전역 변수 참조나 메모리 포인터 직접 전달 방식 대신 소프트웨어 공학의 ‘블랙보드(Blackboard)’ 디자인 패턴을 채택하였다.
5.5.1 블랙보드의 구조적 정의
블랙보드는 상태 머신 내의 상태 인스턴스들이 공통으로 접근할 수 있는 중앙 집중형 공유 메모리 저장소(Shared Data Repository)이다. 문자열 식별자(String Key)와 임의의 자료형을 가진 값(Value)을 매핑하는 동적 키-값(Key-Value) 테이블 구조로 구현된다. 내부적으로 C++의 std::any (또는 이와 유사한 타입 이레이저 기법)와 Python의 동적 타이핑 특성을 활용하여, 기본 자료형뿐만 아니라 복잡한 ROS 2 메시지(Message) 구조체까지 단일 컨테이너 내에 형변환 오류 없이 유연하게 적재한다.
5.5.2 데이터 결합도 최소화 및 모듈화 이점
기존의 직접적인 매개변수 전달 방식은 상태 클래스 간의 강한 코드 의존성(Tight Coupling)을 유발하여 시스템의 유지보수를 저해한다. 반면, 블랙보드 패턴 하에서 개별 상태 모듈은 데이터의 생산자(Producer) 또는 소비자(Consumer)로만 독립적으로 기능한다.
- 생산자 상태: 외부 센서 처리 결과나 내부 연산 산출물을 블랙보드의 특정 키(Key)에 할당 및 기록(Write)한다.
- 소비자 상태: 제어 루프를 실행하기 전, 블랙보드의 지정된 키에 질의하여 필요한 데이터를 읽어온다(Read).
이러한 간접 통신 아키텍처는 상태 모듈 간의 상호 참조를 논리적으로 단절시킨다. 결과적으로 개발자는 데이터의 흐름을 신경 쓰지 않고 단일 상태의 행동 논리에만 집중할 수 있으며, 기 개발된 상태 모듈을 수정 없이 새로운 작업 시나리오의 파이프라인에 즉각적으로 재조합(Reusability)할 수 있다.
5.5.3 [구현 명세: 블랙보드 데이터 적재(Write) 및 추출(Read)]
생산자 및 소비자 패턴을 활용하여 블랙보드에 데이터를 기록하고 조회하는 핵심 API 사용 명세는 다음과 같다. 프레임워크 설계 원칙에 따라 이기종 언어 환경에서도 대칭적인 접근 방식을 제공한다.
C++ API 구현 예제:
#include <yasmin/state.hpp>
class CalculationState : public yasmin::State {
public:
CalculationState() : yasmin::State({"SUCCEEDED", "ABORTED"}) {}
std::string execute(yasmin::Blackboard& blackboard) override {
// 1. 소비자(Consumer) 역할: 데이터 추출 (Read)
if (blackboard.has("target_x")) {
double target = blackboard.get<double>("target_x");
double current_position = 10.5; // 센서 등으로부터 획득한 현재 위치 가정
// 2. 생산자(Producer) 역할: 비즈니스 로직 수행 후 데이터 적재 (Write)
double calculated_error = target - current_position;
blackboard.set("error_margin", calculated_error);
return "SUCCEEDED";
}
// 블랙보드에 필수 타겟 데이터가 누락되었을 경우 예외 전이
return "ABORTED";
}
};
Python API 구현 예제:
import yasmin
class CalculationState(yasmin.State):
def __init__(self):
super().__init__(outcomes=['SUCCEEDED', 'ABORTED'])
def execute(self, blackboard):
# 1. 소비자(Consumer) 역할: 데이터 추출 (Read)
if blackboard.has('target_x'):
target = blackboard.get('target_x')
current_position = 10.5 # 센서 등으로부터 획득한 현재 위치 가정
# 2. 생산자(Producer) 역할: 비즈니스 로직 수행 후 데이터 적재 (Write)
calculated_error = target - current_position
blackboard.set('error_margin', calculated_error)
return 'SUCCEEDED'
# 블랙보드에 필수 타겟 데이터가 누락되었을 경우 예외 전이
return 'ABORTED'
5.5.4 계층적 스코프(Scope)와 변수 리매핑(Remapping)
계층적 유한 상태 머신(HFSM) 구조를 지원하는 YASMIN에서, 블랙보드 메모 공간은 각 상태 머신의 토폴로지 계층별로 독립적으로 할당되어 생명주기를 같이한다.
최상위(부모) 상태 머신의 전역 블랙보드와 하위(자식) 상태 머신의 지역 블랙보드는 기본적으로 격리되어 있다. 이는 하위 서브 태스크에서 발생한 로컬 데이터가 상위 전역 공간을 오염시키거나 변수명 충돌(Naming Collision)을 일으키는 것을 원천적으로 방지한다. 부모 시스템과 자식 시스템 간의 데이터 교환이 필수적인 경우, 명시적인 입력/출력 데이터 포트 리매핑(Input/Output Data Port Remapping) 규칙을 선언해야 한다. 이를 통해 특정 데이터 키에 대해서만 접근 권한을 연결하는 엄격한 데이터 캡슐화(Encapsulation) 원칙을 준수한다.
5.5.5 다중 스레드 환경에서의 데이터 무결성 보장
ROS 2 운영 환경은 다중 콜백 그룹과 멀티 스레드 실행기(Multi-Threaded Executor)를 기반으로 비동기 연산을 수행하므로, 여러 콜백 스레드나 병렬 상태가 동시에 동일한 블랙보드 메모리 주소에 접근할 위험이 상존한다.
이를 통제하기 위해 YASMIN의 블랙보드 자료구조는 내부적으로 엄격한 스레드 안전(Thread-safe) 메커니즘을 내장하고 있다. 데이터의 읽기, 쓰기 및 키 검증 연산 발생 시 운영체제 수준의 상호 배제(Mutex) 또는 읽기-쓰기 잠금(Read-Write Lock) 알고리즘을 강제 적용하여, 런타임 중 데이터 경합(Data Race)으로 인한 메모리 접근 위반(Segmentation Fault)이나 논리적 제어 오류를 방지하고 연산의 원자성(Atomicity)을 보장한다.
6. 하드웨어 및 ROS 2 배포판(Distribution)별 호환성 및 요구 제원
YASMIN은 다양한 로봇 플랫폼과 컴퓨팅 환경에서 범용적으로 작동하도록 설계되었다. 본 장에서는 YASMIN 프레임워크를 정상적으로 구동하기 위한 운영체제, ROS 2 배포판, 하드웨어 아키텍처 및 최소 시스템 요구 제원을 명시한다.
6.1 ROS 2 배포판 및 운영체제 호환성
YASMIN은 ROS 2의 장기 지원(LTS, Long Term Support) 버전 및 최신 릴리스와 공식적으로 호환된다. 컴파일 및 런타임 환경은 각 ROS 2 배포판이 타기팅하는 기본 운영체제에 종속된다.
- ROS 2 Humble Hawksbill: Ubuntu 22.04 LTS (Jammy Jellyfish) 환경에서 완벽하게 지원되며, 현재 로봇 산업계에서 가장 널리 쓰이는 안정적인 레퍼런스 플랫폼으로 활용된다.
- ROS 2 Iron Irwini 및 Jazzy Jalisco: 최신 C++ 표준 기능과 향상된 미들웨어 성능을 활용하기 위해 Ubuntu 22.04 및 24.04 LTS (Noble Numbat) 환경에서 호환성을 제공한다.
- ROS 2 Rolling Ridley: 지속적 통합(CI) 및 배포 파이프라인을 통해 최신 ROS 2 개발 브랜치와의 호환성을 상시 검증받고 있다.
6.2 지원 하드웨어 아키텍처
YASMIN은 하드웨어 종속적인 시스템 호출을 최소화한 플랫폼 독립적인 코드베이스로 작성되어, 로보틱스 분야에서 활용되는 주요 명령어 집합 아키텍처(ISA)를 모두 지원한다.
- x86_64 (AMD64): 일반적인 개발용 데스크톱 PC, 고성능 워크스테이션 및 클라우드 기반의 로봇 시뮬레이션(Gazebo, Ignition) 구동 환경에 적합하다.
- ARM64 (aarch64): 컴퓨팅 자원이 제한적인 단일 보드 컴퓨터(SBC, 예: Raspberry Pi 4/5) 및 하드웨어 가속기가 탑재된 에지 디바이스(예: NVIDIA Jetson Orin/Xavier 시리즈)에서 크로스 컴파일 또는 네이티브 빌드를 통해 정상 작동한다.
6.3 소프트웨어 언어 표준 및 컴파일러 의존성
YASMIN의 대칭적 API와 내부 구조를 활용하기 위해 다음과 같은 프로그래밍 언어 표준이 요구된다.
- C++ 환경: 최소 C++17 표준 규격을 준수하는 컴파일러(GCC 11 이상 또는 동급의 Clang)가 필수적이다. 이는 YASMIN의 블랙보드 시스템이 다양한 데이터 타입을 안전하게 적재하기 위해
std::any,std::variant,std::shared_ptr등 모던 C++의 타입 이레이저(Type Erasure) 및 스마트 포인터 기능을 적극적으로 활용하기 때문이다. - Python 환경: Python 3.10 이상의 인터프리터가 요구되며, ROS 2의
rclpy라이브러리 스택과 충돌 없이 독립적으로 작동한다.
6.4 시스템 자원(Resource) 요구 제원
YASMIN은 복잡한 템플릿 메타프로그래밍이나 과도한 백그라운드 스레드 생성을 배제한 경량 프레임워크이므로 시스템 오버헤드가 극히 낮다.
- 메모리(RAM): 코어 상태 엔진 및 빈 블랙보드가 차지하는 기본 메모리 풋프린트(Footprint)는 수 메가바이트(MB) 이내로 제한된다. 단, 런타임 중 블랙보드에 적재되는 고용량 ROS 2 메시지(예: PointCloud2, Image)의 크기와 빈도에 따라 전체 메모리 점유율은 동적으로 증가할 수 있다.
- 프로세서(CPU): 해시 테이블 기반의 상태 전이 연산은 O(1) 또는 최악의 경우 O(\log n)의 시간 복잡도를 가지므로, 1GHz 대역의 저전력 프로세서에서도 지연 시간(Latency) 병목 없이 실시간에 준하는 고주파 제어 루프를 안정적으로 유지할 수 있다.
7. YASMIN 의존성 패키지(Dependencies) 구성 및 소스 빌드 절차
YASMIN 프레임워크를 ROS 2 환경에 성공적으로 통합하고 구동하기 위해서는 사전에 요구되는 의존성 소프트웨어 패키지들을 식별하고, 표준화된 빌드 시스템을 통해 소스 코드를 컴파일해야 한다. 본 장에서는 YASMIN의 핵심 의존성 구성 요소와 공식적인 소스 빌드 절차를 기술한다.
7.1 핵심 의존성(Dependencies) 소프트웨어 스택
YASMIN은 ROS 2의 표준 미들웨어 및 빌드 도구에 기반하며, 코어 로직과 언어별 인터페이스 구현을 위해 다음과 같은 의존성 패키지들을 요구한다.
- 공통 및 통신 미들웨어: ROS 2 통신 및 노드 관리를 위한 핵심 라이브러리인
rclcpp(C++용) 및rclpy(Python용)에 기본적으로 의존한다. 비동기 목표 지향적 작업 처리를 위한 액션(Action) 지원을 위해rclcpp_action및rclpy.action모듈이 추가로 요구된다. - 빌드 시스템(Build System): ROS 2의 메타 빌드 시스템인
colcon과 패키지 빌드 도구인ament_cmake(C++ 패키지용),ament_python(Python 패키지용)에 종속된다. - 서드파티(Third-party) 및 언어 표준: C++ 구현체의 경우 C++17 이상을 지원하는 컴파일러(GCC 또는 Clang) 표준 라이브러리에 의존하며, Python 구현체는 Python 3.10 이상의 런타임 환경을 필요로 한다. 상태 머신 시각화 도구(YASMIN Viewer)의 경우 웹소켓 통신이나 PyQt 기반의 추가적인 서드파티 UI/네트워크 라이브러리 의존성을 가질 수 있다.
7.2 워크스페이스(Workspace) 초기화 및 소스 코드 획득
ROS 2의 표준 패키지 관리 규칙에 따라 독립적인 워크스페이스를 생성하고 소스 코드를 병합하는 절차는 다음과 같다.
- 워크스페이스 디렉토리 생성: 사용자 환경에 표준 ROS 2 워크스페이스 디렉토리 트리(예:
yasmin_ws/src)를 생성한다. - 버전 관리 시스템을 통한 소스 병합:
git유틸리티를 사용하여 YASMIN의 공식 저장소(Repository)로부터 최신 소스 코드 및 관련 하위 모듈(Submodules)을 워크스페이스의src디렉토리로 복제(Clone)한다. - 의존성 자동 검측 및 설치:
rosdep도구를 사용하여 클론된 패키지의package.xml파일에 명시된 시스템 및 ROS 의존성 패키지 목록을 파싱하고, 운영체제 패키지 관리자(예:apt)를 통해 일괄 설치를 수행한다.
[구현 명세: 워크스페이스 생성 및 의존성 설치 예제]
# 워크스페이스 디렉토리 생성 및 이동
mkdir -p ~/yasmin_ws/src
cd ~/yasmin_ws/src
# 소스 코드 복제 (URL은 실제 저장소 주소로 대체)
git clone <YASMIN_REPOSITORY_URL>
# 루트 디렉토리로 이동 후 rosdep을 통한 의존성 일괄 설치
cd ~/yasmin_ws
rosdep install --from-paths src --ignore-src -r -y
7.3 소스 코드 컴파일 및 빌드(Build) 절차
소스 코드 확보 및 의존성 해결이 완료되면, colcon 빌드 도구를 활용하여 시스템 아키텍처에 맞는 바이너리 및 라이브러리를 생성한다.
- 메타 빌드 실행: 워크스페이스의 루트 디렉토리에서
colcon build명령어를 실행하여 YASMIN 코어 엔진, C++ 래퍼, Python 래퍼 및 관련 예제 패키지들을 순차적으로 컴파일한다. - 심볼릭 링크(Symbolic Link) 설치 적용: 개발 및 디버깅 과정에서의 효율성을 높이기 위해
--symlink-install인자를 부여하여 빌드하는 것이 권장된다. 이는 Python 스크립트나 설정(YAML) 파일 수정 시 전체 재빌드 과정을 생략하고 변경 사항을 런타임에 즉시 반영할 수 있게 한다. - 부분 패키지 선택 빌드: 컴퓨팅 자원을 절약하거나 특정 모듈(예: 타 노드에 통합하기 위한 C++ 코어 모듈)의 컴파일만 필요한 경우,
--packages-select인자를 사용하여 목표 패키지만을 선별적으로 빌드할 수 있다.
[구현 명세: colcon 기반 소스 코드 빌드 예제]
# 심볼릭 링크를 적용한 전체 패키지 빌드
colcon build --symlink-install
# C++ 코어 엔진 패키지만 선별적으로 빌드할 경우
colcon build --symlink-install --packages-select yasmin
7.4 빌드 검증 및 환경 변수 오버레이(Overlay)
빌드가 오류 없이 완료되면 운영체제가 YASMIN 라이브러리 및 노드 실행 파일을 인식할 수 있도록 런타임 환경을 재구성해야 한다.
- 오버레이 소싱(Sourcing): 빌드 산출물이 위치한
install디렉토리 내의 환경 설정 스크립트(예:setup.bash)를 소싱(Source)하여, 시스템의 ROS 2 환경 변수(AMENT_PREFIX_PATH,PYTHONPATH,LD_LIBRARY_PATH등)에 YASMIN 패키지 설치 경로를 주입한다. - 패키지 가시성 검증: 터미널에서
ros2 pkg list명령어를 호출하여 YASMIN 관련 라이브러리 패키지들이 정상적으로 출력되는지 확인한다. 이를 통해 컴파일 및 환경 변수 오버레이 절차의 무결성을 최종 검증한다.
[구현 명세: 환경 변수 소싱 및 패키지 검증 예제]
# 런타임 환경 변수 오버레이
source install/setup.bash
# YASMIN 패키지 인식 여부 확인
ros2 pkg list | grep yasmin
8. 워크스페이스(Workspace) 내 패키지 통합 및 초기화 검증
컴파일이 완료된 YASMIN 라이브러리를 사용자의 자체 ROS 2 패키지에 통합하고, 런타임 시 오류 없이 작동하도록 초기화(Initialization) 및 검증하는 절차는 시스템의 안정성을 확보하는 핵심 단계이다. 본 장에서는 사용자 워크스페이스 내에서 YASMIN을 연동하고 무결성을 확인하는 기술적 방법을 기술한다.
8.1 빌드 시스템 연동 및 패키지 탐색
사용자가 개발하는 독립적인 ROS 2 패키지에서 YASMIN API를 호출하기 위해서는 빌드 구성 파일에 명시적인 의존성 연결이 선행되어야 한다.
- 패키지 매니페스트(package.xml):
<depend>yasmin</depend>태그를 추가하여 ROS 2의 패키지 관리자가 런타임 및 빌드 타임에 해당 라이브러리를 탐색할 수 있도록 보장한다. - CMakeLists.txt (C++ 환경):
find_package(yasmin REQUIRED)명령어를 통해 YASMIN 라이브러리 및 헤더 파일의 경로를 확보하고,ament_target_dependencies(사용자_노드명 yasmin)를 호출하여 실행 파일 빌드 시 YASMIN 코어 라이브러리를 정적/동적으로 링킹(Linking)한다.
8.2 사용자 노드(Node) 내 상태 머신 인스턴스화
YASMIN 상태 머신은 ROS 2 시스템과 상호작용하기 위해 로봇의 메인 제어 노드(Node) 내부에서 객체화(Instantiation)되어야 한다.
- 생명주기 동기화: 상태 머신 객체는 전역 공간에 선언하는 것을 지양하고, 노드 클래스의 멤버 변수로서 스마트 포인터(
std::shared_ptr<yasmin::StateMachine>) 형태로 선언하여 메모리 누수를 방지하고 ROS 2 노드의 소멸과 함께 안전하게 메모리에서 해제되도록 설계한다. - 스레드 풀(Thread Pool) 할당: 상태 머신 내부의 비동기 동작(Action Client 대기, Timer 작동 등)을 원활하게 처리하기 위해, 노드 생성 시 다중 스레드 실행기(Multi-Threaded Executor)에 등록하고 적절한 콜백 그룹(Callback Group)을 매핑하여 YASMIN 코어 엔진에 스레드 자원을 할당한다.
8.3 상태(State) 및 전이(Transition) 토폴로지 구성
객체화된 상태 머신에 실제 로봇의 행동 논리를 부여하기 위해 노드의 초기화 단계(예: 생성자 내부 또는 생명주기 노드의 on_configure 콜백)에서 그래프 토폴로지를 구성한다.
- 상태 등록:
add_state()API를 호출하여 사전 정의된 단위 상태 객체들을 상태 머신 컨테이너에 적재하고, 각각의 상태를 식별할 수 있는 고유한 문자열 이름(State ID)을 부여한다. - 간선(Edge) 연결:
add_transition()API를 통해 현재 상태의 출력값(Outcome)과 전이될 대상 상태(Target State)를 매핑한다. - 진입점(Entry Point) 설정: 다수의 상태 중 실행 시 가장 먼저 제어권을 가질 시작 상태(Initial State)를 명시적으로 선언하여 제어 흐름의 기점을 정의한다.
8.4 초기화 무결성 및 논리적 오류 검증
런타임에 진입하기 전, 구성된 상태 머신의 논리적 결함을 컴파일 타임 또는 초기화 단계에서 선제적으로 포착하는 자가 진단(Self-Diagnostic) 과정이 수반된다.
- 도달 불가능성(Unreachability) 검사: 시작 상태로부터 그래프 탐색 알고리즘을 수행하여, 어떠한 전이 조건을 통해서도 도달할 수 없는 고립된 상태(Orphaned State)가 존재하는지 검증한다.
- 데드엔드(Dead-end) 및 전이 누락 탐지: 특정 상태가 선언한 출력값(Outcome)에 대응하는 전이 규칙이 누락되어 시스템이 예기치 않게 정지할 위험(Dead-end)을 검출한다.
- 위와 같은 논리적 무결성 위반이 탐지될 경우, YASMIN 내장 검증 모듈은 ROS 2 기본 로깅 시스템(
RCLCPP_ERROR또는RCLCPP_FATAL)을 통해 개발자에게 경고 메시지를 출력하고, 예외(Exception)를 발생시켜 불안전한 상태 머신의 구동을 원천 차단한다.
9. 기본 상태(Basic State) 클래스 상속 및 행동(Behavior) 정의
YASMIN 프레임워크에서 로봇의 개별 행동은 객체 지향 프로그래밍(OOP)의 상속(Inheritance) 및 다형성(Polymorphism) 원리를 기반으로 모델링된다. 사용자는 프레임워크가 제공하는 추상화된 기본 상태 클래스를 상속받아 로봇의 구체적인 작업 논리를 캡슐화한다. 본 장에서는 사용자 정의 상태(User-defined State)를 생성하기 위한 클래스 구조 및 행동 정의 명세(Specification)를 분석한다.
9.1 기본 상태 인터페이스의 구조적 정의
YASMIN의 코어 아키텍처는 C++의 yasmin::State 및 Python의 yasmin.State를 최상위 기본 상태 클래스로 제공한다.
- 이 기본 클래스는 상태 머신 엔진이 개별 상태의 생명주기(Lifecycle)를 관리하고 전이(Transition)를 평가하기 위해 필수적인 가상 함수(Virtual Function) 및 추상 메서드(Abstract Method) 인터페이스를 포함한다.
- 사용자는 이 클래스를 상속받는 하위 파생 클래스(Derived Class)를 정의함으로써, 코어 엔진의 내부 구동 로직을 수정하지 않고도 시스템에 새로운 행동 모듈을 안전하게 주입(Inject)할 수 있다.
9.2 생성자(Constructor)를 통한 출력값(Outcomes) 선언
사용자 정의 상태 클래스를 구현할 때 가장 먼저 수행해야 하는 절차는 생성자 내에서 해당 상태가 반환할 수 있는 논리적 결과인 ’출력값(Outcomes)’을 명시적으로 선언하는 것이다.
- 엄격한 계약(Strict Contract): 출력값의 선언은 해당 상태 모듈과 상태 머신 간의 논리적 계약을 의미한다. 기본적으로 상태의 생성자는 가능한 모든 출력값을 문자열의 배열 또는 리스트(예:
{"SUCCEEDED", "ABORTED", "TIMEOUT"}) 형태로 인자로 전달받아 초기화한다. - 전이 조건의 유효성 검증: 런타임 엔진은 선언되지 않은 임의의 출력값이 반환될 경우 이를 예외(Exception) 처리하여 시스템의 불안정한 상태 전이를 방지한다. 따라서 상태 내에서 발생할 수 있는 모든 분기(정상 완료, 연산 시간 초과, 하드웨어 오류 등)를 생성자에서 포괄적으로 정의하여야 한다.
9.3 execute() 메서드 오버라이딩 및 비즈니스 로직 캡슐화
상태의 실제 행동 논리(Behavior Logic)는 파생 클래스에서 execute() 메서드(Python의 경우 execute(self, blackboard))를 오버라이딩(Overriding)함으로써 구체화된다.
- 단일 책임 원칙(Single Responsibility Principle):
execute()메서드 내부는 로봇이 수행해야 할 단일하고 독립적인 작업(예: 모터 각도 제어, 비전 센서 데이터 1회 필터링 등)만을 수행하도록 구성된다. - 데이터 접근 및 제어 반환: 해당 메서드의 매개변수로는 전역 상태가 아닌, 해당 상태가 소속된 블랙보드(Blackboard) 객체의 참조(Reference)가 전달된다. 상태는 블랙보드의 API를 통해 필요한 데이터를 읽어오거나 연산 결과를 기록한다.
- 동기식 블로킹(Synchronous Blocking) 구조: 기본
execute()메서드는 내부 연산이 완전히 종료될 때까지 상태 머신의 메인 스레드 제어권을 반환하지 않는다. 비즈니스 로직 연산이 끝나면, 생성자에서 선언한 출력값 중 하나를 반환(Return)하여 엔진에 작업 완료를 통보하고 다음 상태로의 라우팅을 유도한다.
9.4 생명주기 훅(Lifecycle Hooks) 지원을 통한 자원 관리
복잡한 하드웨어 제어나 동적 메모리 관리가 요구되는 환경을 위해, YASMIN 상태 클래스는 execute() 이외에 추가적인 생명주기 훅(Hook) 메서드를 지원한다.
- 진입(Entry) 및 진출(Exit) 콜백: 상태가 활성화되어
execute()가 호출되기 직전에 실행되는 가상 메서드(예:on_enter())와, 상태가 종료되고 다른 상태로 전이되기 직전에 실행되는 가상 메서드(예:on_exit())를 선택적으로 재정의할 수 있다. - 자원의 안전한 할당과 해제: 이를 통해 상태 진입 시 로컬 타이머를 구동하거나 특정 ROS 2 토픽의 구독(Subscription)을 활성화하고, 상태 진출 시 해당 리소스를 안전하게 해제(Deallocation)하는 패턴을 구현한다. 이는 장기 체공 로봇 시스템에서 빈번하게 발생하는 메모리 누수(Memory Leak)나 통신 채널의 오염을 시스템 레벨에서 방지하는 핵심 기법이다.
10. 이벤트 구동형(Event-driven) 조건부 전이 규칙 및 엣지(Edge) 설정
순차적 종료 대기 및 동기식 폴링(Polling)에 의존하는 기초적인 상태 전이 방식은 센서 노이즈, 통신 지연, 장애물 출현 등 예측 불가능한 변수가 산재한 로봇 구동 환경에서 반응성(Responsiveness)의 한계를 지닌다. YASMIN은 이러한 실시간성(Real-time) 한계를 극복하기 위해, 외부 인터럽트나 데이터의 동적 변화에 즉각적으로 반응하여 실행 흐름을 변경하는 이벤트 구동형(Event-driven) 조건부 전이 아키텍처를 지원한다. 본 장에서는 런타임 이벤트와 조건식에 기반한 전이 규칙의 논리적 구조와 엣지(Edge) 설정 메커니즘을 규명한다.
10.1 조건부 전이(Conditional Transition)의 수학적 및 논리적 모델
일반적인 상태 머신에서 전이는 현재 상태의 실행 종료가 반환하는 출력값(Outcome)에 의해 정적으로 결정된다. 반면, 조건부 전이는 상태의 실행이 완료되기 전이더라도 특정 조건이 충족될 경우 강제적인 상태 분기를 유도하는 동적 라우팅(Dynamic Routing) 기법이다.
- 조건식 평가 모델: 조건부 전이 규칙 R은 논리적 매핑 함수 R: S \times E \times C \rightarrow S'로 모델링할 수 있다. 여기서 S는 현재 활성화된 상태, E는 외부 또는 내부에서 트리거된 이벤트(Event), C는 해당 시점의 시스템 상태나 블랙보드 데이터를 평가하는 논리적 조건식(Boolean Condition), S'는 전이될 대상 상태를 의미한다.
- 콜백(Callback) 기반 조건 검사기: 개발자는 C++의 람다(Lambda) 표현식이나 Python의 콜러블(Callable) 함수를 활용하여 사용자 정의 조건 검사기(Condition Checker)를 간선(Edge)에 주입할 수 있다. 이 검사기는 상태 머신의 스핀(Spin) 주기마다, 또는 특정 이벤트가 큐(Queue)에 적재될 때마다 호출되어 블랙보드의 변수 임계치 초과 여부 등을 연산하고 true 또는 false를 반환한다.
[구현 명세: 조건부 전이 등록 및 검사기 주입]
다음은 런타임 환경에서 람다(Lambda) 표현식을 활용하여 간선에 조건 검사기를 주입하는 C++ API의 실제 구현 명세이다.
// C++ 구현 예제: 람다식을 활용한 조건부 전이(Conditional Transition) 설정
sm->add_transition("MOVE_STATE", "SUCCEEDED", "NEXT_STATE",
[&blackboard]() -> bool {
// 블랙보드의 배터리 잔량이 20% 이상일 때만 전이 허용
return blackboard.get<int>("battery_level") >= 20;
}
);
10.2 엣지(Edge)의 구조적 설정 및 다중 라우팅(Multiple Routing)
상태 머신의 전체 그래프 토폴로지(Topology)는 개별 상태(노드)들을 연결하는 엣지(간선)들의 집합에 의해 완성된다. YASMIN API는 유연하고 복잡한 의사결정 트리를 구성하기 위한 다중 엣지 설정 기능을 제공한다.
- 명시적 간선 매핑: 그래프 구성 단계에서
add_transition(source_state, outcome, target_state)API를 호출하여 소스 상태의 특정 출력값과 타겟 상태를 강하게 결합한다. 이는 FSM의 결정론적 성질을 보장하는 기초 설정이다. - 복합 분기 처리: 하나의 상태가 ‘목표 도달(SUCCEEDED)’, ‘경로 탐색 실패(ABORTED)’, ‘배터리 부족(LOW_BATTERY)’ 등 3개 이상의 다중 출력값을 가지도록 설계된 경우, 각 출력값에 대응하는 독립적인 엣지 3개를 각각 다른 대상 상태(예: 대기 상태, 복구 상태, 충전소 이동 상태)로 매핑하여 복잡한 시나리오 분기를 구현한다.
10.3 ROS 2 비동기 이벤트와의 선점형(Preemptive) 통합
이벤트 구동형 아키텍처의 가장 큰 기술적 효용은 ROS 2의 퍼블리셔-서브스크라이버(Pub-Sub) 기반 비동기 통신 모델과 결합할 때 나타난다. YASMIN은 장기 실행 중인 상태(Long-running State)를 즉각적으로 중단시킬 수 있는 선점형 제어(Preemptive Control)를 지원한다.
- 비상 정지 및 인터럽트 처리: 하위 제어기 노드로부터
/emergency_stop토픽 메시지가 수신되는 즉시, 콜백 함수가 이를 이벤트로 감지하여 현재 활성화된 이동 제어 상태(Navigation State)의 내부 연산을 강제 중단(Cancel)시킨다. 이후 ‘CANCELED’ 엣지를 활성화하여 하드웨어 브레이크를 제어하는 안전 상태(Safe State)로 제어권을 즉각 이양한다. - 토픽 감시(Topic Monitor) 상태 래퍼: 일반적인 상태 위에 비동기 메시지 수신만을 모니터링하는 래퍼(Wrapper) 상태를 덧씌워, 지정된 토픽에서 특정 조건을 만족하는 데이터(예: 비전 센서의 타겟 인식)가 들어올 때만 ‘SUCCEEDED’ 이벤트를 발생시켜 다음 상태로 전이하도록 아키텍처를 추상화한다.
10.4 이벤트 큐(Event Queue)와 원자성(Atomicity) 보장 메커니즘
다수의 센서와 통신 채널이 병렬로 작동하는 ROS 2 환경에서는 여러 개의 전이 이벤트가 극히 짧은 시간 차를 두고 동시다발적으로 발생할 수 있다. 이는 예측 불가능한 상태 변이를 초래하는 경쟁 상태(Race Condition)를 유발한다.
- 스레드 안전한 대기열 처리: YASMIN은 발생한 이벤트를 즉각적으로 평가하는 대신, 스레드 안전성(Thread-safety)이 보장된 내부 이벤트 큐(Event Queue)에 순차적으로 적재한다.
- 임계 구역(Critical Section) 보호: 코어 엔진은 큐에 적재된 이벤트 중 가장 먼저 도달한 유효 조건을 평가하여 전이(Transition) 프로세스를 시작한다. 전이가 진행되어 이전 상태의
on_exit()훅과 다음 상태의on_enter()훅이 실행되는 임계 구역 내에서는 새로운 전이 이벤트 처리를 차단(Block)하거나 무시하여, 상태 교체 연산의 원자적(Atomic) 실행 무결성을 엄격하게 보장한다.
11. 복합 작업 수행을 위한 계층적/중첩 상태 머신(Nested State Machines) 설계 원리
단일 계층의 평면적(Flat) 유한 상태 머신은 로봇의 임무가 복잡해지고 인지-판단-제어 시나리오가 방대해질수록 기하급수적으로 증가하는 상태와 전이 간선으로 인해 이른바 ‘상태 폭발(State Explosion)’ 문제에 직면한다. YASMIN은 이러한 소프트웨어 복잡도를 통제하고 모듈성을 확보하기 위해 계층적 유한 상태 머신(Hierarchical Finite State Machine, HFSM) 아키텍처를 네이티브로 지원한다. 본 장에서는 복합 작업을 추상화하기 위한 중첩 상태 머신의 설계 원리, 시스템 내부 동작 메커니즘, 그리고 구현 명세를 기술한다.
11.1 계층적 추상화(Hierarchical Abstraction)의 논리적 구조
계층적 상태 머신은 특정 복합 상태(Composite State)의 내부를 또 다른 독립적인 하위 상태 머신(Sub-State Machine)으로 정의하는 구조적 패턴이다.
- 상태의 캡슐화: 로봇의 전체 임무(예: 물품 배송)를 최상위 레벨에서 ‘이동(Navigation)’, ‘조작(Manipulation)’, ’충전(Recharging)’과 같은 거시적 상태로 분할한다. 이후 ‘조작’ 상태의 내부를 다시 ‘객체 인식’, ‘그리퍼 접근’, ‘파지’, ’복귀’라는 미시적 상태들의 유기적인 네트워크로 하향식(Top-down) 설계하여 추상화 수준을 관리한다.
- 다형성(Polymorphism) 기반 설계: YASMIN 아키텍처에서
StateMachine클래스 자체는 기본State인터페이스를 상속받는다. 따라서 부모 상태 머신(Parent State Machine)의 관점에서는 자식 상태 머신(Child State Machine)의 내부 구현 복잡도와 무관하게 이를 단일한 상태 노드로 취급하며, 일반 상태와 동일한 방식의 API를 통해 중첩이 가능하다.
11.2 블랙보드 메모리 격리 및 명시적 리매핑(Remapping)
중첩된 상태 머신들이 전역 변수를 무분별하게 공유할 경우, 메모리 오염(Memory Corruption) 및 변수명 충돌 현상이 발생한다. 이를 방지하기 위해 YASMIN은 철저한 메모리 스코프(Scope) 격리 및 데이터 인터페이스 매핑 원칙을 적용한다.
- 독립적 블랙보드 인스턴스: 부모 상태 머신과 각 자식 상태 머신은 생성 시 물리적으로 분리된 독립적인 블랙보드 인스턴스를 할당받는다. 하위 서브 태스크 내부에서 생성된 임시 연산 변수들은 부모의 블랙보드 공간에 영향을 미치지 않고 자식의 생명주기 종료와 함께 소멸된다.
- 데이터 포트 리매핑 규칙: 부모와 자식 간에 필수적인 데이터(예: 부모가 지정한 목표 좌표, 자식이 연산한 최종 파지 성공 여부)를 교환하기 위해 명시적인 입력/출력 리매핑을 설정한다. 하위 상태 머신을 등록할 때, 부모 블랙보드의 특정 키(Key)를 자식 블랙보드의 특정 키로 연결하는 매핑 테이블을 제공하여, 허용된 데이터 채널만을 통한 제한적이고 안전한 정보 교환을 강제한다.
[구현 명세: 중첩 상태 머신의 등록 및 데이터 포트 리매핑]
부모 상태 머신에 자식 상태 머신을 단일 상태 노드로 등록하고, 두 계층 간의 블랙보드 변수를 안전하게 연결하는 C++ 및 Python API의 대칭적 구현 예시이다.
C++ API 기반 중첩 및 리매핑 구현:
#include <yasmin/state_machine.hpp>
#include <memory>
#include <map>
#include <string>
// 1. 자식 및 부모 상태 머신 인스턴스화
auto child_sm = std::make_shared<yasmin::StateMachine>(
std::vector<std::string>{"DONE", "FAILED"});
auto parent_sm = std::make_shared<yasmin::StateMachine>(
std::vector<std::string>{"SUCCESS", "ERROR"});
// (자식 상태 머신 내부의 상태 추가 로직 생략)
// 2. 리매핑 규칙 딕셔너리 정의 (부모 키 -> 자식 키)
std::map<std::string, std::string> remapping_rules = {
{"parent_target_pose", "child_local_pose"}
};
// 3. 자식 상태 머신을 부모의 단일 상태("SUB_TASK")로 캡슐화하여 등록
parent_sm->add_state(
"SUB_TASK",
child_sm,
{{"DONE", "FINAL_STATE"}, {"FAILED", "RECOVERY_STATE"}}, // 전이 규칙
remapping_rules // 데이터 포트 매핑
);
Python API 기반 중첩 및 리매핑 구현:
import yasmin
# 1. 자식 및 부모 상태 머신 인스턴스화
child_sm = yasmin.StateMachine(outcomes=['DONE', 'FAILED'])
parent_sm = yasmin.StateMachine(outcomes=['SUCCESS', 'ERROR'])
# (자식 상태 머신 내부의 상태 추가 로직 생략)
# 2 & 3. 자식 상태 머신을 부모의 단일 상태로 캡슐화하여 등록 및 블랙보드 리매핑 동시 수행
parent_sm.add_state(
'SUB_TASK',
child_sm,
transitions={'DONE': 'FINAL_STATE', 'FAILED': 'RECOVERY_STATE'},
remapping={'parent_target_pose': 'child_local_pose'} # 부모 키: 자식 키
)
11.3 자식 상태 머신의 실행 제어 및 제어권 반환 메커니즘
계층적 구조에서 실행 스레드의 제어권 이양은 코어 엔진의 엄격한 생명주기 관리에 따라 동기적으로 수행된다.
- 실행 위임(Delegation): 런타임 중 부모 상태 머신의 실행 커서가 중첩된 자식 상태 머신 노드에 도달하면, 부모는 자체적인 틱(Tick) 연산을 일시 중단(Suspend)하고 스레드 제어권을 자식 엔진으로 완전히 위임한다.
- 종료 상태 감지 및 결과 전파: 자식 상태 머신이 내부 전이를 거쳐 자체적인 종료 상태(Terminal State)에 도달하면, 자식은 최종 출력값(Final Outcome)을 산출하고 실행을 종료한다. 이 출력값은 부모 상태 머신으로 반환되어 부모 계층에서의 다음 전이(Transition)를 결정짓는 이벤트로 작용한다.
11.4 모듈성 향상 및 소프트웨어 재사용성 극대화 효과
HFSM 기반의 설계는 로봇 소프트웨어의 유지보수 및 확장성 측면에서 명확한 공학적 이점을 제공한다.
- 단위 검증(Unit Testing)의 용이성: 하위 상태 머신(예: ‘도어 개방 동작’ 서브 태스크)을 최상위 임무와 완전히 독립된 샌드박스(Sandbox) 환경에서 개별적으로 구동하고 디버깅할 수 있다.
- 기능 블록의 플러그 앤 플레이(Plug-and-Play): 한 번 논리적 무결성이 검증된 자식 상태 머신은 마치 라이브러리의 함수처럼 다양한 상위 시나리오에 수정 없이 반복적으로 삽입(Inject)하여 재사용할 수 있으며, 이는 다기종 로봇 플랫폼 간의 행동 알고리즘 이식성을 획기적으로 향상시킨다.
11.5 ## 13. 외부 ROS 2 통신 인터페이스(Topic, Service, Action)와의 동기적/비동기적 통합
ROS 2 기반의 분산 로봇 시스템에서 개별 하위 모듈(인지, 계획, 하드웨어 제어 등)은 토픽(Topic), 서비스(Service), 액션(Action)이라는 세 가지 표준 통신 인터페이스를 통해 상호작용한다. YASMIN 상태 머신이 로봇의 중앙 제어기 역할을 수행하기 위해서는 이러한 외부 비동기 통신 모델과 상태 머신의 순차적, 동기적 제어 흐름 간의 논리적 임피던스 불일치(Impedance Mismatch)를 해결해야 한다. 본 장에서는 YASMIN이 제공하는 외부 통신 통합 메커니즘 및 구체적인 구현 명세를 규명한다.
11.6 통신 모델과 제어 흐름의 추상화 원리
YASMIN은 ROS 2의 복잡한 콜백(Callback) 구조를 개발자가 직접 다루지 않도록 통신 전용 래퍼 상태(Wrapper State) 클래스들을 제공한다. 외부 네트워크 통신의 송수신 대기, 스레드 블로킹(Blocking), 예외 처리 로직이 단일 상태(State)의 내부 비즈니스 로직으로 캡슐화된다. 통신의 최종 결과(예: 서비스 응답 수신 성공, 통신 시간 초과 등)는 유한 상태 머신의 표준 출력값(Outcome)인 SUCCEEDED, ABORTED, TIMEOUT 등으로 평탄화(Flattening)되어 그래프 전이 규칙에 편입된다.
11.6.1 ### 13.2 토픽(Topic) 통신 통합: 퍼블리셔 및 서브스크라이버 상태
단방향 데이터 스트리밍에 사용되는 토픽 통신은 로봇의 센서 데이터 획득 및 연속적인 제어 명령 하달에 주로 활용된다.
- 퍼블리셔 상태(Publisher State): 상태가 활성화될 때 블랙보드(Blackboard)에 저장된 변수나 사전에 정의된 상수를 ROS 2 메시지 타입으로 직렬화(Serialization)하여 특정 토픽으로 발행(Publish)한다.
- 서브스크라이버 상태(Subscriber State): 특정 토픽의 수신 대기열을 모니터링한다. 수신된 메시지 데이터를 파싱하여 블랙보드에 기록하며, 사용자가 주입한 조건 검사기(Condition Checker)를 통해 메시지 페이로드(Payload)가 특정 임계값을 만족할 경우 이벤트를 발생시켜 비동기적인 상태 전이를 유도한다.
[구현 명세: 서브스크라이버 상태 기반 데이터 수신]
import yasmin_ros
from std_msgs.msg import String
class SensorMonitorState(yasmin_ros.SubscriberState):
def __init__(self):
super().__init__(
TopicType=String,
topic_name='/sensor_data',
outcomes=['DATA_RECEIVED', 'TIMEOUT']
)
def check_msg(self, msg, blackboard):
# 수신된 메시지를 평가하고 블랙보드에 기록
if msg.data != "":
blackboard.set('latest_sensor_data', msg.data)
return 'DATA_RECEIVED'
return None # 전이 조건을 만족하지 않을 경우 상태 유지
11.7 서비스(Service) 통신 통합: 동기적/비동기적 요청-응답
서비스는 단발성 연산 요구나 특정 모듈의 파라미터 변경을 위한 요청-응답(Request-Response) 구조를 갖는다. YASMIN의 ServiceClientState는 호출 방식에 따라 두 가지 동기화 모델을 지원한다.
- 동기식 블로킹(Synchronous Blocking) 호출: 서비스 요청을 전송한 후, 응답이 도달할 때까지 해당 상태의
execute()스레드를 블로킹한다. 이는 연산 시간이 매우 짧고 결과가 즉시 반환되는 서비스에 적합하며, 제어 흐름의 직관성을 보장한다. - 비동기식 퓨처(Asynchronous Future) 기반 호출: 서비스 요청 전송 후 즉시 제어권을 YASMIN 메인 엔진으로 반환한다. 내부적으로 ROS 2의 완료 콜백(Completion Callback)을 활용하여 응답을 대기하며, 응답 수신 시 이벤트 큐를 통해 상태 완료를 통보함으로써 시스템 자원 점유를 최소화한다.
11.8 액션(Action) 통신 통합: 장기 실행 작업(Long-running Task)의 선점형 제어
자율 주행(Nav2)이나 매니퓰레이션(MoveIt2)과 같이 수 초에서 수십 분이 소요되는 복합 작업은 피드백(Feedback)과 작업 취소(Cancel)가 가능한 액션(Action) 인터페이스를 요구한다. ActionClientState는 이러한 장기 실행 작업의 전 주기를 상태 머신 내에 통합한다.
- 목표(Goal) 전송 및 피드백 처리: 상태 진입 시 블랙보드의 데이터를 목표 메시지로 구성하여 액션 서버에 전송한다. 작업 진행 중 수신되는 피드백은 내부 콜백을 통해 처리되며 블랙보드를 갱신한다.
- 선점(Preemption) 및 목표 취소(Cancel Goal): 상위 상태 머신에서 비상 상황이 감지되어 현재의 액션 상태를 강제 종료해야 할 경우, YASMIN 코어는 상태 모듈에 중단 시그널을 보낸다. 상태는 내부적으로 액션 서버에
cancel_goal()요청을 전송하여 로봇의 물리적 구동을 안전하게 정지시킨다.
[구현 명세: 액션 클라이언트 상태 캡슐화 및 목표 주입]
import yasmin_ros
from nav2_msgs.action import NavigateToPose
class MoveToTargetState(yasmin_ros.ActionClientState):
def __init__(self):
super().__init__(
ActionType=NavigateToPose,
action_name='/navigate_to_pose',
outcomes=['SUCCEEDED', 'ABORTED', 'CANCELED']
)
def create_goal(self, blackboard):
# 블랙보드 데이터를 기반으로 액션 목표(Goal) 생성
goal = NavigateToPose.Goal()
if blackboard.has('target_waypoint'):
goal.pose = blackboard.get('target_waypoint')
return goal
11.9 스레드 풀(Thread Pool) 및 콜백 그룹(Callback Group) 관리 메커니즘
동시다발적인 외부 통신을 상태 머신과 결합할 때 빈번하게 발생하는 기술적 오류인 교착 상태(Deadlock)를 회피하기 위해 엄격한 스레드 분리 아키텍처가 적용된다.
- 상호 배타적 콜백 그룹 활용: YASMIN 노드는 ROS 2의 다중 스레드 실행기(Multi-Threaded Executor) 하에서 구동되며, 통신 래퍼 상태 내부의 토픽, 서비스, 액션 콜백 함수들은 각각 독립된 상호 배타적 콜백 그룹(Mutually Exclusive Callback Group)에 할당된다.
- 실행과 통신의 분리: 상태 머신의 메인 연산을 담당하는 스레드와 ROS 2 외부 통신 메시지를 수신하는 스핀(Spin) 스레드가 물리적으로 분리되어 동작한다. 데이터 교환은 동기화 락(Mutex Lock)이 적용된 블랙보드와 이벤트 큐를 통해서만 이루어지며, 이를 통해 상태 전이의 결정론성을 수호한다.
12. YASMIN Viewer의 데이터 통신 원리 및 시각화 렌더링 방식
로봇의 자율 행동 알고리즘이 복잡해짐에 따라, 내부의 제어 흐름과 데이터 상태를 개발자가 직관적으로 추적하고 검증할 수 있는 가시성(Observability) 확보가 필수적이다. YASMIN은 로봇의 메인 연산 주기(Control Loop)에 부하를 주지 않으면서 실시간으로 상태 전이 과정을 시각화하는 전용 도구인 YASMIN Viewer를 제공한다. 본 장에서는 코어 엔진과 Viewer 간의 데이터 통신 프로토콜 및 그래픽 렌더링 아키텍처를 분석한다.
12.1 실시간 상태 데이터 브로드캐스팅(Broadcasting) 아키텍처
YASMIN 코어 엔진은 실행 중인 상태 머신의 토폴로지(Topology)와 런타임 정보를 외부로 전송하기 위해 내부적으로 시각화 전용 ROS 2 퍼블리셔(Publisher)를 인스턴스화한다.
- 직렬화(Serialization) 및 페이로드 구성: 초기화 단계에서 전체 상태 그래프의 정적 구조(상태 이름, 부모-자식 계층 관계, 정의된 전이 규칙)를 추출한다. 이후 런타임에 상태 전이가 발생하거나 블랙보드 데이터가 갱신될 때마다, 현재 활성 상태(Active State)와 블랙보드의 동적 데이터를 문자열 기반의 JSON(JavaScript Object Notation) 형식으로 직렬화하여 페이로드(Payload)를 구성한다.
- 비동기 토픽 발행: 구성된 상태 정보 메시지는 지정된 전용 디버깅 토픽(예:
/yasmin/state_machine_info)을 통해 주기적, 혹은 이벤트 기반으로 발행(Publish)된다. 이러한 단방향 브로드캐스팅 방식은 뷰어가 연결되어 있지 않은 런타임 상황에서도 코어 제어 로직의 실행 속도나 결정론성에 어떠한 간섭도 일으키지 않는다.
12.2 클라이언트-서버 웹소켓(WebSocket) 통신 브릿지
YASMIN Viewer는 운영체제나 플랫폼에 종속되지 않는 시각화 환경을 제공하기 위해 웹 기반 기술 스택(Web-based Tech Stack)을 채택하고 있으며, 이를 위해 중간 브릿지 통신 계층을 운용한다.
- ROS-Web 브릿지 연동: Viewer의 백엔드(Backend) 서버 또는
rosbridge_suite와 같은 미들웨어가 ROS 2 네트워크 상에서 디버깅 토픽을 구독(Subscribe)한다. - 프로토콜 변환 및 실시간 스트리밍: 수신된 ROS 2 메시지는 웹소켓(WebSocket) 프로토콜로 변환되어 프론트엔드(Frontend) 웹 브라우저로 비동기 송신된다. 이 브릿지 통신 구조는 물리적인 로봇 하드웨어(호스트)와 디버깅을 수행하는 개발자 PC(클라이언트)가 IP 네트워크로 분리된 원격(Remote) 환경에서도 지연 없는 실시간 모니터링을 가능하게 한다.
12.3 방향성 그래프(Directed Graph) 시각화 및 동적 렌더링 방식
Viewer 프론트엔드는 수신된 상태 머신의 구조 데이터를 파싱(Parsing)하여 시각적 객체로 변환하는 렌더링 엔진(예: D3.js, Cytoscape.js 기반)을 탑재하고 있다.
- 그래프 토폴로지 투사: 파싱된 데이터는 노드(Node, 상태)와 링크(Link, 전이 및 간선)로 구성된 방향성 그래프(Directed Graph) 자료구조로 메모리에 적재된다. 렌더링 엔진은 계층적 레이아웃(Hierarchical Layout) 알고리즘을 적용하여 화면에 중첩된 부모-자식 상태 머신의 다층 구조를 시각적으로 투사한다.
- 동적 렌더링 및 추적: 로봇이 임무를 수행함에 따라 수신되는 활성 상태 업데이트 정보에 기반하여, 현재 제어권을 가진 노드에 시각적 강조(Highlighting) 및 색상 변환 처리를 동적으로 적용한다. 이를 통해 개발자는 전체 시나리오 중 현재 로봇이 어느 단계에 머물러 있는지를 직관적으로 파악할 수 있다.
12.4 런타임 블랙보드 모니터링 및 상태 추적 뷰(View)
그래픽 렌더링뿐만 아니라, 시스템 내부의 데이터 파이프라인 무결성을 검증하기 위한 부가적인 인터페이스가 동기화되어 렌더링된다.
- 블랙보드 인스펙터(Inspector): 그래픽 패널 측면에 별도의 UI 컴포넌트로 구현되며, 현재 활성화된 상태 머신의 블랙보드 키-값(Key-Value) 테이블을 실시간으로 출력한다. 센서 좌표, 임계치 플래그, 타이머 카운트 등의 변동 내역이 지속적으로 갱신되어 데이터 누락이나 오염 여부를 즉각적으로 추적할 수 있다.
- 로그 및 전이 히스토리: 상태가 전이된 이력(과거 상태 -> 출력값 -> 현재 상태)을 타임스탬프(Timestamp)와 함께 스택(Stack) 형태로 기록하여 표시한다. 이는 예기치 않은 오류나 무한 루프(Infinite Loop) 발생 시, 어느 시점의 어떤 조건에 의해 논리적 결함이 발생했는지 역추적하는 사후 디버깅(Post-mortem Debugging)의 핵심 근거 자료로 활용된다.
13. 실시간 상태 전이 그래프 추적 및 내부 블랙보드 변수 모니터링
자율 동작 시스템의 런타임 무결성을 검증하고 논리적 결함을 식별하기 위해서는 실행 중인 상태 머신의 동적 변화를 실시간으로 관측할 수 있는 메커니즘이 요구된다. YASMIN은 코어 제어 루프의 성능 저하를 최소화하면서 상태 전이 궤적과 블랙보드 메모리 상태를 추적하는 인트로스펙션(Introspection) 아키텍처를 내장하고 있다. 본 장에서는 시스템 내부 상태의 실시간 추적 및 모니터링 기술을 분석한다.
13.1 런타임 상태 궤적(Trajectory)의 훅(Hook) 기반 추적 메커니즘
YASMIN 상태 머신 코어는 그래프 횡단(Graph Traversal) 과정에서 발생하는 모든 이벤트(상태 진입, 실행, 이탈, 전이 조건 만족 등)를 포착하기 위해 내부 생명주기 훅(Lifecycle Hook)을 활용한다.
- 이벤트 타임스탬핑(Timestamping): 전이 규칙이 트리거되어 새로운 상태로 제어권이 넘어가는 즉시, 엔진은 운영체제의 고정밀 타이머(High-Resolution Timer)를 호출하여 해당 이벤트의 발생 시간을 마이크로초(µs) 단위로 기록한다.
- 궤적 로깅(Trajectory Logging): ’이전 상태(Source) -> 발생한 출력값(Outcome) -> 현재 활성 상태(Target)’로 이어지는 단방향 전이 이력을 스택(Stack) 또는 원형 큐(Circular Queue) 형태의 내부 메모리에 지속적으로 적재한다. 이를 통해 복잡한 중첩 상태 머신 내부에서도 현재 제어 위치의 논리적 경로를 실시간으로 추적할 수 있다.
13.2 블랙보드 메모리 스냅샷(Snapshot) 및 데이터 직렬화
블랙보드는 다양한 자료형을 은닉하여 저장하는 동적 메모리 공간이므로, 외부에서 이를 모니터링하기 위해서는 메모리 주소 참조가 아닌 데이터의 안전한 추출과 변환 과정이 필수적이다.
- 타입 검사 및 직렬화(Serialization): 모니터링 모듈이 블랙보드에 접근할 때, 각 키(Key)에 저장된 데이터의 실제 타입 정보(
type_info)를 동적으로 검사한다. 정수, 실수, 문자열과 같은 기본 C++/Python 자료형은 물론, 사전 등록된 특정 ROS 2 메시지 타입에 대해서도 이를 사람이 읽을 수 있는 JSON(JavaScript Object Notation) 또는 딕셔너리 포맷으로 직렬화한다. - 비동기 스냅샷 생성: 상태
execute()연산이 진행 중인 도중 데이터가 변경되어 발생하는 데이터 경합(Data Race)을 방지하기 위해, 상태 간 전이가 발생하는 찰나의 임계 구역(Critical Section) 또는 읽기-쓰기 잠금(Read-Write Lock)이 확보된 시점에 전체 블랙보드의 스냅샷(Snapshot)을 일괄 생성한다.
[구현 명세: 블랙보드 데이터의 JSON 직렬화 스냅샷 예시]
{
"timestamp": 1679823451.123456,
"state_machine_id": "manipulation_sm",
"active_state": "APPROACH_OBJECT",
"blackboard_snapshot": {
"target_pose": {"x": 1.2, "y": 0.5, "z": 0.3},
"gripper_force": 15.5,
"is_object_detected": true
}
}
13.3 성능 간섭 배제를 위한 비동기 브로드캐스팅(Asynchronous Broadcasting)
실시간 로봇 제어 시스템에서 디버깅 및 모니터링 연산이 메인 제어 루프(Control Loop)의 주파수를 저하시키는 현상(Observer Effect)을 방지해야 한다.
- 모니터링 스레드 분리: 추적된 상태 궤적 데이터와 블랙보드 스냅샷 정보는 제어 로직을 담당하는 메인 스레드와 완전히 분리된 독립적인 백그라운드 스레드로 전달된다.
- 전용 진단 토픽(Diagnostic Topic) 활용: 백그라운드 스레드는 ROS 2의 퍼블리셔(Publisher)를 통해 주기적(예: 10Hz) 또는 이벤트 구동 방식(전이 발생 시점)으로 모니터링 데이터를 외부 토픽으로 발행(Publish)한다. 이 과정에서 Best-Effort QoS(Quality of Service) 프로토콜을 적용하여, 네트워크 대역폭 부족 시 모니터링 패킷이 드롭(Drop)되더라도 코어 상태 머신의 구동에는 어떠한 지연도 유발하지 않도록 설계되었다.
13.4 ROS 2 CLI 기반 인트로스펙션(Introspection) 인터페이스
그래픽 기반의 Viewer 외에도, 컴퓨팅 자원이 극도로 제한된 헤드리스(Headless) 환경이나 터미널 환경의 개발자를 위한 명령어 인터페이스를 제공한다.
- 동적 질의(Dynamic Query) 처리: YASMIN은 노드 내부에 상태 머신 진단을 위한 ROS 2 서비스(Service) 서버를 개설한다. 개발자는 터미널에서 특정 서비스 호출을 통해 현재 실행 중인 상태 머신의 전체 계층 구조(Tree)를 출력하거나, 블랙보드 내 특정 키(Key)의 현재 값을 선택적으로 조회할 수 있다.
- 상태 주입(State Injection) 및 강제 전이(Forced Transition): 디버깅 목적에 한하여, 인트로스펙션 인터페이스를 통해 임의의 출력값(Outcome)을 엔진에 주입하여 강제적인 엣지 전이를 유발하거나, 블랙보드 변수를 외부에서 덮어쓰기(Overwrite)하여 엣지 케이스(Edge Case) 시나리오에서의 로봇 반응을 즉각적으로 테스트할 수 있는 제어 권한을 제공한다.
[구현 명세: ROS 2 CLI를 활용한 동적 질의 및 강제 전이 제어 예시]
# 1. 런타임 중 특정 상태 머신의 내부 블랙보드 변수(배터리 잔량) 동적 조회
ros2 service call /yasmin/get_blackboard_variable yasmin_msgs/srv/GetBlackboard "{state_machine_id: 'nav_sm', key: 'battery_level'}"
# 2. 임의의 출력값 주입을 통한 강제 전이 유발 (장애물 탐지 복구 시나리오 테스트 목적)
ros2 service call /yasmin/inject_outcome yasmin_msgs/srv/InjectOutcome "{state_machine_id: 'nav_sm', state_name: 'MOVE_TO_GOAL', outcome: 'OBSTACLE_DETECTED'}"
14. ROS 2 기본 로거(Logger)와 연동된 상태 추적 메커니즘 및 오류 진단
로봇 소프트웨어의 안정성을 보장하고 런타임 디버깅 효율을 극대화하기 위해, YASMIN은 독자적인 텍스트 출력 계층을 구축하는 대신 ROS 2의 표준 로깅(Logging) 인프라스트럭처와 심층적으로 통합된 추적 및 진단 메커니즘을 제공한다. 본 장에서는 YASMIN 코어 엔진이 시스템의 실행 문맥(Context)을 기록하고 논리적 오류를 진단하는 기술적 연동 구조를 규명한다.
14.1 표준 로깅 인터페이스(Standard Logging Interface)의 네이티브 통합
YASMIN 상태 머신은 운영체제 수준의 표준 출력(std::cout 또는 print()) 사용을 철저히 배제한다. 대신, 상태 머신이 구동되는 호스트 ROS 2 노드의 rclcpp::Logger (C++ 환경) 또는 Node.get_logger() (Python 환경) 객체의 참조(Reference)를 내부 엔진으로 전달받아 로깅을 수행한다.
- 이를 통해 시스템 관리자는 ROS 2의 기본 심각도 레벨(Severity Level: DEBUG, INFO, WARN, ERROR, FATAL)을 런타임에 동적으로 조절하여, 불필요한 연산 부하 없이 원하는 해상도의 상태 머신 실행 로그만을 선택적으로 필터링할 수 있다.
14.2 문맥 인지형(Context-Aware) 상태 전이 추적
분산 환경에서 수많은 노드가 동시에 로그를 쏟아내는 가운데 상태 머신의 흐름을 식별하기 위해, YASMIN은 정형화된 문맥 인지형 로그 메시지를 자동 생성한다.
- 생명주기 기반 로깅: 각 단위 상태(State)의 진입(
on_enter), 메인 로직 실행(execute), 종료(on_exit) 훅(Hook)이 호출될 때마다 코어 엔진은 추적 로그를 발생시킨다. - 식별자 캡슐화: 발생한 로그 메시지 페이로드에는 해당 로그를 트리거한 ‘최상위 상태 머신 ID’, ‘현재 활성 상태의 이름’, 그리고 전이를 유발한 ’출력값(Outcome)’이 캡슐화되어 출력된다. 이는 복잡한 중첩 상태 머신(Nested State Machine) 아키텍처 내부에서도 현재 제어권의 정확한 논리적 위치를 추적할 수 있는 가시성을 제공한다.
14.3 예외(Exception) 감지 및 치명적 오류(Fatal Error) 진단
상태 머신의 결정론적(Deterministic) 특성을 위협하는 논리적 결함은 코어 엔진의 내부 예외 처리기(Exception Handler)에 의해 즉각적으로 감지되어 로깅 시스템으로 전달된다.
- 타입 불일치 및 메모리 위반 감지: 블랙보드(Blackboard)에서 데이터를 읽어올 때 요청한 자료형(Type)과 실제 적재된 자료형이 불일치할 경우(
std::bad_any_cast등), 엔진은 이를 WARN 또는 ERROR 레벨로 즉시 보고하여 데이터 오염으로 인한 제어 실패를 예방한다. - 침묵적 실패(Silent Failure) 방지: 현재 상태가 사전에 정의되지 않은 미등록 출력값(Unknown Outcome)을 반환하거나, 그래프 토폴로지상 연결된 간선(Edge)이 존재하지 않는 데드엔드(Dead-end) 상황에 직면할 경우, 상태 머신은 임의의 동작을 멈추고
FATAL로그와 함께 현재 콜스택(Call Stack) 정보를 출력한 후 시스템 제어권을 안전하게 반환(Abort)한다.
14.4 분산 시스템 환경에서의 로그 집계(Log Aggregation) 및 사후 분석
ROS 2 아키텍처의 특성상 rclcpp 및 rclpy를 통해 발생한 모든 로그는 로컬 콘솔뿐만 아니라 전역 /rosout 토픽을 통해 DDS(Data Distribution Service) 네트워크 상에 브로드캐스팅(Broadcasting)된다.
- 시간 동기화(Time-synchronized) 진단: YASMIN의 런타임 로그 역시
/rosout토픽으로 일괄 전송되므로, 다수의 이기종 컴퓨팅 보드(예: 내비게이션 PC, 비전 처리 PC)에 분산 탑재된 여러 상태 머신의 실행 이력을 Foxglove Studio나 ELK(Elasticsearch, Logstash, Kibana) 스택과 같은 중앙 관제 도구에서 시스템 노드 시간 기준으로 정렬하여 통합 분석할 수 있다. - 이는 다중 로봇 시스템(Multi-Robot System)에서 로봇 간 협업 임무 실패 시, 어느 로봇의 어느 상태 모듈에서 병목이나 통신 지연이 발생했는지 원인을 규명하는 사후 부검(Post-mortem) 진단의 핵심 데이터로 기능한다.
15. 인지 로봇 아키텍처(예: MERLIN2)에서의 YASMIN 탑재 및 운용 사례
현대의 로봇 시스템은 단순한 반복 작업을 넘어, 비정형 환경을 이해하고 자율적으로 의사결정을 내리는 인지 로봇 아키텍처(Cognitive Robot Architecture)로 진화하고 있다. YASMIN은 이러한 하이브리드 인지 아키텍처 내에서 절차적 추론(Procedural Reasoning)과 작업 실행(Task Execution)을 담당하는 핵심 미들웨어로 기능한다. 본 장에서는 MERLIN2(Mobile Entity for Research in Local Environments)와 같은 인지 로봇 플랫폼에 YASMIN이 통합되어 운용되는 기술적 사례를 분석한다.
15.1 하이브리드 인지 아키텍처 내 YASMIN의 논리적 계층(Layer)
인지 로봇은 일반적으로 반응형 제어(Reactive Control) 계층, 심볼릭 추론 및 계획(Deliberative Planning) 계층, 그리고 이 둘을 중재하는 실행(Executive) 계층의 3계층 아키텍처(Three-Tier Architecture)를 채택한다.
- 실행 계층(Executive Layer)의 중앙 통제소: YASMIN은 이 중 실행 계층에 탑재된다. 상위의 작업 계획기(Task Planner, 예: PDDL 기반 심볼릭 플래너)가 생성한 거시적인 계획(Symbolic Plan)을 입력받아, 이를 로봇이 실행할 수 있는 물리적이고 이산적인 행동 상태(Action State)들의 시퀀스로 변환한다.
- 반응형 하위 시스템과의 비동기 중재: 하위의 반응형 제어기(예: 동적 장애물 회피, 모터 PID 제어)와는 ROS 2 액션(Action) 및 토픽(Topic) 인터페이스를 통해 통신하며, 하드웨어의 실시간 피드백을 상위 인지 모델로 전달하는 브릿지 역할을 수행한다.
15.2 MERLIN2 플랫폼의 데이터 파이프라인 및 블랙보드 연동
MERLIN2와 같은 인지 로봇은 다중 센서(RGB-D 카메라, LiDAR 등) 융합을 통해 환경에 대한 의미론적(Semantic) 지식을 생성한다. YASMIN은 이 지식 베이스(Knowledge Base)와 행동 제어를 통합형 블랙보드(Blackboard) 패턴을 통해 결합한다.
- 인지 데이터의 직렬화 및 적재: 로봇의 비전 시스템이 특정 객체(예: ‘조작 대상 물체’)를 인식하면, 해당 객체의 3D 좌표와 속성 정보가 ROS 2 토픽을 통해 발행된다. YASMIN 내의 사용자 정의
PerceptionState는 이 데이터를 수신하여 블랙보드의 전역 변수로 직렬화(Serialization)한다. - 컨텍스트 인지형(Context-Aware) 매개변수 주입: 블랙보드에 적재된 객체 좌표 및 파지점(Grasp Pose) 데이터는 후속 매니퓰레이션 상태(
ActionClientState기반)로 직접 전달되어, 매니퓰레이터의 궤적 계획(Trajectory Planning)을 위한 목표 매개변수로 주입(Injection)된다. 이를 통해 인지와 제어 모듈 간의 강한 코드 결합 없이 데이터 파이프라인이 완성된다.
15.3 인지적 오류 복구(Cognitive Error Recovery) 시나리오 모델링
비정형 환경에서는 물체의 이동, 조도 변화, 파지 실패 등 예기치 않은 오류가 빈번하게 발생한다. YASMIN의 이벤트 구동형 분기 및 계층적 상태 머신(HFSM) 구조는 이러한 오류에 대한 로봇의 인지적 복원력(Resilience)을 보장한다.
- 폴백(Fallback) 상태 네트워크 구성: 물체 집기(Pick) 상태가 ’ABORTED’를 반환할 경우, 즉시 시스템을 종료하는 대신 ‘시점 변경(Change Viewpoint)’, ‘객체 재탐색(Re-detect Object)’, ‘접근 경로 재계획(Re-plan Approach)’ 등 사전에 정의된 복구 계층(Recovery Hierarchy) 하위 상태 머신으로 제어권을 이양한다.
- 동적 전이 및 작업 재시도: 복구 상태에서 인지 모듈이 객체를 성공적으로 재인식하여 블랙보드를 업데이트하면, 조건부 엣지(Edge)가 이를 평가하여 다시 본래의 물체 집기 상태로 제어권을 라우팅한다. 이는 하드코드된 예외 처리(Hard-coded Exception Handling)를 배제하고, 수학적으로 검증 가능한 결정론적 재시도 루프(Retry Loop)를 형성한다.
15.4 인간-로봇 상호작용(HRI) 시나리오에서의 비동기 제어
인지 로봇은 자율 작업 도중 인간의 개입(Intervention)이나 비동기적인 명령을 수용하고 실행 흐름을 변경할 수 있어야 한다.
- 이벤트 기반 선점형(Preemptive) 태스크 스위칭: YASMIN은 메인 작업을 수행하는 도중, 인간의 인터럽트(예: 비상 정지 또는 새로운 목적지 지시 토픽 수신)를 즉각적으로 감지한다. 유효한 명령이 감지되면 이벤트 큐(Event Queue)에 고순위 인터럽트가 발생한다.
- 제어권의 안전한 이양: 엔진은 현재 실행 중인 장기 작업(예: Nav2 기반 이동 액션)에 안전한 취소 요청(Cancel Goal)을 전송하여 로봇의 물리적 구동을 정지시킨 후, 인간의 명령에 대응하는 새로운 상호작용 상태(Interaction State) 분기로 즉각적인 제어권 전환(Context Switching)을 수행한다.
16. 자율 주행(Navigation) 및 매니퓰레이션(Manipulation) 시나리오의 상태 머신 모델링
자율 주행과 매니퓰레이션은 현대 로봇 시스템의 핵심 임무이며, 각각 연속적인 경로 추종과 고자유도 관절 제어를 수반하는 복잡한 절차적 작업이다. YASMIN은 이러한 이기종 제어 스택(예: ROS 2 Nav2, MoveIt2)을 일관된 논리적 흐름으로 통합하고 제어하는 모델링 방법론을 제공한다. 본 장에서는 대표적인 로봇 임무 시나리오에 대한 상태 머신 모델링 아키텍처 및 구현 원리를 기술한다.
16.1 자율 주행(Navigation) 시나리오 모델링 (Nav2 연동)
자율 주행은 동적 환경에서 목적지까지의 경로를 계획하고 이동하는 장기 실행 작업(Long-running Task)이므로, 비동기 피드백과 예외 처리가 가능한 액션(Action) 통신 기반의 모델링이 필수적이다.
- 액션 클라이언트 상태(Action Client State) 매핑: ROS 2 Nav2 스택의
MapsToPose액션을 YASMIN의ActionClientState로 캡슐화한다. 상태가 활성화되면 블랙보드에 저장된 목표 2D/3D 좌표(Pose)를 액션 목표(Goal)로 변환하여 전송한다. - 실시간 피드백 처리: 이동 중 발생하는 주기적인 피드백(예: 목표 지점까지의 남은 거리, 현재 로봇의 추정 좌표)은 상태 내부의 콜백을 통해 수신되며, 필요에 따라 블랙보드의 지정된 변수를 갱신하여 상위 모니터링 노드나 UI가 로봇의 진행 상황을 관측할 수 있도록 한다.
- 복구 행동(Recovery Behavior) 분기: 경로 상에 예기치 않은 동적 장애물이 출현하여 Nav2 스택이 실패(ABORTED)를 반환할 경우, YASMIN 그래프 토폴로지는 이를 즉각 감지하여 사전에 정의된 복구 상태(예:
ClearCostmap,Spin,BackUp상태)로 제어권을 라우팅(Routing)한다. 복구 상태가 성공적으로 완료되면 원래의 이동 상태로 복귀하는 조건부 루프(Loop)를 형성하여 자율 주행의 신뢰성을 확보한다.
16.2 매니퓰레이션(Manipulation) 시나리오 모델링 (MoveIt2 연동)
로봇 팔(Manipulator)을 이용한 파지(Grasp) 및 조작 임무는 정밀한 궤적 연산과 다단계 하드웨어 제어 시퀀스를 요구하므로, 임무를 미시적인 단위 상태들로 분할하여 직렬화하는 모델링이 필요하다.
- 이산적 상태 시퀀스 분해: 전형적인 ‘물체 집고 놓기(Pick and Place)’ 임무는
접근(Approach) -> 파지(Grasp/Close Gripper) -> 후퇴(Retreat) -> 이동(Move to Target) -> 배치(Place/Open Gripper)의 순차적인 상태 체인(State Chain)으로 분할된다. - 인지-제어 데이터 파이프라인 연동: 비전 센서 노드가 발행한 목표 객체의 6D 자세(Pose) 정보는
SubscriberState를 통해 수신되어 블랙보드에 기록된다. 후속 상태인 역기구학(Inverse Kinematics) 연산 상태는 블랙보드에서 이 Pose 데이터를 읽어와 엔드 이펙터(End-effector)의 목표 위치로 설정한다. - 궤적 계획 및 실행의 분리: 매니퓰레이션의 안전성을 위해 궤적을 계획(Plan)하는 상태와 계획된 궤적을 실제 하드웨어에 실행(Execute)하는 상태를 분리하여 모델링한다. 계획 상태에서 역기구학 연산 실패(IK Failure)나 충돌 예상(Collision Detected) 결과가 도달하면, 하드웨어 구동을 생략하고 작업 실패 분기로 안전하게 전이한다.
16.3 모바일 매니퓰레이션(Mobile Manipulation) 복합 시나리오 모델링
자율 주행 로봇(AMR) 위에 매니퓰레이터가 탑재된 형태의 모바일 매니퓰레이터 시스템은 탐색, 이동, 인지, 조작이 결합된 이기종 다중 작업(Heterogeneous Multi-Task)을 수행해야 한다.
- 계층적 상태 머신(HFSM) 통합 적용: 복잡도 통제를 위해 ’내비게이션 상태 머신’과 ’매니퓰레이션 상태 머신’을 각각 독립된 자식 상태 머신(Child State Machine)으로 구성한다. 최상위 부모 상태 머신(Parent State Machine)은 ’물품 이송(Fetch and Deliver)’이라는 거시적 시나리오를 관장하며, 주행 상태 머신이 목적지 도달(SUCCEEDED)을 반환하면 조작 상태 머신으로 제어권을 순차적으로 이양한다.
- 전역 블랙보드를 통한 스택 간 변수 교환: 자율 주행 스택(Nav2)과 매니퓰레이션 스택(MoveIt2)은 기본적으로 서로의 제어 공간을 인지하지 못한다. YASMIN은 최상위 계층의 전역 블랙보드를 매개체로 활용하여, 주행 완료 후 획득한 로봇 베이스의 최종 위치 오차 데이터를 매니퓰레이션 상태 머신으로 전달함으로써, 물체 파지를 위한 조인트(Joint) 궤적 보상 연산에 활용하도록 한다.
17. 노드 간 통신 부하(Overhead) 및 상태 전이 지연 시간(Latency) 성능 평가
실시간성(Real-time)이 요구되는 로봇 제어 시스템에서 유한 상태 머신(FSM) 모듈이 유발하는 컴퓨팅 자원 점유율과 반응 지연은 전체 시스템의 안정성을 결정짓는 핵심 지표이다. YASMIN은 ROS 2 환경에 특화된 경량 아키텍처를 채택함으로써 이러한 성능 지표를 최적화하였다. 본 장에서는 YASMIN의 노드 간 통신 부하 및 상태 전이 지연 시간에 대한 학술적 성능 평가 원리와 아키텍처적 이점을 분석한다.
17.1 성능 평가 지표의 학술적 정의
상태 머신 프레임워크의 성능 평가는 주로 다음의 두 가지 정량적 지표를 기준으로 수행된다.
- 상태 전이 지연 시간(Transition Latency): 특정 전이 조건(Trigger Event)이 발생하거나 활성 상태의 연산이 종료되어 최종 출력값(Outcome)이 반환된 시점부터, 대상 상태(Target State)의 진입 훅(Entry Hook)이 실행되기까지 소요되는 절대 시간(\Delta t)을 의미한다.
- 통신 오버헤드(Communication Overhead): 상태 머신이 구동되는 동안 데이터의 동기화 및 전이를 위해 소모되는 CPU 점유율(%), 메모리 할당량(MB), 그리고 ROS 2 미들웨어 계층(RMW)을 통해 발생하는 네트워크 대역폭(Bandwidth) 트래픽을 의미한다.
17.2 내부 코어 엔진의 국소적 상태 전이 지연(Local Transition Latency)
YASMIN의 코어 엔진 자체는 ROS 2 통신 스택과 독립된 순수 로컬 메모리 연산으로 구동되므로 극한의 지연 시간 최적화를 달성한다.
- 해시 기반 라우팅 탐색: 상태 머신 내부의 전이 규칙은 해시 테이블(예: C++의
std::unordered_map) 구조로 메모리에 맵핑된다. 현재 출력값에 대응하는 다음 상태를 탐색하는 알고리즘의 시간 복잡도는 평균적으로 O(1)이다. - 마이크로초(\mu s) 단위의 반응성: 미들웨어 간의 메시지 복사나 직렬화 과정이 생략되므로, 순수 코어 엔진 내에서의 상태 전이 연산은 일반적인 x86_64 또는 ARM64 아키텍처 프로세서 기준 1~10마이크로초(\mu s) 이내에 완료된다. 이는 1,000Hz 이상의 초고주파 제어 루프(High-frequency Control Loop)를 요구하는 모터 드라이버 제어기 수준에서도 병목 없이 작동할 수 있음을 의미한다.
17.3 미들웨어 종속성 분리를 통한 네트워크 통신 부하(Overhead) 소거
기존의 분산형 아키텍처를 채택한 일부 상태 머신 라이브러리(예: 상태가 각각 독립된 ROS 2 노드로 구동되는 패턴)는 상태가 전환될 때마다 DDS(Data Distribution Service) 네트워크 계층을 통과해야 하므로 극심한 직렬화/역직렬화(Serialization/Deserialization) 부하를 유발한다.
- 단일 프로세스 내 캡슐화: YASMIN은 단일 ROS 2 노드(Node) 내부에서 전체 상태 머신 토폴로지를 인스턴스화한다. 따라서 래퍼 상태(Wrapper State)를 통한 외부와의 명시적인 액션(Action)이나 토픽(Topic) 통신이 발생하지 않는 한, 일반적인 상태 간 전이 및 블랙보드 연산 과정에서는 네트워크 트래픽이 전혀 발생하지 않는다.
- 통신 오버헤드의 최소화: 이 아키텍처는 ROS 2 미들웨어 트래픽 부하를 사실상 0에 수렴하게 만들어, 다수의 카메라와 라이다(LiDAR) 센서 데이터 전송으로 인해 네트워크 대역폭이 포화된 모바일 로봇 환경에서도 상태 제어 시스템이 안정적으로 기능하도록 보장한다.
17.4 블랙보드 동기화 및 다중 스레드 병목(Bottleneck) 평가
통신 부하 대신, YASMIN 아키텍처에서 유일하게 성능 지연을 유발할 수 있는 변수는 다중 스레드 환경에서의 블랙보드(Blackboard) 공유 메모리 접근 경합(Contention)이다.
- 상호 배제(Mutex)에 의한 대기 지연: 여러 콜백 그룹에서 동시에 블랙보드의 데이터를 읽고 쓰기 위해 접근할 경우, 스레드 안전성 보장을 위한 동기화 락(Lock)이 작동한다. 이로 인해 스케줄러에 의한 스레드 블로킹(Blocking)이 발생하여 일시적인 런타임 지연 시간이 증가할 수 있다.
- 참조 전달(Reference Passing) 및 복사 비용 최소화: YASMIN은 고용량 ROS 2 메시지(예:
sensor_msgs/Image,sensor_msgs/PointCloud2)를 블랙보드에 저장할 때, 값 복사(Pass by Value)가 아닌 스마트 포인터(std::shared_ptr)를 이용한 참조 단위 기록을 권장한다. 포인터 복사 연산은 오버헤드가 상수 시간인 O(1)이므로, 메모리 복사로 인한 CPU 부하 및 힙(Heap) 메모리 단편화 현상을 방지할 수 있다.
17.5 이벤트 구동형 비동기 전이의 선점 시간(Preemption Latency)
순차적 execute() 실행 도중 비상 정지와 같은 외부 인터럽트가 발생하여 큐(Queue)에 적재되는 경우, 선점 지연(Preemption Latency)이 발생한다.
- YASMIN 코어는 임계 구역(Critical Section)에서의 실행 원자성을 보장하기 위해 현재 실행 중인 틱(Tick) 연산이나
on_exit()훅이 종료될 때까지 새로운 이벤트를 대기시킨다. - 따라서 사용자 정의 상태의
execute()내부에 블로킹 함수(예: 무한 루프나 긴sleep)를 잘못 배치할 경우, 이벤트 반응성이 해당 함수의 체공 시간만큼 선형적으로 지연되므로 설계 시 주의가 요구된다. 코루틴(Coroutine)이나 비동기 타이머 기반의 논블로킹(Non-blocking) 상태 로직 구현이 성능 평가 최적화의 핵심이다.
18. YASMIN 라이브러리 도입이 로봇 소프트웨어 모듈화에 미치는 기술적 효과
로봇 운영체제(ROS 2) 기반의 자율 시스템 설계에 있어 소프트웨어의 모듈화(Modularity)는 시스템의 확장성, 유지보수성, 그리고 런타임 신뢰성을 결정짓는 핵심 척도이다. YASMIN 프레임워크는 유한 상태 머신(FSM)의 수학적 모델을 소프트웨어 아키텍처에 적용함으로써 시스템의 결합도(Coupling)를 억제하고 응집도(Cohesion)를 극대화한다. 본 장에서는 YASMIN의 도입이 로봇 소프트웨어 공학 측면에서 창출하는 모듈화의 기술적 효과를 5가지 차원에서 세부적으로 규명한다.
18.1 제어 로직과 통신 미들웨어의 구조적 분리 (Structural Decoupling)
전통적인 ROS 노드 작성 방식은 제어 알고리즘(비즈니스 로직)과 ROS 미들웨어 통신(Pub/Sub, Action, Service 콜백)이 하나의 클래스 내에 강하게 결합(Tight Coupling)되는 스파게티 코드(Spaghetti Code)를 유발하기 쉽다.
- 미들웨어 독립성: YASMIN은 순수 상태 전이 연산과 ROS 2 계층(rclcpp, rclpy)을 물리적으로 분리한다. 코어 상태 엔진은 외부 네트워크 상태나 데이터 분배 서비스(DDS)의 설정에 전혀 영향을 받지 않고 독립적으로 구동된다.
- 통신 래퍼(Wrapper) 추상화: 외부 노드와의 통신이 필요한 경우에만
PublisherState,ActionClientState등의 통신 전용 파생 클래스를 제한적으로 사용한다. 이는 ROS 2 프레임워크의 버전 업그레이드나 타 미들웨어(예: eProsima Fast DDS에서 Eclipse Cyclone DDS로의 변경) 환경으로의 이식 작업 시, 코어 제어 알고리즘의 수정을 전혀 요구하지 않는 강력한 아키텍처적 유연성을 제공한다.
18.2 통합형 블랙보드 패턴을 통한 데이터 결합도 최소화 (Minimization of Data Coupling)
클래스나 함수 간에 매개변수(Parameter)나 포인터를 직접 전달하는 구조는 모듈 간의 상호 의존성을 높여 코드의 재사용성을 심각하게 저해한다.
- 간접 통신 매커니즘: YASMIN은 ‘블랙보드(Blackboard)’ 디자인 패턴을 내장하여 개별 상태 인스턴스 간의 직접적인 데이터 참조를 원천적으로 차단한다.
- 생산자-소비자 격리: 인지 모듈(생산자)은 블랙보드의 지정된 키(Key)에 데이터를 직렬화하여 적재할 뿐, 후속 제어 모듈(소비자)의 메모리 주소나 존재 여부를 인지할 필요가 없다. 이러한 데이터 중심(Data-centric) 간접 통신은 개별 상태 모듈이 입출력 인터페이스만 일치한다면 시스템 내 어느 위치에서든 독립적으로 동작할 수 있는 완벽한 모듈화를 달성한다.
18.3 단일 책임 원칙(SRP) 강제 및 기능적 응집도 향상 (Enforcement of SRP)
객체 지향 설계의 핵심인 단일 책임 원칙(Single Responsibility Principle)은 하나의 클래스가 단 하나의 책임만을 가져야 함을 명시한다. YASMIN의 상태 머신 설계 방법론은 개발자로 하여금 이 원칙을 강제적으로 준수하도록 유도한다.
- 이산적 캡슐화: 로봇의 복합 임무는 반드시 이산적이고 단일한 목적을 지닌 상태(예: ‘객체 추적 좌표 연산’, ‘모터 구동 한계치 검사’)로 분할되어야 한다. 각 상태 클래스의
execute()메서드는 선언된 단일 기능만을 수행하고 명시적인 결과값(Outcome)을 반환한 후 종료된다. - 응집도 극대화: 관련된 데이터 연산과 제어 명령이 하나의 상태 클래스 내부에 고도로 응집(High Cohesion)됨으로써, 특정 로봇 행동에 논리적 결함이 발생했을 때 해당 오류의 원인이 되는 코드 블록을 즉각적으로 추적하고 격리할 수 있다.
18.4 단위 테스트(Unit Testing) 독립성 확보 및 검증 자동화
하드웨어 종속성이 강한 로봇 소프트웨어는 모듈 단위의 테스트가 매우 난해하다는 기술적 한계가 존재한다. YASMIN은 이러한 한계를 극복하는 소프트웨어 테스트 환경을 제공한다.
- 모의 객체(Mock Object) 주입: YASMIN의 상태 클래스는 ROS 2 실행기(Executor)나 실제 센서 데이터 통신 없이도 독립적으로 객체화될 수 있다. 개발자는 모의 블랙보드(Mock Blackboard) 객체를 생성하여 가상의 센서 데이터를 강제 주입(Injection)한 뒤, 타겟 상태 모듈을 단독으로 실행할 수 있다.
- CI/CD 파이프라인 통합: 이를 통해 하드웨어 인 더 루프(HIL, Hardware-In-the-Loop) 시뮬레이터를 가동하지 않고도, 수학적으로 모든 분기(Branch)와 출력값(Outcome) 발생 조건을 검증하는 단위 테스트(예: GTest, PyTest)를 작성하여 지속적 통합(Continuous Integration) 파이프라인에 완벽하게 결합할 수 있다.
18.5 행동 모듈의 재사용성 및 교차 플랫폼 이식성 (Reusability & Portability)
고도로 분리되고 응집된 YASMIN의 단위 상태 모듈들은 단일 프로젝트를 넘어 다수 로봇 플랫폼 간에 공유될 수 있는 자산(Asset)으로 기능한다.
- 계층적 라이브러리화: 특정 로봇의 그리퍼(Gripper)를 닫고 파지 성공 여부를 검증하는 로직을 YASMIN 상태 머신(또는 단일 상태)으로 구현하여 패키징하면, 해당 모듈은 매니퓰레이터가 탑재된 모든 이기종 로봇 프로젝트에서 소스 코드의 수정 없이
add_state()호출만으로 재사용이 가능하다. - C++/Python 대칭 API의 효과: C++로 작성된 고성능 실시간 연산 상태 모듈과 Python으로 작성된 딥러닝 추론 기반 상태 모듈을 하나의 상태 머신 토폴로지 내에서 유기적으로 결합할 수 있다. 이는 각 프로그래밍 언어의 강점을 모듈별로 취사선택할 수 있는 하이브리드 소프트웨어 아키텍처의 구축을 가능하게 한다.
19. 다중 로봇 제어 시스템(Multi-Robot System)으로의 확장 적용 가능성 심층 고찰
다중 로봇 시스템(MRS) 및 군집 로봇(Swarm Robotics) 환경에서는 다수의 자율 에이전트가 제한된 공간과 네트워크 자원을 공유하며 협력적 임무를 수행해야 한다. 이러한 환경에서 중앙 집중식 제어는 통신 지연(Latency)과 단일 장애점(Single Point of Failure) 문제를 유발하므로, 각 로봇의 독립적인 의사결정 능력을 보장하는 분산형 행동 제어 아키텍처가 요구된다. YASMIN 프레임워크는 그 구조적 특성상 단일 로봇을 넘어 다중 로봇 통제 및 조율 스택으로 확장 적용할 수 있는 기술적 기반을 제공한다. 본 장에서는 YASMIN을 다중 로봇 제어 시스템에 적용할 때의 아키텍처적 확장성과 기술적 이점을 5가지 측면에서 심층 분석한다.
19.1 분산형 하향식(Top-down) 임무 할당 및 제어 아키텍처
다중 로봇 환경에서 중앙 플릿 관리자(Fleet Manager)가 개별 로봇의 모든 모터 제어나 센서 처리를 직접 통제하는 것은 비효율적이다. YASMIN은 로컬 환경에서의 ‘실행기(Executive)’ 역할을 수행하여 이러한 부하를 분산시킨다.
- 추상화된 목표 수신: 플릿 관리 서버는 ROS 2 액션(Action) 통신을 통해 개별 로봇에게 “A 구역으로 이동 후 B 화물 적재“와 같은 거시적이고 추상화된 목표(Goal)만을 하달한다.
- 로컬 상태 머신 구동: 명령을 수신한 로봇 내의 YASMIN 상태 머신(ActionServer 인터페이스 연동)은 이 거시적 목표를 자체적인 ‘주행 상태’, ‘인지 상태’, ’조작 상태’의 미시적 시퀀스로 분해하여 자율적으로 구동한다. 이는 중앙 서버의 연산 부하를 획기적으로 낮추고, 개별 로봇이 통신 단절(Dead-zone) 상황에서도 주어진 단위 임무를 독립적으로 완수할 수 있는 자율성을 부여한다.
19.2 글로벌-로컬 블랙보드(Global-Local Blackboard) 토폴로지 및 데이터 동기화
다중 로봇 간의 협력 작업(예: 두 대의 로봇이 협소 구역을 교차 통과하거나 무거운 화물을 공동 운반)을 위해서는 에이전트 간의 상태 공유가 필수적이다.
- 메모리 격리 및 선택적 동기화: YASMIN의 개별 로봇 내 블랙보드(로컬 블랙보드)는 물리적으로 완전히 격리되어 있어 변수 오염을 방지한다. 단, 협업에 필수적인 메타데이터(예: 로봇의 현재 위치, 작업 완료 플래그, 점유 중인 노드 ID)에 한하여 PublisherState와 SubscriberState를 통해 특정 공용 ROS 2 토픽(예:
/fleet/shared_states)으로 직렬화하여 발행/수신한다. - 가상 전역 메모리 구성: 이러한 선택적 동기화 메커니즘은 물리적인 중앙 메모리 서버 없이도 각 로봇의 상태 머신이 서로의 상태를 평가하고 전이 조건(Transition Condition)으로 활용할 수 있는 가상 전역 블랙보드(Virtual Global Blackboard) 토폴로지를 형성한다.
19.3 네트워크 대역폭(Bandwidth) 보존 및 통신 부하 병목 최소화
수십에서 수백 대의 로봇이 구동되는 환경에서는 ROS 2 데이터 분배 서비스(DDS) 네트워크의 대역폭 포화(Bandwidth Saturation)가 시스템 전체의 마비를 초래할 수 있다.
- 로컬 전이 연산: 만약 상태 머신의 각 상태가 별도의 노드로 분리되어 있다면 상태 전이 시마다 DDS 트래픽이 발생한다. 반면, YASMIN은 단일 프로세스 내에서 동작하므로 상태 간 전이 및 로컬 블랙보드 연산이 네트워크 트래픽을 전혀 유발하지 않는다.
- 트래픽 최적화: 외부 통신은 명시적으로 정의된 래퍼 상태(Wrapper State)를 통해서만 발생하므로, 설계자는 다중 로봇 네트워크 상에 브로드캐스팅되는 데이터의 주기와 용량을 엄격하게 통제할 수 있으며, 한정된 무선 네트워크(Wi-Fi, 5G 등) 자원을 센서 데이터 스트리밍 등 핵심 통신에 집중할 수 있다.
19.4 다중 에이전트 간 교착 상태(Deadlock) 방지 및 동기화 제어
여러 로봇이 공유 자원(예: 좁은 복도, 충전 스테이션, 엘리베이터)을 경쟁적으로 사용할 때 발생하는 교착 상태(Deadlock)를 회피하기 위한 논리 구조를 제공한다.
- 이벤트 구동형 대기(Event-driven Yielding): 로봇 A가 특정 자원을 점유하고 있을 때, 로봇 B의 YASMIN 상태 머신은 단순 블로킹(Blocking) 방식으로 무한 대기하지 않는다. SubscriberState를 통해 로봇 A의 ‘점유 해제(Release)’ 이벤트를 비동기적으로 모니터링하는 대기 상태(Waiting State)로 진입한다.
- 자원 선점 및 복구: 일정 시간 내에 이벤트가 수신되지 않으면 내부 타이머에 의해 ‘TIMEOUT’ 출력값이 발생하며, 이는 상태 머신을 우회 경로 탐색(Detour)이나 임무 재할당 요청과 같은 복구 상태(Recovery State)로 결정론적으로 라우팅하여 교착 상태를 해소한다.
19.5 동적 재구성(Dynamic Reconfiguration) 및 결함 허용(Fault Tolerance) 지원
다중 로봇 환경에서는 특정 개체의 하드웨어 고장이나 임무 실패가 전체 시스템의 실패로 이어지지 않도록 하는 결함 허용 설계가 중요하다.
- 오류 전파 및 전역 복구: 로봇 A의 하드웨어에 치명적 오류가 발생하여 YASMIN 코어가 ‘FATAL’ 상태로 전이될 경우, 해당 상태 모듈은 종료 직전 글로벌 블랙보드(공용 토픽)에 구조 요청(Distress Signal) 및 미완료 작업 데이터를 발행한다.
- 작업 이양(Task Handover): 주변에 위치한 로봇 B의 YASMIN 상태 머신은 조건부 전이 검사기(Condition Checker)를 통해 이 신호를 백그라운드에서 감지한다. 조건이 충족되면 로봇 B는 즉시 현재 하위 우선순위 작업을 일시 중지(Suspend)하고, 로봇 A의 미완료 작업을 넘겨받아 수행하는 복구 시나리오 분기로 엣지(Edge)를 동적으로 전환할 수 있다.
19.6 버전 업데이트 대응 및 시스템 유지보수를 위한 기술적 지침
로봇 제어 소프트웨어는 하드웨어의 수명 주기 및 운영체제(OS)의 판올림과 궤를 같이하며 지속적으로 진화해야 한다. 특히 ROS 2 생태계는 정기적인 장기 지원(LTS) 버전 출시와 함께 코어 미들웨어(DDS) 및 클라이언트 라이브러리(rclcpp, rclpy)의 API 변경이 빈번하게 발생한다. YASMIN 프레임워크를 채택한 상용 및 연구용 로봇 시스템의 장기적인 가용성(Availability)과 런타임 신뢰성을 보장하기 위해, 소프트웨어 공학적 관점에서의 엄격한 유지보수 및 버전 관리 지침이 요구된다. 본 장에서는 시스템의 수명 주기를 연장하기 위한 5가지 기술적 지침을 규명한다.
22.1 ROS 2 배포판 마이그레이션(Migration) 및 통신 계층 호환성 검증
새로운 ROS 2 LTS 배포판(예: Ubuntu 22.04 기반 Humble에서 Ubuntu 24.04 기반 Jazzy로의 전환)을 도입할 때, YASMIN의 미들웨어 종속성 영역에 대한 철저한 회귀 테스트(Regression Testing)가 수반되어야 한다.
- API 변경 대응: ROS 2의 핵심 통신 메커니즘인 액션(Action) 서버/클라이언트 구현체나 타이머 콜백(Timer Callback) 스케줄링 방식은 배포판 업데이트 시 내부 구조가 변경될 수 있다. YASMIN의
ActionClientState및 생명주기 제어 모듈이 새로운rclcpp_actionAPI 규격과 완벽하게 호환되는지 검증해야 한다. - QoS(Quality of Service) 프로필 갱신: DDS 미들웨어 업데이트에 따라 기본 QoS 설정(Reliability, Durability 등)의 동작 방식이 미세하게 달라질 수 있으므로, 상태 머신의 이벤트 퍼블리셔와 서브스크라이버 간의 통신 신뢰성을 담보하기 위해 명시적인 QoS 프로필 재설정이 요구된다.
22.2 메모리 타입 안정성(Type Safety) 및 예외 처리 방어 체계 갱신
YASMIN의 블랙보드(Blackboard) 패턴은 다양한 자료형을 수용하기 위해 C++17 표준의 std::any (또는 유사한 타입 이레이저 기법)와 스마트 포인터를 적극 활용한다. 시스템 유지보수 과정에서 컴파일러 버전이 상향되거나 C++20 표준으로 마이그레이션할 경우 메모리 접근 규칙이 더욱 엄격해진다.
- 명시적 형변환 검증: 블랙보드에 적재된 데이터를 소비자 상태(Consumer State)가 읽어올 때, 잘못된 타입 캐스팅으로 인한
std::bad_any_cast예외는 시스템의 즉각적인 세그멘테이션 폴트(Segmentation Fault)를 유발한다. 유지보수 단계에서는 이를 방어하기 위해 로직 전반에 걸쳐has_value()및type()검사를 강제하는 정적 분석(Static Analysis) 규칙을 적용해야 한다. - 메모리 누수(Memory Leak) 추적: 장기간 구동되는 자율 시스템의 특성상, 잦은 상태 전이와 동적 메모리 할당/해제로 인한 힙(Heap) 메모리 단편화나 누수를 방지하기 위해 Valgrind 또는 AddressSanitizer와 같은 메모리 프로파일링 도구를 CI(지속적 통합) 파이프라인에 통합해야 한다.
22.3 형상 관리(Configuration Management) 및 토폴로지 정적 검증 자동화
로봇의 임무 시나리오가 고도화됨에 따라 YASMIN 상태 머신의 그래프 토폴로지(노드 및 간선)는 기하급수적으로 복잡해진다. 런타임 오류를 사전에 차단하기 위해 상태 머신의 구조 자체를 코드가 아닌 데이터로 관리하는 형상 관리 체계가 필요하다.
- 토폴로지 무결성 검사 자동화: 새로운 상태(State)가 추가되거나 기존 전이(Transition) 규칙이 변경될 때마다, 도달 불가능한 상태(Unreachable State)나 목적지가 소실된 데드엔드(Dead-end), 미정의된 출력값(Unknown Outcome) 반환 여부를 검출하는 스크립트를 빌드 단계(Build-time)에 실행하도록 구성한다.
- 상태 명세서 동기화: 상태의 입출력 매개변수(블랙보드 필수 요구 Key)와 반환 가능한 Outcome 목록을 YAML 또는 JSON 형태의 매니페스트(Manifest) 파일로 정의하고, 코드를 이 매니페스트와 동기화하여 개발자 간의 인터페이스 오용을 시스템적으로 차단한다.
22.4 시각화 및 디버깅 도구(YASMIN Viewer)의 통신 프로토콜 동기화
YASMIN 코어 엔진과 외부 관제/디버깅 도구 간의 데이터 동기화는 런타임 가시성 확보에 필수적이다. 코어 라이브러리가 업데이트될 때 시각화 도구도 반드시 상응하는 업데이트를 거쳐야 한다.
- 직렬화(Serialization) 스키마 관리: 코어 엔진이 상태 머신 궤적과 블랙보드 스냅샷을 브로드캐스팅할 때 사용하는 JSON 스키마 구조가 변경될 경우(예: 타임스탬프 형식 변경, 새로운 상태 메타데이터 추가 등), YASMIN Viewer의 파싱(Parsing) 로직을 즉각적으로 동기화하여 디버깅 정보의 누락이나 렌더링 오류를 방지해야 한다.
- 네트워크 보안 계층 연동: 최신 ROS 2 시스템(예: SROS2)에서 보안 기능이 강화됨에 따라, 원격 디버깅을 위한 웹소켓 브릿지(Websocket Bridge) 통신에도 암호화 및 인증 인증서(Certificate) 갱신 절차를 정기적인 유지보수 프로토콜에 포함시켜야 한다.
22.5 하위 호환성(Backward Compatibility) 및 폐기(Deprecation) 정책 수립
자체적으로 커스텀 상태(Custom State) 라이브러리를 구축하여 운용하는 환경에서는 프레임워크 코어의 변경이 기존 코드베이스에 미치는 영향을 최소화해야 한다.
- 점진적 폐기 체계: 기존에 사용되던 API나 구형 통신 래퍼(Wrapper) 로직을 교체할 때는 즉각적인 삭제를 지양하고, 컴파일러의
[[deprecated]]매크로 또는 Python의warnings모듈을 활용하여 개발자에게 마이그레이션 기간을 부여한다. - 버전 록인(Version Lock-in) 관리: 운영 환경의 신뢰성이 극도로 요구되는 상용 로봇(예: 의료용, 산업용 자율주행 로봇)의 경우, 검증이 완료된 특정 YASMIN 커밋 해시(Commit Hash)와 ROS 2 패키지 버전을 Docker 컨테이너 등에 고정(Lock-in)시켜 의도치 않은 업스트림(Upstream) 업데이트로 인한 런타임 제어 알고리즘의 오작동을 원천 통제해야 한다.
20. 행동 트리(Behavior Tree, BT) 아키텍처와의 상호 운용성 및 구조적 비교
현대 로봇 소프트웨어 생태계, 특히 ROS 2 내비게이션 스택(Nav2) 및 고급 매니퓰레이션 프레임워크에서는 반응성(Reactivity)과 모듈성을 극대화하기 위해 행동 트리(Behavior Tree, BT) 아키텍처가 광범위하게 채택되고 있다. 유한 상태 머신(FSM) 기반의 YASMIN 프레임워크를 복잡한 로봇 시스템에 통합하기 위해서는, 이 두 이기종 제어 패러다임 간의 구조적 차이를 규명하고 유기적인 상호 운용(Interoperability) 방안을 수립하는 것이 필수적이다. 본 장에서는 FSM과 BT의 아키텍처를 학술적으로 비교하고, YASMIN을 활용한 하이브리드 제어 시스템 구축 방법론을 제시한다.
20.1 제어 패러다임 및 수학적 모델의 구조적 비교
유한 상태 머신과 행동 트리는 로봇의 의사결정을 모델링하는 목적은 동일하나, 그 실행 모델(Execution Model)에서 본질적인 차이를 지닌다.
- 상태 중심(State-centric) vs. 틱 중심(Tick-centric) 실행 모델: YASMIN(FSM)은 활성화된 단일 ’상태(State)’가 제어권을 독점하며, 명시적인 이벤트나 조건에 의해 다음 상태로 제어권이 이양되는 결정론적(Deterministic) 블로킹 모델에 가깝다. 반면, BT는 루트(Root) 노드부터 리프(Leaf) 노드까지 지정된 주파수로 ‘틱(Tick)’ 신호를 하향식으로 전파(Traversal)하여 각 노드의 상태를 비동기적으로 평가하는 반응형(Reactive) 폴링 모델이다.
- 제어 흐름의 추상화 및 복구 논리: FSM은 S \times E \rightarrow S' (현재 상태와 이벤트의 조합이 다음 상태를 결정)의 수학적 매핑을 통해 절차적 임무의 ’순서(Sequence)’를 명확하게 모델링하는 데 강점을 지닌다. 반면 BT는 상태 변이 대신
SUCCESS,FAILURE,RUNNING이라는 3가지 표준 반환값을 기반으로 폴백(Fallback) 노드를 구성하므로, 예기치 않은 센서 노이즈나 하드웨어 인터럽트에 대한 복구(Recovery) 절차를 유연하게 처리하는 데 수학적 우위를 갖는다.
20.2 하이브리드 인지-실행 아키텍처 (Hybrid Cognitive-Executive Architecture)
FSM의 절차적 명확성과 BT의 반응성을 동시에 취하기 위해, 학계 및 산업계에서는 매크로-마이크로(Macro-Micro) 계층 분할 형태의 하이브리드 아키텍처를 채택한다.
- 최상위 임무 통제 (Macro-level Executive): YASMIN은 로봇의 전체 임무 생명주기를 관장하는 최상위 작업 관리자(Task Executive)로 배치된다. ’물품 픽업 대기 -> 자율 주행 -> 물품 조작 -> 충전 스테이션 복귀’로 이어지는 거시적인 시나리오 횡단 및 전역 예외 처리를 담당한다.
- 하위 반응형 제어 (Micro-level Reactive Control): 개별 상태(예: ‘자율 주행’) 내부의 구체적인 하드웨어 제어, 장애물 회피 연산, 로컬 센서 피드백 처리는 BehaviorTree.CPP와 같은 BT 기반 로컬 컨트롤러(예: Nav2 스택)로 위임(Delegation)된다.
20.3 전역-지역 블랙보드(Blackboard) 간의 데이터 동기화 메커니즘
두 아키텍처 모두 모듈 간 결합도를 낮추기 위해 블랙보드 패턴을 사용하지만, 직접적인 메모리 포인터 공유는 다중 스레드 환경에서 메모리 접근 위반을 유발하므로 ROS 2 미들웨어를 통한 간접 동기화가 요구된다.
- YASMIN의 전역 블랙보드에 저장된 추상화된 목표 데이터(예: 최종 목적지의 2D 좌표)는 ROS 2 Action 통신의 목표(Goal) 메시지로 직렬화되어 BT 엔진으로 전송된다.
- 수신측의 BT 엔진은 이 메시지를 역직렬화하여 자체적인 로컬 블랙보드의 입력 포트(Input Port)에 적재하고, 경로 탐색 플러그인의 매개변수로 활용하여 두 프레임워크 간의 스레드 안전성(Thread-safety)을 보장한다.
20.4 상호 운용성 구현 명세 (Implementation Specification)
하이브리드 아키텍처를 구현하기 위해, YASMIN 상태 머신 내부에서 BT 기반의 외부 하위 시스템(Nav2)을 비동기적으로 호출하고, BT의 최종 횡단 결과를 FSM의 전이 규칙으로 평탄화(Flattening)하는 표준 통신 래퍼(Wrapper) 설계 방식이다.
// C++ 구현 명세: YASMIN 내에서 BT 기반 Nav2 스택을 호출하는 하이브리드 통합 아키텍처
#include <yasmin/state.hpp>
#include <yasmin_ros/action_client_state.hpp>
#include <nav2_msgs/action/navigate_to_pose.hpp>
// Nav2의 NavigateToPose 액션(내부적으로 BT 구동)을 YASMIN 상태로 캡슐화
class NavigateWithBTState : public yasmin_ros::ActionClientState<nav2_msgs::action::NavigateToPose> {
public:
// 생성자를 통해 BT의 연산 결과에 대응하는 FSM 출력값(Outcome) 명시적 선언
NavigateWithBTState() : ActionClientState(
"navigate_to_pose",
{"SUCCEEDED", "ABORTED", "CANCELED"}
) {}
// YASMIN 전역 블랙보드 데이터를 기반으로 BT에 전달할 액션 목표(Goal) 직렬화
nav2_msgs::action::NavigateToPose::Goal create_goal(yasmin::Blackboard& blackboard) override {
nav2_msgs::action::NavigateToPose::Goal goal;
if (blackboard.has("target_pose")) {
// YASMIN의 런타임 목표를 BT의 로컬 블랙보드로 전달하기 위한 매핑
goal.pose = blackboard.get<geometry_msgs::msg::PoseStamped>("target_pose");
}
return goal;
}
// BT(Nav2) 서버로부터 결과를 수신하여 YASMIN 코어 엔진의 논리적 전이 이벤트로 변환
std::string on_result(
const rclcpp_action::ClientGoalHandle<nav2_msgs::action::NavigateToPose>::WrappedResult& result,
yasmin::Blackboard& blackboard) override {
// BT 리프 노드의 반환값을 YASMIN 그래프 라우팅 테이블의 키(Key)로 평탄화
switch (result.code) {
case rclcpp_action::ResultCode::SUCCEEDED:
return "SUCCEEDED"; // BT 루트 노드가 최종 SUCCESS를 반환한 경우
case rclcpp_action::ResultCode::CANCELED:
return "CANCELED"; // 상위 인터럽트에 의해 횡단이 선점(Preempted)된 경우
default:
return "ABORTED"; // BT 복구 노드가 모두 실패하여 FAILURE를 반환한 경우
}
}
};
21. 산업용 로봇 기능 안전(Functional Safety) 규격 및 정형 검증(Formal Verification)
산업 현장에 투입되는 자율 주행 로봇(AMR) 및 협동 매니퓰레이터는 작업자와 동일한 공간을 공유하므로, 소프트웨어의 논리적 결함이 심각한 인명 피해나 물리적 손실로 직결될 수 있다. 따라서 상용 로봇 시스템은 국제 기능 안전 규격을 준수해야 하며, 제어 소프트웨어는 수학적으로 무결성이 입증되어야 한다. 본 장에서는 YASMIN 프레임워크를 기반으로 설계된 로봇 행동 제어 시스템이 산업용 기능 안전 규격을 충족하기 위한 아키텍처 설계 원리와 정형 검증(Formal Verification) 방법론을 기술한다.
21.1 기능 안전 규격(IEC 61508 및 ISO 13849) 기반 소프트웨어 안전성
산업용 로봇 제어 시스템은 통상적으로 전기/전자/프로그래머블 전자 안전 관련 시스템의 기능 안전 표준인 IEC 61508과 기계류의 안전을 다루는 ISO 13849-1 규격을 준수해야 한다.
- 안전 무결성 기준(SIL 및 PL): IEC 61508의 SIL(Safety Integrity Level)과 ISO 13849의 PL(Performance Level)은 시스템이 위험한 고장을 일으키지 않을 확률을 정량화한다. YASMIN과 같은 상위 수준의 작업 관리자(Task Executive)는 최소 SIL 2 또는 PL ‘d’ 수준의 신뢰성을 요구받는다.
- 소프트웨어 체계적 고장(Systematic Failure) 방지: 규격은 소프트웨어의 복잡성으로 인해 발생하는 체계적 고장을 방지하기 위해 결정론적(Deterministic) 제어 흐름과 모듈화된 설계를 강제한다. YASMIN은 로봇의 임무를 이산적인 상태와 명시적인 전이 엣지(Edge)로만 제한하므로, 제어 흐름의 분기 예측이 100% 가능하여 규격이 요구하는 ’소프트웨어 아키텍처의 투명성’을 기본적으로 충족한다.
21.2 유한 상태 머신의 수학적 모델링 및 정형화
정형 검증을 수행하기 위해서는 코드로 구현된 YASMIN 상태 머신을 오토마타(Automata) 이론에 기반한 수학적 모델로 변환해야 한다. YASMIN의 아키텍처는 수학적 튜플(Tuple) 구조로 1:1 매핑이 가능하다.
- 모델 정의: YASMIN 상태 머신 M은 튜플 M = \langle S, s_0, E, C, T \rangle 로 정의할 수 있다.
- S: 유한한 상태들의 집합 (사용자가 등록한 모든 상태 노드)
- s_0: 초기 진입 상태 (s_0 \in S)
- E: 시스템에 입력되는 유한한 이벤트 또는 출력값(Outcome)의 집합
- C: 블랙보드(Blackboard) 변수에 기반한 조건식(Condition)의 집합
- T: 전이 함수 (Transition Function). T: S \times E \times C \rightarrow S
- 상태 폭발(State Explosion)의 통제: 정형 검증 시 가장 큰 제약은 상태의 경우의 수가 무한대로 발산하는 상태 폭발 문제이다. YASMIN은 블랙보드 메모리 공간을 계층적으로 격리하고, 부모-자식 상태 머신(HFSM) 구조를 통해 모듈 단위로 검증 모델을 분할할 수 있어 이 문제를 효과적으로 회피한다.
21.3 시제 논리(Temporal Logic) 기반 모델 검사(Model Checking)
설계된 상태 머신 토폴로지가 런타임에 치명적인 논리 오류를 유발하지 않음을 수학적으로 증명하기 위해 UPPAAL이나 NuSMV와 같은 모델 검사(Model Checking) 도구를 활용한다. 시스템의 요구사항을 계산 트리 논리(Computation Tree Logic, CTL)로 작성하여 토폴로지를 전수 탐색한다.
- 안전성 속성 (Safety Property): “시스템에 나쁜 일이 절대 발생하지 않는다“는 것을 증명한다. 예를 들어, 로봇이 특정 전이 조건 누락으로 인해 멈춰버리는 데드엔드(Dead-end) 상황이 발생하지 않음을 검증한다.
- CTL 명세:
A[] not deadlock(모든 가능한 실행 경로에 대해, 교착 상태는 존재하지 않는다.) - 활동성 속성 (Liveness Property): “시스템에 좋은 일이 결국 발생한다“는 것을 증명한다. 로봇이 복구 상태(Recovery State)에 진입하더라도, 유한한 틱(Tick) 내에 반드시 초기 대기 상태나 안전 종료 상태로 빠져나올 수 있음을 검증한다.
- CTL 명세:
A<> (State == RECOVERY imply A<> State == SAFE_STOP)(복구 상태에 진입하면, 모든 경로에서 결국 안전 정지 상태에 도달한다.)
21.4 고장 감내(Fault Tolerance) 아키텍처 및 안전 루프(Safety Loop)
단일 상태 머신의 논리적 무결성이 입증되더라도, 센서 고장이나 ROS 2 미들웨어의 통신 타임아웃 등 외부 요인에 의한 시스템 마비를 방지하기 위해 고장 감내 아키텍처가 YASMIN 내부에 설계되어야 한다.
- 병렬 감시자(Watchdog) 상태 머신: 주 임무를 수행하는 상태 머신과 별개로, 시스템 자원(CPU, 배터리) 및 하위 하드웨어 노드의 하트비트(Heartbeat) 통신만을 전담하여 모니터링하는 직교(Orthogonal) 구조의 감시자 상태 머신을 인스턴스화한다.
- 하드코드된 안전 루프(Safety Loop): 주 상태 머신이 블랙보드 연산 중 치명적 예외(Fatal Exception)를 발생시켜 작동을 멈추더라도, 독립된 스레드에서 구동되는 감시자 상태 머신이 이를 감지하여 로봇의 하드웨어 브레이크를 활성화하는
/hardware/estop토픽을 즉각 발행하는 하드코드된 폴백(Fallback) 라우팅을 구성한다.
[구현 명세: 고장 감내를 위한 타임아웃 및 비상 정지 분기 설계]
YASMIN에서 네트워크 단절이나 연산 지연에 대비하여 결정론적으로 안전 상태로 전이하는 코드 구현 예시이다.
// C++ 구현 예제: 서비스 호출 상태에 고장 감내(Fault Tolerance) 타임아웃 엣지 추가
class NavigationState : public yasmin_ros::ServiceClientState<nav_msgs::srv::GetPlan> {
public:
NavigationState() : ServiceClientState("/get_plan", {"SUCCEEDED", "ABORTED", "TIMEOUT"}) {}
// 타임아웃 시간(예: 3초) 초과 시 엔진이 강제로 "TIMEOUT"을 반환하도록 설정
std::chrono::milliseconds get_timeout() override {
return std::chrono::milliseconds(3000);
}
};
// ... 토폴로지 구성 단계 ...
auto sm = std::make_shared<yasmin::StateMachine>({"TASK_DONE", "EMERGENCY_STOP"});
// 정상 경로 전이
sm->add_transition("NAVIGATE", "SUCCEEDED", "EXECUTE_MOTION");
// 경로 탐색 실패 시 복구 상태로 전이
sm->add_transition("NAVIGATE", "ABORTED", "RECOVERY_PLANNING");
// 3초간 통신 응답이 없는 고장(Fault) 발생 시 즉시 안전 정지 상태로 강제 라우팅
sm->add_transition("NAVIGATE", "TIMEOUT", "HARDWARE_SAFE_STOP");
21.5 비상 정지(Emergency Stop) 시나리오의 결정론적 제어권 이양
기능 안전 규격에서 가장 중요하게 다루는 범주는 인간의 비상 정지 스위치 조작이나 라이다(LiDAR) 안전 영역(Safety Zone) 침범 시의 시스템 반응이다.
- 선점형 인터럽트(Preemptive Interrupt) 처리: YASMIN은 이벤트 구동형(Event-driven) 전이를 통해 진행 중인 모든 비동기 작업(예:
ActionClientState의 주행 연산)을 즉각 취소(Cancel)한다. - 상태 이탈(Exit Hook)의 안전성 보장: 비상 정지로 인해 현재 상태가 강제 종료될 때, 해당 상태의
on_exit()생명주기 훅이 반드시 호출되도록 보장해야 한다. 이 훅 내부에 모터의 토크(Torque) 차단 명령이나 레이저 활성 해제 등 하드웨어 레벨의 안전 차단 로직을 구현하여, 논리적 상태 전이와 물리적 하드웨어의 안전 상태를 완벽하게 동기화(Synchronization)한다.
22. 지속적 통합(CI/CD) 기반의 자동화된 성능 회귀(Performance Regression) 벤치마킹
로봇 제어 시스템은 장기적인 유지보수 및 기능 확장 과정에서 코드가 추가되거나 미들웨어가 업데이트됨에 따라, 의도치 않은 시스템 자원 점유율 증가나 연산 지연과 같은 성능 회귀(Performance Regression) 현상이 발생할 위험이 상존한다. YASMIN과 같은 코어 행동 제어 프레임워크의 성능 저하는 전체 자율 주행 및 조작 제어 루프의 병목(Bottleneck)으로 직결되므로, 단순한 기능 무결성 테스트(Unit Test)를 넘어 정량적인 성능 벤치마킹을 지속적 통합(CI/CD) 파이프라인에 자동화하는 아키텍처가 필수적이다. 본 장에서는 YASMIN 시스템의 성능을 추적하고 결함을 선제적으로 차단하기 위한 벤치마킹 파이프라인 구축 명세를 기술한다.
22.1 성능 회귀(Performance Regression)의 학술적 정의 및 핵심 추적 지표
성능 회귀란 소프트웨어의 변경 사항(Commit 또는 Pull Request)이 기존 버전 대비 정량적 성능 지표를 악화시키는 현상을 의미한다. YASMIN 프레임워크 벤치마킹에서 추적해야 할 핵심 지표(Metrics)는 다음과 같다.
- 상태 전이 지연 시간 (Transition Latency, \Delta t): 전이 조건이 충족된 시점부터 다음 상태의
on_enter()훅이 호출되기까지 소요되는 절대 시간(마이크로초, \mu s 단위). - 블랙보드 접근 오버헤드 (Blackboard Access Overhead): 다중 스레드 환경에서
std::any기반의 공유 메모리에 읽기/쓰기 연산을 수행할 때 발생하는 상호 배제(Mutex) 대기 시간 및 데이터 직렬화 캐스팅 시간. - 동적 메모리 할당 빈도 (Dynamic Memory Allocation Rate): 실행 주기(Tick)마다 발생하는 힙(Heap) 메모리 할당 횟수. 빈번한 동적 할당은 실시간(Real-time) 운영체제에서 예측 불가능한 지연(Jitter)을 유발한다.
22.2 프로파일링 파이프라인 구축 및 마이크로 벤치마크(Micro-benchmark) 연동
ROS 2 C++ 생태계의 표준 성능 측정 도구인 구글 벤치마크(Google Benchmark) 라이브러리를 활용하여, 외부 네트워크 토픽이나 하드웨어 인터페이스가 완전히 배제된 고립(Isolated) 환경에서 YASMIN 코어 엔진의 순수 연산 성능을 측정한다.
[구현 명세: C++ 구글 벤치마크를 활용한 상태 전이 지연 시간 측정]
#include <benchmark/benchmark.h>
#include <yasmin/state_machine.hpp>
#include <yasmin/blackboard.hpp>
// 벤치마크용 더미 상태 클래스 정의
class DummyState : public yasmin::State {
public:
DummyState() : yasmin::State({"NEXT"}) {}
std::string execute(yasmin::Blackboard& bb) override { return "NEXT"; }
};
static void BM_YasminTransitionLatency(benchmark::State& state) {
// 1. 상태 머신 및 블랙보드 초기화 (측정 범위 외 연산)
auto sm = std::make_shared<yasmin::StateMachine>("bench_sm");
sm->add_state("STATE_A", std::make_shared<DummyState>());
sm->add_state("STATE_B", std::make_shared<DummyState>());
sm->add_transition("STATE_A", "NEXT", "STATE_B");
sm->add_transition("STATE_B", "NEXT", "STATE_A");
yasmin::Blackboard blackboard;
// 2. 핵심 연산 반복 측정 (마이크로초 단위)
for (auto _ : state) {
// 단일 틱(Tick) 연산 실행: 내부 상태 전이 및 로직 수행 시간 측정
sm->spin_once(blackboard);
}
}
// 벤치마크 등록 및 수행 반복 횟수 최적화 지시
BENCHMARK(BM_YasminTransitionLatency)->Iterations(100000);
BENCHMARK_MAIN();
22.3 CI 환경에서의 임계치(Threshold) 검증 및 자동 차단 메커니즘
작성된 벤치마크 코드는 GitHub Actions, GitLab CI 등의 지속적 통합 환경에서 자동화된 스크립트(예: ros2_benchmark 프레임워크)를 통해 실행된다.
- 기준선(Baseline) 비교 알고리즘: CI 파이프라인은 메인 브랜치(Main Branch)의 최신 안정 버전에서 도출된 벤치마크 결과(기준선)와 현재 병합(Merge) 대기 중인 코드의 결과를 통계적으로 비교한다.
- 하드 리미트(Hard Limit) 기반 파이프라인 제어: 상태 전이 지연 시간이 기준선 대비 5% 이상 증가하거나, 블랙보드 락(Lock) 대기 시간이 설정된 허용 임계치(예: 50 \mu s)를 초과할 경우, CI 시스템은 해당 Pull Request에 ‘실패(Fail)’ 플래그를 부여하고 병합을 시스템적으로 강제 차단한다.
22.4 스트레스 테스트(Stress Test) 및 장기 구동(Endurance) 안정성 평가
단순한 지연 시간 측정을 넘어, 극한의 환경에서 프레임워크가 자원 고갈 없이 안정적으로 작동하는지 검증하는 단계가 포함되어야 한다.
- 고빈도 이벤트 큐(Event Queue) 주입 테스트: 다수의 ROS 2 서브스크라이버 콜백이 초당 1,000회 이상의 비동기 이벤트를 YASMIN 엔진으로 동시다발적으로 주입하는 상황을 시뮬레이션하여, 이벤트 큐의 오버플로우(Overflow) 및 경쟁 상태(Race Condition) 발생 여부를 검증한다.
- 메모리 단편화 및 누수 검사: CI 파이프라인 내에서 상태 머신을 가상 시간으로 수십 시간 분량(수백만 번의 상태 전이) 연속 구동시킨 후,
AddressSanitizer (ASan)도구를 호출하여 블랙보드 내 잔존하는 참조 카운트 오류(Dangling Pointers)나 메모리 누수(Memory Leak)를 정적으로 추적 및 보고하도록 구성한다.