Main Concepts

YASMIN (Yet Another State MachINe) is designed to simplify the creation of complex robot behaviors using state machines. Understanding the core concepts is essential for using the library effectively.

Finite State Machines (FSM)

A Finite State Machine is a mathematical model of computation. It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some inputs; the change from one state to another is called a transition.

In the context of robotics, FSMs are used to define the behavior of a robot. Each state represents a specific task or mode of operation (e.g., "Idle", "Moving", "Grasping"), and transitions define how the robot switches between these tasks based on sensor data or internal logic.

FSMs provide several key advantages for robot control: they offer a clear, visual representation of robot behavior that is easy to understand and debug; they ensure deterministic behavior where the robot's actions are predictable and reproducible; and they enable modular design where each state encapsulates a specific functionality that can be developed and tested independently. This makes FSMs particularly well-suited for complex robotic applications where reliability and maintainability are crucial.

In YASMIN, FSMs are implemented as state machine objects that manage the execution flow. You define states, add them to the state machine with their transition logic, and then execute the state machine. The framework handles the state execution loop, transition management, and data sharing through the blackboard, allowing you to focus on implementing the behavior logic within each state.

Hierarchical Finite State Machines (HFSM)

As systems become more complex, a simple "flat" FSM can become unmanageable due to the explosion of states and transitions. Hierarchical Finite State Machines (HFSM) address this by allowing states to contain other state machines.

In YASMIN, you can nest state machines within states. This allows you to encapsulate complex behaviors into reusable modules. For example, a "Navigation" state could internally be an FSM with states like "Plan Path", "Follow Path", and "Recover". The parent FSM only sees the high-level "Navigation" state.

The hierarchical approach provides significant architectural benefits. It enables abstraction layers where high-level state machines deal with strategic decisions while nested state machines handle tactical execution details. This separation of concerns makes the overall system easier to understand, test, and maintain. Each nested state machine can be developed and validated independently before being integrated into the larger system.

YASMIN's implementation of HFSM is particularly powerful because nested state machines are treated as regular states from the parent's perspective. They receive the same blackboard access, can use remapping just like simple states, and return outcomes that drive transitions in the parent machine. This uniformity means you can refactor a simple state into a complex nested state machine without changing the parent's logic, enabling iterative refinement of behaviors as requirements evolve.

Hierarchical composition also facilitates team collaboration on large robotic systems. Different team members can work on different nested state machines simultaneously, with clear interfaces defined by the blackboard keys and outcomes. This modular structure supports parallel development and makes it easier to reuse proven behavior components across multiple robot applications.

Key Components in YASMIN

State

The fundamental building block. A state performs a task and returns an outcome. In YASMIN, you create custom states by inheriting from the State class and implementing the execute method.

Each state is designed to be self-contained and focused on a single responsibility. When you create a state, you define what inputs it needs from the blackboard, what outputs it produces, and what outcomes it can return. The execute method contains the core logic of the state - this could be anything from simple data processing to complex interactions with robot hardware or external services.

States can be stateless (performing the same operation every time) or stateful (maintaining internal variables between executions). YASMIN supports both patterns, giving you flexibility in how you design your behaviors. For example, a counter state might maintain an internal count that increments on each execution, while a sensor reading state might be completely stateless, simply querying a sensor and returning the result each time.

Outcomes

Every state execution concludes with an outcome (a string). This outcome determines which transition is triggered. Common outcomes include "success", "failure", "aborted", or custom events like "target_detected". Outcomes are the glue that connects states together - they define the flow of execution through your state machine.

You can define custom outcomes for your states to represent different completion scenarios. For example, a "GraspObject" state might have outcomes like "grasped", "object_not_found", "gripper_error", each leading to different next states or recovery behaviors. This flexibility allows you to model complex decision trees and error handling logic in a clear, explicit way.

Transitions

Transitions map the outcome of a state to the next state to be executed. This defines the flow of the application. When you add a state to a state machine, you specify a dictionary of transitions where each key is a possible outcome from that state, and the value is the name of the next state to execute. This creates a directed graph that represents your application's logic. Transitions can point to other states, loop back to the same state (useful for retry logic), or terminate the state machine by mapping to a final outcome. The transition mechanism is what makes YASMIN a true finite state machine, ensuring deterministic and predictable behavior flows.

Blackboard

The Blackboard is a shared memory space that allows states to exchange data. Since states are often independent classes, they need a mechanism to pass information (e.g., a target pose found by a "Perception" state needs to be passed to a "Move" state). The Blackboard stores key-value pairs that are accessible to all states in the FSM.

One of the most powerful features of the Blackboard is remapping. Remapping allows you to connect states with different key names without modifying the state classes themselves. For example, if a state reads from input_data and another state writes to sensor_reading, you can remap input_data to sensor_reading when adding the state to the state machine. This enables:

When you add a state to a state machine using add_state(), you can provide a remappings dictionary that maps the state's internal key names to the actual blackboard keys. This is particularly useful when building complex state machines from reusable components or when integrating third-party states into your application.

State Machine Composition

YASMIN supports building complex behaviors by composing multiple state machines. You can nest state machines within other state machines, creating hierarchical structures. This composition allows you to:

For example, a high-level "PerformTask" state machine might contain nested state machines for "NavigateToLocation", "PerceiveEnvironment", and "ExecuteAction", each of which is a complete FSM with its own states and transitions. This hierarchical approach mirrors how humans break down complex problems into smaller sub-problems.

Concurrency

YASMIN provides a Concurrence container that allows multiple states to execute in parallel. This is useful when you need to perform multiple independent tasks simultaneously, such as monitoring sensors while executing an action. The Concurrence container manages the parallel execution and provides flexible outcome resolution - you can specify whether all states must succeed, if any state succeeding is sufficient, or implement custom logic to combine the outcomes of concurrent states.

Concurrent states share the same blackboard, so you need to be careful about data access patterns. YASMIN handles thread safety for blackboard operations, but you should design your states to avoid conflicts when reading and writing shared data concurrently.