Note: This tutorial assumes that you have completed the previous tutorials: Run RSM.
(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Writing a Plugin State

Description: How to write a plugin state for the Robot Statemachine and properly setup the package where it will be in

Tutorial Level: ADVANCED

Next Tutorial: Use Plugin State in RSM

Package Configuration

To create a plugin state to be used with the robot RSM follow the upcoming steps. This is very similar to the ROS tutorial Writing and Using a Simple Plugin but also includes some specific details for the RSM.

In your package, add the following code to the respective files:

CMakeLists.txt:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  pluginlib
  rsm_core
  rsm_msgs
  ...
)

package.xml:

...
<build_depend>pluginlib</build_depend>
<build_export_depend>pluginlib</build_export_depend>
<exec_depend>pluginlib</exec_depend>
<exec_depend>rsm_core</exec_depend>
<build_depend>rsm_core</build_depend>
<build_export_depend>rsm_core</build_export_depend>
<build_depend>rsm_msgs</build_depend>
<build_export_depend>rsm_msgs</build_export_depend>
<exec_depend>rsm_msgs</exec_depend>
...

This adds all dependencies needed to use the pluginlib and include the Base State.

Plugin Implementation

Next, create a class consisting of a header and source file in the respective directory in your package. The class needs to inherit from the Base State, interact with the State Interface and declare it is a plugin. The code for header and source are shown below.

ExampleState.h:

   1 #include <pluginlib/class_list_macros.h>
   2 #include <rsm_core/BaseState.h>
   3 #include <rsm_core/StateInterface.h>
   4 
   5 namespace rsm {
   6 
   7 class ExampleState: public BaseState {
   8 
   9 public:
  10         ExampleState();
  11         ~ExampleState();
  12         void onSetup();
  13         void onEntry();
  14         void onActive();
  15         void onExit();
  16         void onExplorationStart(bool &success, std::string &message);
  17         void onExplorationStop(bool &success, std::string &message);
  18         void onWaypointFollowingStart(bool &success, std::string &message);
  19         void onWaypointFollowingStop(bool &success, std::string &message);
  20         void onInterrupt(int interrupt);
  21 };
  22 
  23 }

ExampleState.cpp:

   1 #include "ExampleState.h"
   2 
   3 namespace rsm {
   4 
   5 ExampleState::ExampleState() {
   6         //...
   7 }
   8 
   9 ExampleState::~ExampleState() {
  10         //...
  11 }
  12 
  13 void ExampleState::onSetup() {
  14         //...
  15 }
  16 
  17 void ExampleState::onEntry() {
  18         //...
  19 }
  20 
  21 void ExampleState::onActive() {
  22         //...
  23 }
  24 
  25 void ExampleState::onExit() {
  26         //...
  27 }
  28 
  29 void ExampleState::onExplorationStart(bool &success,
  30                 std::string &message) {
  31         //...
  32 }
  33 
  34 void ExampleState::onExplorationStop(bool &success,
  35                 std::string &message) {
  36         //...
  37 }
  38 
  39 void ExampleState::onWaypointFollowingStart(bool &success,
  40                 std::string &message) {
  41         //...
  42 }
  43 
  44 void ExampleState::onWaypointFollowingStop(bool &success,
  45                 std::string &message) {
  46         //...
  47 }
  48 
  49 void ExampleState::onInterrupt(int interrupt) {
  50         //...
  51 }
  52 
  53 }
  54 
  55 PLUGINLIB_EXPORT_CLASS(rsm::ExampleState,
  56                 rsm::BaseState)

The state plugin needs to implement all methods declared in the Base State as virtual and enables to add arbitrary functionality to them. The PLUGINLIB_EXPORT_CLASS macro registers the class as a plugin to the pluginlib.

Plugin Export

To make the plugin available to ROS, an XML file needs to be added in the package that declares them as a library. The file should look like this:

rsm_example_plugins.xml:

<library path="lib/librsm_example_plugins">
        <class type="rsm::ExampleState"
                base_class_type="rsm::BaseState">
                <description>This is the example state.</description>
        </class>
        ...
</library>

It can feature multiple classes to declare in the same manner. The plugin library needs to be exported as well. Therefore the following lines need to be added to the package.xml:

<export>
        <rsm_core plugin="${prefix}/rsm_example_plugins.xml" />
</export>

Note: There can only be one export bracket in each package.xml.

Check Plugin Implementation

With the following statement you can check in the terminal if the plugin was registered correctly:

rospack plugins --attrib=plugin rsm_core

It should show:

"your_package_name" /"your_workspace_path"/src/"your_package_name"/rsm_example_plugins.xml
rsm_additions /"your_workspace_path"/src/robot_statemachine/rsm_additions/rsm_plugins.xml

You can now use the plugin state in the RSM.

Wiki: robot_statemachine/Tutorials/WritingAPluginState (last edited 2020-03-30 07:04:04 by MarcoSteinbrink)