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

SCXML implementation of BT Control Nodes #58

Merged
merged 46 commits into from
Oct 25, 2024
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b5ea3be
Initial verasion of BT control nodes scxml
MarcoLm993 Oct 8, 2024
5cb16d3
Second iteration of scxml_control_nodes
MarcoLm993 Oct 8, 2024
1e353c3
Rename BT Ports scxml declarations
MarcoLm993 Oct 9, 2024
7fd7fc6
One more iteration over the BT Control node SCXML
MarcoLm993 Oct 9, 2024
8bd28ed
STart implementing new scxml bt tags
MarcoLm993 Oct 9, 2024
02b7454
First skeleton on new BT tags
MarcoLm993 Oct 9, 2024
019d6c3
Prepare for testing new bt functionality
MarcoLm993 Oct 9, 2024
045f5f7
Prepare example using new format
MarcoLm993 Oct 9, 2024
1f8f6ff
Start implementing new BT SCXML generator
MarcoLm993 Oct 9, 2024
f86b904
Integrate bt_children ids in the scxml root
MarcoLm993 Oct 9, 2024
f7e8f90
Fix package not found in ipython
MarcoLm993 Oct 9, 2024
f11c651
Move controllers scxml to another folder
MarcoLm993 Oct 9, 2024
dab8efe
Check type of BtTickChild id
MarcoLm993 Oct 9, 2024
64e1ed4
Continue new import of bt plugins
MarcoLm993 Oct 14, 2024
44651f8
Install and import plugins in resources
MarcoLm993 Oct 14, 2024
a9bf8de
Continue integration
MarcoLm993 Oct 14, 2024
bc16c96
Implement missing conversions
MarcoLm993 Oct 14, 2024
5d2f706
First scxml without errors
MarcoLm993 Oct 14, 2024
f93c9e3
Substitution of xml escape sequence and re-order ecmascript entities…
MarcoLm993 Oct 14, 2024
54ea01e
First jani result
MarcoLm993 Oct 14, 2024
e00f599
Various fixes
MarcoLm993 Oct 15, 2024
dc64bac
Fix bug and improve variables naming
MarcoLm993 Oct 15, 2024
dd6f908
Yet another bug
MarcoLm993 Oct 15, 2024
84a3e57
First working version
MarcoLm993 Oct 15, 2024
c018af3
Support for old implementation
MarcoLm993 Oct 15, 2024
6e2692a
Rename battery_depleted_bt_tests
MarcoLm993 Oct 15, 2024
3a9704e
Remove btlib-based BT conversion
MarcoLm993 Oct 15, 2024
9797151
Add input ports support
MarcoLm993 Oct 15, 2024
bc24073
Fixing various tests
MarcoLm993 Oct 15, 2024
0a69d0e
Finish tests fixes
MarcoLm993 Oct 15, 2024
02307be
Adjust BT implementations
MarcoLm993 Oct 15, 2024
8c91364
Fix ReactiveFallback control node
MarcoLm993 Oct 15, 2024
8164302
Documentation
MarcoLm993 Oct 15, 2024
29e7a56
Remove deprecated use of importlib's path
MarcoLm993 Oct 15, 2024
5301d90
Remove unused btlib
MarcoLm993 Oct 15, 2024
bb267d7
Remove old dependencies
MarcoLm993 Oct 15, 2024
46478bd
Fix font path in toml file
MarcoLm993 Oct 15, 2024
aeafe3d
Test for reactive sequence
MarcoLm993 Oct 16, 2024
5cb1a43
Add test for reactive fallbacks
MarcoLm993 Oct 16, 2024
ad544f4
Implement BT sequence model and update test plugin for counting ticks
MarcoLm993 Oct 17, 2024
0a61598
Test for sequence controller
MarcoLm993 Oct 17, 2024
6eb2c4c
Implement Fallback control
MarcoLm993 Oct 17, 2024
c5cb74e
Add test for fallback bt controller
MarcoLm993 Oct 17, 2024
18712ea
Small TODO
MarcoLm993 Oct 18, 2024
2a3c64c
Prevent extra self-loops in the BT root jani automaton
MarcoLm993 Oct 18, 2024
e5d3666
Always return a List of transitions when instantiating BT events
MarcoLm993 Oct 25, 2024
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
Prev Previous commit
Next Next commit
Test for reactive sequence
Signed-off-by: Marco Lampacrescia <marco.lampacrescia@de.bosch.com>
MarcoLm993 committed Oct 16, 2024
commit aeafe3d8495de2fd5d44f997ad2cb6df3881aae1
32 changes: 32 additions & 0 deletions src/as2fm/resources/bt_control_nodes/always_failure.scxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<scxml
xmlns="http://www.w3.org/2005/07/scxml"
initial="idle"
version="1.0"
name="AlwaysFailure"
model_src="https://raw.githubusercontent.com/BehaviorTree/BehaviorTree.CPP/refs/heads/v3.8/include/behaviortree_cpp_v3/actions/always_failure_node.h">

