SMACHA Documentation

SMACHA is a meta-scripting, templating, and code generation engine for rapid prototyping of ROS SMACH state machines.

SMACH is an exceptionally useful and comprehensive task-level architecture for state machine construction in ROS-based robot control systems. However, while it provides much in terms of power and flexibility, its overall task-level simplicity can often be obfuscated at the script-level by boilerplate code, intricate structure and lack of code reuse between state machine prototypes.

SMACHA (short for “State Machine Assembler”, pronounced “smasha”) aims at distilling the task-level simplicity of SMACH into compact YAML scripts in the foreground, while retaining all of its power and flexibility in Jinja2-based templates and a custom code generation engine in the background. Thus SMACHA does not aim to replace SMACH, but to augment it.

Overview

Here is a high-level illustration of the main components of the SMACHA API:

SMACHA API Overview

Here is a video demonstrating the use of SMACHA with the Baxter robot simulator using the baxter_smacha package:


Why SMACHA?

SMACHA allows for arbitrarily complex SMACH state machine programs to be written as much shorter YAML scripts that can be directly executed with ROS. Here is the “Nesting State Machines” example from the SMACH Tutorials described in a SMACHA script:

--- # Nesting State Machines Tutorial SMACHA script.
name: sm_top
template: Base
manifest: smacha
node_name: smach_example_state_machine
outcomes: [outcome5]
states:
  - BAS: {template: Bas, transitions: {outcome3: SUB}}
  - SUB:
      template: StateMachine
      outcomes: [outcome4]
      transitions: {outcome4: outcome5}
      states:
        - FOO: {template: Foo, transitions: {outcome1: BAR, outcome2: outcome4}}
        - BAR: {template: Bar, transitions: {outcome1: FOO}}

This demonstrates a reduction from 80 lines of raw SMACH Python code to 14 lines of SMACHA script. Not bad. However, if we employ YAML inline format and SMACHA shorthand script syntax, we can get this down to 5 lines:

--- # Nesting State Machines Tutorial SMACHA script.
{n: sm_top, T: Base, m: smacha, nn: smach_example_state_machine, o: [outcome5],
 s: [BAS: {T: Bas, t: {outcome3: SUB}},
     SUB: {T: StateMachine, o: [outcome4], t: {outcome4: outcome5},
           s: [FOO: {T: Foo, t: {outcome1: BAR, outcome2: outcome4}},
               BAR: {T: Bar, t: {outcome1: FOO}}]}]}

Outside of script brevity, SMACHA provides many other benefits and tools to help rapidly prototype complex state machines for robot control.

Scripting

SMACHA Scripts are parsed by the Parser module and direct the Generator module on how to combine SMACHA templates using the Templater module.

Some of the benefits of meta-scripting in this way include:

  • quick, at-a-glance overviews of state machine program intent,
  • easy script manipulation, reuse and restructuring - SMACHA provides various utilities to automate some common script manipulation tasks, e.g.
    • the Contain Tool for automatic containerization of state sequences,
    • the Extract Tool for automatic conversion of commonly used container states to reusable sub-scripts,
  • streamlined ROS integration, e.g.
    • loading of scripts onto the ROS parameter server and
    • executing them with service calls.

Templating

SMACHA Templates are filled out by the Templater module as directed by the Generator module and as determined by the structure of the SMACHA scripts parsed by the Parser module.

The use of templates comes with its own additional benefits:

  • intricate boilerplate code can be automatically filled,
  • increased code reusability and modularity, e.g.
    • common design patterns can be easily turned into state templates,
    • template macros make it easy to repeat common patterns between templates,
    • template inheritance helps avoid repetitive code blocks,
  • templates could be designed for use with frameworks other than SMACH and Python
    • although this has not yet been tested, in theory templates could be written for use with other frameworks, e.g. FlexBE, CoSTAR, and others.

Code Generation

The SMACHA Code Generator recursively processes SMACHA Scripts parsed by The Parser Module, manages the use of SMACHA Templates that are filled out by The Templater Module, and renders the final result to executable Python SMACH code.

Installation

Simply clone into the src directory of your catkin workspace, update dependencies, and run catkin_make or catkin build from the root of the workspace.

$ cd ~/catkin_ws/src
$ git clone git@github.com:ReconCell/smacha.git
$ cd ..
$ rosdep install --from-paths src --ignore-src --rosdistro kinetic -y
$ catkin build
$ source ~/catkin_ws/devel/setup.bash

Usage

Generate

Given a SMACHA script (seq_nesting_1.yml) and a set of templates, e.g. to replicate the code from the SMACH Nesting State Machines tutorial, SMACH Python code can be generated with the following command:

$ rosrun smacha generate -t `rospack find smacha`/test/smacha_templates/executive_smach_tutorials -o state_machine_nesting2.py -v `rospack find smacha`/test/smacha_scripts/executive_smach_tutorials/state_machine_nesting2.yml

Here, the -t argument specifies custom template directories for this particular tutorial, which may contain templates that override the core templates.

The -o argument specifies a custom name for the generated output file.

The -v argument tells SMACHA to print verbose processing output to the terminal.

Further arguments and options may be explored by running rosrun smacha generate -h or rosrun smacha generate --help.

Execute

The script from the above example can also be directly executed provided that a roscore is running:

$ rosrun smacha execute -t `rospack find smacha`/test/smacha_templates/executive_smach_tutorials -v `rospack find smacha`/test/smacha_scripts/executive_smach_tutorials/state_machine_nesting2.yml

Again, further arguments and options may be explored by running rosrun smacha execute -h or rosrun smacha execute --help.

Important

A roscore must be running in order to execute scripts in this way!

Help

Help information may be printed for any template that contains a metadata block by running, e.g. the following command for the PrintUserdataState template:

$ rosrun smacha help PrintUserdataState

Testing

Tests may be performed by running:

$ python `rospack find smacha`/test/executive_smach_tutorials_test.py
$ python `rospack find smacha`/test/smacha_test_examples.py

Passing the -h argument as follows will bring up a list of some other options.

Passing the -w argument will write the generated output files to disk, which can subsequently be run as follows, e.g. for the state_machine_nesting2.py example:

$ rosrun smacha state_machine_nesting2_generate_output.py

To run the original file script, use the following command:

$ rosrun smacha state_machine_nesting2.py

SMACHA API

Modules

These are the main smacha package submodules:

Templates

These are the core smacha package templates:

Base Templates

  • Base: used for specifying the bare bones of a Python SMACH state machine script.

Container Templates

State Templates

Other Templates

  • State: contains code common to all state templates.
  • Utils: contains template macros and other utilities.

Other SMACHA Packages

SMACHA ROS

The SMACHA ROS provides ROS oriented templates and contains a SMACHA server that provides ROS services, ROS parameter server integration, and other functions.

SMACHA GUI

The SMACHA GUI package provides a visual programming interface for SMACHA for use within the ReconCell Project.

References/Citations

If you use SMACHA in your work, please consider citing the following paper:

B. Ridge, T. Gašpar, and A. Ude. Rapid State Machine Assembly for Modular Robot Control using Meta-Scripting, Templating and Code Generation. In IEEE-RAS 17th International Conference on Humanoid Robots (Humanoids), pages 661–668, Birmingham, UK, November 2017.

Indices and tables