Skip to content

Commit

Permalink
Improve tutorials (#21)
Browse files Browse the repository at this point in the history
Signed-off-by: Marco Lampacrescia <[email protected]>
  • Loading branch information
MarcoLm993 authored Aug 14, 2024
1 parent 9a9e181 commit bec6b2e
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 66 deletions.
257 changes: 257 additions & 0 deletions docs/source/graphics/scxml_tutorial_ros_example_w_bt.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
232 changes: 232 additions & 0 deletions docs/source/howto.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
.. _howto:

How To Guides
=============


.. _scxml_howto:

(ROS) SCXML Model Implementation
---------------------------------

SCXML is the language of choice to model the autonomous systems that we will be processed by AS2FM.

It relies on multiple SCXML files, each one representing a different state-based automaton, to represent a complete system.
Those automaton can exchange data and synchronize their execution through the use of **events**.

A simple, exemplary SCXML model is shown below:

.. code-block:: xml
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="s0">
<datamodel>
<data id="counter" expr="0" type="int16"/>
</datamodel>
<state id="s0">
<transition event="e1" target="s1">
<assign location="counter" expr="counter + 1"/>
</transition>
</state>
<state id="s1">
<transition event="e2" target="s2">
<assign location="counter" expr="counter + 1"/>
</transition>
</state>
<state id="s2">
<onentry>
<send event="extra_event"/>
</onentry>
<transition event="e3" target="s0">
<assign location="counter" expr="counter + 1"/>
</transition>
</state>
</scxml>
In this example, the SCXML model consists of three states, `s0`, `s1`, and `s2`, and three transitions, triggered by the events `e1`, `e2` and `e3`, respectively. Each transition will advance the automaton state to the next one.
Additionally, on each transition, a counter is incremented.

The events are expected to be sent by another scxml model, similarly to how it is done in the `s2` state.

In order to make SCXML fit more the typical robotics tech-stack, we extended the default SCXML language to support ROS specific specific features and Behavior Trees.

The following sections will guide you through the process of :ref:`creating a SCXML model of a ROS node <ros_node_scxml>` and of a :ref:`BT plugin <bt_plugin_scxml>` that can be processed by AS2FM.


.. _ros_node_scxml:

Creating a SCXML model of a ROS node
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In AS2FM, we extended the SCXML language with some additional functionalities, to support the following ROS specific features:

* :ref:`ROS Timers <ros_timers>`: to trigger callbacks at a specific rate
* :ref:`ROS Topics <ros_topics>`: to publish-receive messages via a ROS topic
* :ref:`ROS Services <ros_services>`: to call a ROS service and implement service servers
* :ref:`ROS Actions <ros_actions>`: to call a ROS action and implement action servers (under development)

All functionalities require the interface to be declared before being used, similarly to how ROS requires the interfaces to be declared in a node.
In (ROS) SCXML, this is done similarly to how variables are defined in the datamodel.

.. _ros_timers:

ROS Timers
___________

ROS Timers are used to trigger callbacks (behaving like an SCXML transition) at a specific rate. They can be declared as follows:

.. code-block:: xml
<ros_time_rate rate_hz="1" name="my_timer" />
This will create a ROS Timer that triggers the related callbacks at a rate of 1 Hz, w.r.t. the internal, simulated time.

The timer callbacks can be used similarly to SCXML transitions, and are specified as follows:

.. code-block:: xml
<state id="src_state">
<ros_rate_callback name="my_timer" target="target_state" cond="cond_expression">
<assign location="internal_var" expr="some_expression" />
</ros_rate_callback>
</state>
Assuming the automaton is in the `src_state`, the transition to `target_state` will be triggered by the timer `my_timer`, if the condition `cond_expression` holds.
Additionally, the internal variable `internal_var` will be updated with the value of `some_expression` when that transition is performed.


.. _ros_topics:

ROS Topics
___________

ROS Topics are used to publish (via a ROS Publisher) and receive (via a ROS Subscriber) messages via a ROS topic across different automata. They can be declared as follows:

.. code-block:: xml
<!-- ROS Topic Subscriber -->
<ros_topic_subscriber topic="/topic1" type="std_msgs/Bool" />
<!-- ROS Topic Publisher -->
<ros_topic_publisher topic="/topic2" type="std_msgs/Int32" />
Once created, subscribers and publishers can be referenced using the `topic` name, and can be used in the states to send messages and perform callbacks upon receiving messages:

.. code-block:: xml
<datamodel>
<data id="internal_bool" expr="True" type="bool" />
</datamodel>
<state id="src_state">
<ros_topic_callback topic="/topic1" target="target_state">
<assign location="internal_var" expr="_msg.data" />
</ros_topic_callback>
</state>
<state id="target_state">
<onentry>
<if cond="internal_bool">
<ros_topic_publish topic="/topic2" >
<field name="data" expr="10">
</ros_topic_publish>
<else />
<ros_topic_publish topic="/topic2" >
<field name="data" expr="20">
</ros_topic_publish>
</if>
</onentry>
<transition target="src_state" />
</state>
Note that the `ros_topic_publish` can be used where one would normally use executable content in SCXML: in `transition`s, in `onentry` and `onexit` tags.
The `ros_topic_callback` tag is similarly to the `ros_rate_callback` used like a transition and will transition the state machine to the state declared in `target` upon receiving a message.
Executable content within it can use `_msg` to access the message content.

.. _ros_services:

ROS Services
____________

ROS Services are used to provide, for a given service name, one server and, possibly, multiple clients.
The clients makes a request and the server provides a response to that request only to the client that made the request.

The declaration of a ROS Service server and the one of a client can be achieved like this:

.. code-block:: xml
<!-- ROS Service Server -->
<ros_service_server service_name="/service1" type="std_srvs/SetBool" />
<!-- ROS Service Client -->
<ros_service_client service_name="/service2" type="std_srvs/Trigger" />
Once created, servers and clients can be referenced using the `service_name` name, and can be used in the states of a SCXML model to provide and request services.
In the following, an exemplary client is provided:

.. code-block:: xml
<datamodel>
<data id="internal_bool" expr="False" type="bool" />
</datamodel>
<state id="send_req">
<onentry>
<ros_service_send_request service_name="/service2">
</ros_service_send_request>
</onentry>
<ros_service_handle_response service_name="/service2" target="done">
<assign location="internal_bool" expr="_res.success" />
</ros_service_handle_response>
</state>
To send a request, the `ros_service_send_request` can be used where any other executable content may be used.
After the server has processed the service, `ros_service_handle_response`, can be used similarly to a SCXML transition and is triggered by the server.
The data of the request can be accessed with the `_res` field.

And here, an example of a server:

.. code-block:: xml
<datamodel>
<data id="temp_data" type="bool" expr="False" />
</datamodel>
<state id="idle">
<ros_service_handle_request service_name="/service1" target="idle">
<assign location="temp_data" expr="_req.data" />
<ros_service_send_response service_name="/adder">
<field name="success" expr="temp_data" />
</ros_service_send_response>
</ros_service_handle_request>
</state>
A service request from a client will trigger the `ros_service_handle_request` callback which transitions the automaton to the state declared in `target` (it is a self loop in the example).
After processing the request the server must use the `ros_service_send_response` to send the response.


.. _ros_actions:

ROS Actions
___________

TODO


.. _bt_plugin_scxml:

Creating a SCXML model of a BT plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

TODO


.. _additional_params_howto:

Additional Parameters for the Main XML file
-------------------------------------------


.. _max_time_tag:

Max Time
~~~~~~~~

TODO
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ Contents
.. toctree::
:maxdepth: 2

installation
tutorials
howto
scxml-jani-conversion
api
contacts
34 changes: 34 additions & 0 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.. _installation:

Installation
--------------

Pre-requisites
^^^^^^^^^^^^^^

The scripts have been tested with Python 3.10 and pip version 24.0.

Additionally, the following dependencies are required to be installed:

* `ROS Humble <https://docs.ros.org/en/humble/index.html>`_
* `bt_tools <https://github.com/boschresearch/bt_tools>`_


AS2FM packages installation
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Before installing the AS2FM packages, make sure to source the ROS workspace containing the `bt_tools` package by executing ``source <path_to_ws>/install/setup.bash``.

Afterwards, install the AS2FM packages with the following commands:

.. code-block:: bash
python3 -m pip install as2fm_common/
python3 -m pip install jani_generator/
python3 -m pip install scxml_converter/
Verify your installation by running:

.. code-block:: bash
scxml_to_jani --help
6 changes: 4 additions & 2 deletions docs/source/scxml-jani-conversion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ Jani Conversion

Once the Low-Level SCXML is obtained, we can use it together with the timers information in the conversion to a Jani model.

.. _simple_overview:

Simple Overview
________________
.. _simple_overview:

The following picture gives a simple overview of how our conversion works:

Expand Down Expand Up @@ -81,9 +82,10 @@ TODO
:alt: How execution blocks and conditions are translated
:align: center

.. _handling_events:

Handling events
________________
.. _handling_events:

In section :ref:`Simple Overview<simple_overview>` we introduced the basic concept of how events are handled in the conversion from SCXML to Jani.
That concept works for the simplest cases, but there are more complex scenarios where problems may occur, and require special handling.
Expand Down
Loading

0 comments on commit bec6b2e

Please sign in to comment.