<!-- A default BT port reporting the amount of children -->
<bt_declare_port_in key="CHILDREN_COUNT" type="int8" />

<datamodel>
<data id="children_count" type="int8">
<expr>
<bt_get_input key="CHILDREN_COUNT" />
</expr>
</data>
</datamodel>

<state id="idle">
<!-- Check if the state is valid. If not, go to error and stop -->
<transition target="error" cond="children_count != 0" />
<!-- React to an incoming BT Tick -->
<bt_tick target="idle">
<bt_return_status status="FAILURE" />
</bt_tick>
</state>

<!-- A state to transition to when something did not work -->
<state id="error" />

</scxml>
32 changes: 32 additions & 0 deletions src/as2fm/resources/bt_control_nodes/always_success.scxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<scxml
xmlns="http://www.w3.org/2005/07/scxml"
initial="idle"
version="1.0"
name="AlwaysSuccess"
model_src="https://raw.githubusercontent.com/BehaviorTree/BehaviorTree.CPP/refs/heads/v3.8/include/behaviortree_cpp_v3/actions/always_success_node.h">

<!-- A default BT port reporting the amount of children -->
<bt_declare_port_in key="CHILDREN_COUNT" type="int8" />

<datamodel>
<data id="children_count" type="int8">
<expr>
<bt_get_input key="CHILDREN_COUNT" />
</expr>
</data>
</datamodel>

<state id="idle">
<!-- Check if the state is valid. If not, go to error and stop -->
<transition target="error" cond="children_count != 0" />
<!-- React to an incoming BT Tick -->
<bt_tick target="idle">
<bt_return_status status="SUCCESS" />
</bt_tick>
</state>

<!-- A state to transition to when something did not work -->
<state id="error" />

</scxml>
31 changes: 31 additions & 0 deletions test/jani_generator/_test_data/bt_test_models/bt_count_ticks.scxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<scxml
xmlns="http://www.w3.org/2005/07/scxml"
initial="initial"
version="1.0"
name="BtCountTicks"
model_src="">

<datamodel>
<data id="counter" type="int16" expr="0" />
</datamodel>

<bt_declare_port_in key="topic_name" type="string" />

<ros_topic_publisher type="std_msgs/Int16" name="counter_pub">
<topic>
<bt_get_input key="topic_name" />
</topic>
</ros_topic_publisher>

<state id="initial">
<bt_tick target="initial">
<assign location="counter" expr="counter + 1" />
<ros_topic_publish name="counter_pub">
<field name="data" expr="counter" />
</ros_topic_publish>
<bt_return_status status="SUCCESS" />
</bt_tick>
</state>

</scxml>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- First test: We expect that tick_count_0 is ticked multiple times and tick_count_1 is never ticked -->
<root BTCPP_format="4" >
<BehaviorTree ID="MainTree">
<ReactiveSequence name="root_sequence">
<Action ID="BtCountTicks" topic_name="tick_count_0" />
<Action ID="AlwaysFailure" />
<Action ID="BtCountTicks" topic_name="tick_count_1" />
</ReactiveSequence>
</BehaviorTree>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<convince_mc_tc>
<mc_parameters>
<max_time value="100" unit="s" />
<bt_tick_rate value="1.0" />
</mc_parameters>

