Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tutorials #21

Merged
merged 9 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 257 additions & 0 deletions docs/source/graphics/scxml_tutorial_ros_example_w_bt.drawio.svg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both are called Drainer ..

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
206 changes: 206 additions & 0 deletions docs/source/howto.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
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, `e1`, `e2` and `e3`, that transition each state to the next one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this example, the SCXML model consists of three states, `s0`, `s1`, and `s2`, and three transitions, `e1`, `e2` and `e3`, that transition each state to the next one.
In this example, the SCXML model consists of three states, `s0`, `s1`, and `s2`, and three transitions, these transitions are triggered by the event `e1`, `e2` and `e3` respectively.

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 it more appealing to robotics developers, we have extended the default SCXML language with some ROS and BT specific features.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In order to make it more appealing to robotics developers, we have extended the default SCXML language with some ROS and BT specific features.
In order to fit the techstack of typical robotics developers, we have extended the default SCXML language to support ROS 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 schedule events at a specific rate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* :ref:`ROS Timers <ros_timers>`: to schedule events at a specific rate
* :ref:`ROS Timers <ros_timers>`: to trigger transitions at a specific rate

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, this would be fine. But since events are a concept in SCXML already, this could be misleading.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but transitions are an SCXML concept, too! Will rework it a little

* :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 variables in the SCXML datamodel.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
All functionalities require the interface to be declared before being used, similarly to variables in the SCXML datamodel.
All functionalities require the interface to be declared before being used, similarly to variables in the SCXML datamodel.
And similar to how ROS requires these interfaces to be declared in a node.



.. _ros_timers:

ROS Timers
___________

ROS Timers are used to schedule events at a specific rate. They can be declared as follows:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ROS Timers are used to schedule events at a specific rate. They can be declared as follows:
ROS Timers are used to trigger transitions 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 messages receipt, as in the following:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 messages receipt, as in the following:
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>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 topic, one server and, possibly, multiple clients.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ROS Services are used to provide, for a given topic, one server and, possibly, multiple clients.
ROS Services are used to provide, for a given service, one server and, possibly, multiple clients.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I changed topic to service name... I am always confused by the terminology here: would you define the communication channel of a server a topic, or a service name, just a service, or something different?

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 looks as in the following:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The declaration of a ROS Service server and the one of a client looks as in the following:
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>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
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
28 changes: 28 additions & 0 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. _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/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
python3 -m pip install scxml_converter/
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
Loading