Factory Demo (C++)

This tutorial demonstrates how to load YASMIN state machines from XML files using the YasminFactory in C++. This approach separates the FSM structure from the code, making it easier to design, share, and modify state machines without recompiling.

Background

The YASMIN Factory provides:

1. Create an XML State Machine

Define your state machine structure in an XML file (e.g., demo_1.xml):

<StateMachine outcomes="outcome4">
    <State name="Foo" type="py" module="yasmin_demos.foo_state" class="FooState">
        <Transition from="outcome1" to="Bar"/>
        <Transition from="outcome2" to="outcome4"/>
    </State>
    <State name="Bar" type="cpp" class="yasmin_demos/BarState">
        <Transition from="outcome3" to="Foo"/>
    </State>
</StateMachine>

Running the Demo

ros2 run yasmin_demos factory_demo

Source Code

You can find the full source code in the yasmin_demos package.

#include <iostream>
#include <memory>
#include <string>

#include "ament_index_cpp/get_package_share_directory.hpp"
#include "rclcpp/rclcpp.hpp"
#include "yasmin/state_machine.hpp"
#include "yasmin_factory/yasmin_factory.hpp"
#include "yasmin_ros/ros_logs.hpp"

int main(int argc, char *argv[]) {
  YASMIN_LOG_INFO("yasmin_factory_demo");
  rclcpp::init(argc, argv);

  // Set up ROS 2 loggers
  yasmin_ros::set_ros_loggers();

  std::string outcome;

  // Create the factory in a scope
  yasmin_factory::YasminFactory factory;

  // Load state machine from XML file
  std::string xml_file =
      ament_index_cpp::get_package_share_directory("yasmin_demos") +
      "/state_machines/demo_2.xml";

  // Create the state machine from the XML file
  auto sm = factory.create_sm_from_file(xml_file);

  // Execute the state machine
  try {
    std::string outcome = (*sm.get())();
    YASMIN_LOG_INFO(outcome.c_str());
  } catch (const std::exception &e) {
    YASMIN_LOG_WARN(e.what());
  }

  // Shutdown ROS 2
  rclcpp::shutdown();
  return 0;
}