<behavior_tree>
<input type="bt.cpp-xml" src="./bt_test_reactive_sequence.xml" />
<input type="bt-plugin-ros-scxml" src="./bt_count_ticks.scxml" />
</behavior_tree>

<properties>
<input type="jani" src="./property_test_reactive_sequence.jani" />
</properties>
</convince_mc_tc>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"properties": [
{
"name": "ten_tick_zero_no_tick_one",
"expression": {
"op": "filter",
"fun": "values",
"values": {
"op": "Pmin",
"exp": {
"step-bounds": {
"lower": 100
},
"left": true,
"op": "U",
"right": {
"left": {
"op": "=",
"left": "topic_tick_count_0_msg.ros_fields__data",
"right": 10
},
"op": "∧",
"right": {
"op": "¬",
"exp": "topic_tick_count_1_msg.valid"
}
}
}
},
"states": {
"op": "initial"
}
}
}
]
}
77 changes: 77 additions & 0 deletions test/jani_generator/test_systemtest_behavior_tree_scxml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Copyright (c) 2024 - for information on the respective copyright owner
# see the NOTICE file

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Test the SCXML conversion to JANI"""

import os
import unittest

import pytest

from as2fm.jani_generator.scxml_helpers.top_level_interpreter import interpret_top_level_xml

from ..as2fm_common.test_utilities_smc_storm import run_smc_storm_with_output


# pylint: disable=too-many-public-methods
class TestConversion(unittest.TestCase):
"""
Test the conversion of SCXML to JANI.
"""

def _test_with_main(self, path_to_main_xml: str, property_name: str, success: bool):
"""
Testing the model resulting from the main xml file with the entrypoint.

:param path_to_main_xml: The path to the main xml file.
:param property_name: The property name to test.
:param success: If the property is expected to be always satisfied or always not satisfied.
"""
test_folder = os.path.join(os.path.dirname(__file__), "_test_data")
main_xml_full_path = os.path.join(test_folder, path_to_main_xml)
generated_scxml_path = "generated_plain_scxml"
jani_file = "main.jani"
test_folder = os.path.dirname(main_xml_full_path)
interpret_top_level_xml(main_xml_full_path, "main.jani", generated_scxml_path)
jani_file_path = os.path.join(test_folder, jani_file)
generated_scxml_path = os.path.join(test_folder, generated_scxml_path)
self.assertTrue(os.path.exists(jani_file_path))
pos_res = "Result: 1" if success else "Result: 0"
neg_res = "Result: 0" if success else "Result: 1"
run_smc_storm_with_output(
f"--model {jani_file_path} --properties-names {property_name}",
[property_name, jani_file_path, pos_res],
[neg_res],
)
# Remove generated file (in case of test passed)
if os.path.exists(jani_file_path):
os.remove(jani_file_path)
if os.path.exists(generated_scxml_path):
for file in os.listdir(generated_scxml_path):
assert file.endswith(".scxml")
os.remove(os.path.join(generated_scxml_path, file))
os.removedirs(generated_scxml_path)

def test_reactive_sequence(self):
"""Test the reactive_sequence behavior."""
self._test_with_main(
os.path.join("bt_test_models", "main_test_reactive_sequence.xml"),
"ten_tick_zero_no_tick_one",
True,
)


if __name__ == "__main__":
pytest.main(["-s", "-v", __file__])
2 changes: 1 addition & 1 deletion test/jani_generator/test_systemtest_scxml_to_jani.py
Original file line number Diff line number Diff line change
@@ -218,7 +218,7 @@ def _test_with_main(
:param folder: The folder containing the test data.
:param store_generated_scxmls: If the generated SCXMLs should be stored.
:param property_name: The property name to test.
:param success: If the property is expected to be always satisfied of always not satisfied.
:param success: If the property is expected to be always satisfied or always not satisfied.
:param skip_smc: If the model shall be executed using SMC (uses smc_storm).
"""
test_data_dir = os.path.join(os.path.dirname(__file__), "_test_data", folder)