Skip to content

Commit

Permalink
Generated gh-pages for commit 62d767e
Browse files Browse the repository at this point in the history
Author: Dennis Holzmann <[email protected]>

    add examples
  • Loading branch information
dholzmann committed Oct 31, 2024
1 parent 112b5e5 commit 5702fa6
Show file tree
Hide file tree
Showing 37 changed files with 1,811 additions and 25 deletions.
1 change: 1 addition & 0 deletions _sources/behavior.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ The Bonsai SCXML utilises this to couple skills to rich behavior.

Intro <behavior/scxml-intro>
Statemachine Configuration <behavior/config>
Examples <behavior/scxml-examples>
28 changes: 28 additions & 0 deletions _sources/behavior/example/compound.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
============
Compound States
============

States can consist of multiple other states. These states are grouped:

.. code-block:: xml
<state id="DoCoolStuff" initial="example.Succeeder">
<!-- we can also define transitions here -->
<!-- The parent states transition gets checked if none of the childs matches -->
<transition event="Succeeder.*" target="Fatal"/>
<state id="example.Succeeder">
<transition event="Succeeder.success" target="example.Succeeder#again"/>
</state>
<state id="example.Succeeder#again">
<transition event="Succeeder.success" target="example.Nothing"/>
</state>
</state>
<state id="example.Nothing">
<!-- this is a easy reference to transition too -->
<transition event="Nothing.fatal" target="DoCoolStuff"/>
</state>
130 changes: 130 additions & 0 deletions _sources/behavior/example/memory-slots.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
============
Memory Slots
============

Skills
------

Slots are used to store data for other skills/states to use.

Take a look at the SlotWriter and SlotReader skill:

.. code-block:: kotlin
class SlotWriter : AbstractSkill() {
private var tokenSuccess: ExitToken? = null
private var slot: MemorySlotWriter<String>? = null
override fun configure(configurator: ISkillConfigurator) {
tokenSuccess = configurator.requestExitToken(ExitStatus.SUCCESS())
slot = configurator.getWriteSlot("StringToWriteTo", String::class.java)
}
override fun init(): Boolean {
return true
}
override fun execute(): ExitToken {
slot!!.memorize("Hello World")
return tokenSuccess!!
}
override fun end(curToken: ExitToken): ExitToken {
return curToken
}
}
.. code-block:: kotlin
class SlotReader : AbstractSkill() {
private var tokenSuccess: ExitToken? = null
private var slot: MemorySlot<String>? = null
private var read: String? = ""
override fun configure(configurator: ISkillConfigurator) {
tokenSuccess = configurator.requestExitToken(ExitStatus.SUCCESS())
slot = configurator.getReadSlot<String>("StringIAmReading", String::class.java)
}
override fun init(): Boolean {
read = slot!!.recall<String>() ?: return false
return true
}
override fun execute(): ExitToken {
logger.info("current data: $read")
return tokenSuccess!!
}
override fun end(curToken: ExitToken): ExitToken {
return curToken
}
}
Both want to access a slot which stores strings.
The SlotWriter requests access to the slot with the key "StringToWriteTo" in which he wants to write The string "Hello World":

.. code-block:: kotlin
slot = configurator.getWriteSlot("StringToWriteTo", String::class.java)
// ... some other code ...
override fun execute(): ExitToken {
slot!!.memorize("Hello World")
return tokenSuccess!!
}
The SlotReader on the other hand requests a slot to read a string from.
The read data is then simply printed:

.. code-block:: kotlin
slot = configurator.getReadSlot<String>("StringIAmReading", String::class.java)
// ... some other code ...
override fun init(): Boolean {
read = slot!!.recall<String>() ?: return false
return true
}
override fun execute(): ExitToken {
logger.info("current data: $read")
return tokenSuccess!!
}
State Machine
-------------

Now that we have the skills to read and write, we need to integrate them into our state machine.
The skills require slots with the keys "StringToWriteTo" and "StringIAmReading".
We have to assign a path for the slots in the state machine.
The paths should be the same, so that the writer writes "hello World" and the reader then reads the same string.
The path for the slots have to be defined in the datamodel. The data id needs to be "#_SLOTS".
There, we can define the path for each slot key.

.. code-block:: xml
<datamodel>
<data id="#_STATE_PREFIX" expr="'de.unibi.citec.clf.bonsai.skills.'"/>
<!-- slots are used to store data for other skills/states to use -->
<!-- we have to define the path for each used slot -->
<data id="#_SLOTS">
<slots>
<slot key="StringToWriteTo" state="example.SlotWriter" xpath="/path"/>
<slot key="StringIAmReading" state="example.SlotReader" xpath="/path"/>
</slots>
</data>
</datamodel>
.. warning::
Keep in mind that the slot key in the datamodel of the state machine needs to be the same as in the skill!

