mlpy.agents.fsm.StateMachine.load_from_file

StateMachine.load_from_file(owner, filename, **kwargs)[source]

Load the FSM from file.

Read the information of the state machine from file. The file contains information of the states, transitions and callback function.

Parameters:

owner : object

Reference to the object owning the FSM.

filename : str

The name of the file containing the FSM configuration information.

kwargs : dict

Non-positional arguments match with configuration parameters during state creation.

Notes

The FSM setup can be specified via a configuration file in .json format. The configuration file must follow a specific format.

The configuration file must contain the absolute path to the module containing the implementation of each state. Additionally, the configuration file must contain the name of the initial state, a list of states, their transitions, and information of the onupdate callback functions.

Example:

A skeleton configuration with two states named “<initial>” and “<next>” and one simple transition between them named “<event>”. The implementation of the states are defined in the file specified in “Module”.

{
    "Module": "absolute/path/to/the/fsm/states.py",
    "States": [
        "<initial>",
        "<next>"
    ],
    "Initial": "<initial>",
    "Transitions": [
        {"source": "<initial>", "event": "<event>", "dest": "<next>"},
        {"source": "<next>", "event": "<event2>", "dest": "<initial>"}
    ],
    "OnUpdate": [
    ]
}

If the states have initialization parameters these can be specified as follows:

{
    "States": [
        {"<initial>": {
            "args": "motion",
            "kwargs": {"support_leg": "right"}
        }}
    ]
}

This lets the FSM know that the state “<initial>” has two parameters. The positional arguments (specified in args) are compared to non-positional arguments in kwargs passed to load_from_file. If a match exists, the value of the match is passed as argument. If no match exist the value in “args” is send directly to the state. Multiple positional arguments can be specified by adding them in a list: [“arg1”, “arg2”, ...]. The non-positional arguments are send as is to the state.

To specify callback functions before and after transitioning from a source to the destination the following formats are available:

{
    "Transitions": [
        {"source": "<initial>", "event": "<event>", "dest": "<next>",
            "before": {"model": "<ClassName>", "func": "<FuncName>"},
            "after": {"model": "<ClassName>", "func": "<FuncName>"}},
        {"source": "<next>", "event": "<event2>", "dest": "<initial>",
            "before": "<FuncName>",
            "after": "<FuncName>"}
    ]
}

It is also possible to define conditions on the transitions, such that a transition between states is only performed when the condition(s) are met:

{
    "Transitions": [
        {"source": "<initial>", "event": "<event>", "dest": "<next>",
            "conditions": ["lambda x: not x._motion.is_running",
                           "FuncName"]
            "before": {"model": "<ClassName>", "func": "<FuncName>"},
            "after": {"model": "<ClassName>", "func": "<FuncName>"}},
        {"source": "<next>", "event": "<event2>", "dest": "<initial>",
            "conditions": "FuncName"
            "before": "<FuncName>",
            "after": "<FuncName>"}
    ]
}

It is also possible to add a transition to every state by using *:

{
    "Transitions": [
        {"source": "*", "event": "<event>", "dest": "*"},
    ]
}

This statement means that “<event>” is a valid event from every state to every other state.

To identify the onupdate callback functions use the following format:

{
    "OnUpdate": [
        {"source": "<initial>", "conditions": ["lambda x: not x._motion.is_running",
                                               "FuncName"]
            "onupdate": {"model": "<ClassName>", "func": "<FuncName>"}},
    ]
}

This lets the FSM know to call the function specified in “onupdate” when in state “<initial>” when the conditions are met. The conditions are optional. Also, instead of calling a class function a lambda or other function can be called here.