With the keys being setup correctly, the slot writer will write the string to the /path path and the reader will read from it.
140 changes: 140 additions & 0 deletions _sources/behavior/example/parameter.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
============
Parameters and Variables
============

Parameters
----------

Some skills require further parameters that you don't necessarily want to write in a slot.
For that case, the state machine enables propagating parameters to the skill.

For example, the skill ParameterHaver defines two parameters "value" and "optional":

.. code-block:: kotlin
class ParameterHaver : AbstractSkill() {
private var value = ""
private var optional = false
//...
override fun configure(configurator: ISkillConfigurator) {
// ...
value = configurator.requestValue("value")
optional = configurator.requestOptionalBool("option", optional)
}
// ...
}
Each Parameters needs to be requested by the configurator.
The "optional" parameter here is an optional bool value.

When we are using this skill in the state machine, we can provide the skill with these parameters.
The parameter "value" *must* be provided in the state machine. The parameters have to be set in a datamodel **within** the state:

.. code-block:: xml
<state id="example.ParameterHaver">
<!-- skill parameter are read from the state datamodel -->
<datamodel>
<data id="value" expr="'Hello'"/>
</datamodel>
<transition event="ParameterHaver.*" target="example.ParameterHaver#option"/>
</state>
<state id="example.ParameterHaver#option">
<datamodel>
<data id="value" expr="'World'"/>
<data id="option" expr="true"/>
</datamodel>
<transition event="ParameterHaver.*" target="End"/>
</state>
.. warning::
Make sure to use extra quotes for strings! ``<data id="value" expr="'Hello'"/>``.
Booleans and numbers do not need the extra quotes.


Variables
---------

Variables are not specific for each state but rather for the whole state machine. As such, they are defined in the datamodel of the state machine:

.. code-block:: xml
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="example.ParameterHaver">
<datamodel>
<data id="hellosToSpeak" expr="3"/>
</datamodel>
<state id="example.ParameterHaver">
<datamodel>
<data id="value" expr="'@hellosToSpeak'"/>
</datamodel>
<transition event="ParameterHaver.*" target="End" />
</state>
</scxml>
The ParameterHaver skill gets the "hellosToSpeak" variable assigned as parameter.

.. warning::
Since the "value" parameter needs to be a string, we need to add quotes and a @ to get the variable as string:
``<data id="value" expr="'@hellosToSpeak'"/>``

During transitions we can execute SCXML actions.
The variables can be changed by assigning them a new value using the "assign" action:

.. code-block:: xml
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="example.ParameterHaver">
<datamodel>
<data id="hellosToSpeak" expr="3"/>
</datamodel>
<state id="example.ParameterHaver">
<datamodel>
<data id="value" expr="'Hello'"/>
</datamodel>
<transition event="ParameterHaver.*" target="example.ParameterHaver" >
<assign name="hellosToSpeak" expr="hellosToSpeak - 1"/>
</transition>
</state>
</scxml>
With variables, we also can introduce conditions in transitions. For example, as long as "hellosToSpeak" is greater than 1, we want ParameterHaver to be executed again.
This can be done by adding ``cond="hellosToSpeak > 1"`` in the transition. Another transition without any conditions is then defined at the end:

.. code-block:: xml
<state id="example.ParameterHaver">
<datamodel>
<data id="value" expr="'Hello'"/>
</datamodel>
<transition event="ParameterHaver.*" cond="hellosToSpeak > 1" target="example.ParameterHaver">
<assign name="hellosToSpeak" expr="hellosToSpeak - 1"/>
</transition>
<transition event="ParameterHaver.*" target="End" />
</state>
On Entry/Exit
--------

We can also use the on_entry/on_exit actions of the state to assign some values to a variable.
The on_entry action here decrements the "hellosToSpeak" variable each time the state machine transitions back to the state:

.. code-block:: xml
<state id="example.ParameterHaver">
<datamodel>
<data id="value" expr="'Hello'"/>
</datamodel>
<onentry>
<assign name="hellosToSpeak" expr="hellosToSpeak - 1"/>
</onentry>
<transition event="ParameterHaver.*" cond="hellosToSpeak > 0" target="example.ParameterHaver" />
<transition event="ParameterHaver.*" target="End" />
</state>
Loading

0 comments on commit 5702fa6

Please sign in to comment.