diff --git a/Docs/CHANGELOG.md b/Docs/CHANGELOG.md index a85218b14..d5078cceb 100644 --- a/Docs/CHANGELOG.md +++ b/Docs/CHANGELOG.md @@ -16,6 +16,9 @@ ### :bug: Bug Fixes * Fixed exception when using OSC scenarios without EnvironmentAction inside Storyboard-Init * Fixed bug causing the TrafficManager to not be correctly updated at asynchronous simualtions +### :ghost: Maintenance +* Added check to ensure OSC names (for story/act/maneuver) are unique + ## CARLA ScenarioRunner 0.9.10 diff --git a/srunner/scenarios/open_scenario.py b/srunner/scenarios/open_scenario.py index f50d6ce99..2a5263f92 100644 --- a/srunner/scenarios/open_scenario.py +++ b/srunner/scenarios/open_scenario.py @@ -18,8 +18,8 @@ from srunner.scenariomanager.scenarioatomics.atomic_behaviors import ChangeActorControl, ChangeActorTargetSpeed from srunner.scenariomanager.timer import GameTime from srunner.scenarios.basic_scenario import BasicScenario -from srunner.tools.openscenario_parser import OpenScenarioParser -from srunner.tools.py_trees_port import Decorator, oneshot_behavior +from srunner.tools.openscenario_parser import OpenScenarioParser, oneshot_with_check +from srunner.tools.py_trees_port import Decorator def repeatable_behavior(behaviour, name=None): @@ -203,8 +203,8 @@ def _create_environment_behavior(self): OpenScenarioParser.get_weather_from_env_action(self.config.init, self.config.catalogs)) road_friction = ChangeRoadFriction( OpenScenarioParser.get_friction_from_env_action(self.config.init, self.config.catalogs)) - env_behavior.add_child(oneshot_behavior(variable_name="InitialWeather", behaviour=weather_update)) - env_behavior.add_child(oneshot_behavior(variable_name="InitRoadFriction", behaviour=road_friction)) + env_behavior.add_child(oneshot_with_check(variable_name="InitialWeather", behaviour=weather_update)) + env_behavior.add_child(oneshot_with_check(variable_name="InitRoadFriction", behaviour=road_friction)) return env_behavior @@ -311,10 +311,10 @@ def _create_behavior(self): maneuver_behavior = StoryElementStatusToBlackboard( maneuver_behavior, "ACTION", child.attrib.get('name')) parallel_actions.add_child( - oneshot_behavior(variable_name=# See note in get_xml_path - get_xml_path(self.config.story, sequence) + '>' + \ - get_xml_path(maneuver, child), - behaviour=maneuver_behavior)) + oneshot_with_check(variable_name=# See note in get_xml_path + get_xml_path(self.config.story, sequence) + '>' + \ + get_xml_path(maneuver, child), + behaviour=maneuver_behavior)) if child.tag == "StartTrigger": # There is always one StartConditions block per Event @@ -327,15 +327,15 @@ def _create_behavior(self): parallel_actions, "EVENT", event.attrib.get('name')) event_sequence.add_child(parallel_actions) maneuver_parallel.add_child( - oneshot_behavior(variable_name=get_xml_path(self.config.story, sequence) + '>' + - get_xml_path(maneuver, event), # See get_xml_path - behaviour=event_sequence)) + oneshot_with_check(variable_name=get_xml_path(self.config.story, sequence) + '>' + + get_xml_path(maneuver, event), # See get_xml_path + behaviour=event_sequence)) maneuver_parallel = StoryElementStatusToBlackboard( maneuver_parallel, "MANEUVER", maneuver.attrib.get('name')) single_sequence_iteration.add_child( - oneshot_behavior(variable_name=get_xml_path(self.config.story, sequence) + '>' + - maneuver.attrib.get('name'), # See get_xml_path - behaviour=maneuver_parallel)) + oneshot_with_check(variable_name=get_xml_path(self.config.story, sequence) + '>' + + maneuver.attrib.get('name'), # See get_xml_path + behaviour=maneuver_parallel)) # OpenSCENARIO refers to Sequences as Scenes in this instance single_sequence_iteration = StoryElementStatusToBlackboard( @@ -347,8 +347,8 @@ def _create_behavior(self): if sequence_behavior.children: parallel_sequences.add_child( - oneshot_behavior(variable_name=get_xml_path(self.config.story, sequence), - behaviour=sequence_behavior)) + oneshot_with_check(variable_name=get_xml_path(self.config.story, sequence), + behaviour=sequence_behavior)) if parallel_sequences.children: parallel_sequences = StoryElementStatusToBlackboard( @@ -383,11 +383,11 @@ def _create_behavior(self): env_behavior = self._create_environment_behavior() if env_behavior is not None: - behavior.add_child(oneshot_behavior(variable_name="InitialEnvironmentSettings", behaviour=env_behavior)) + behavior.add_child(oneshot_with_check(variable_name="InitialEnvironmentSettings", behaviour=env_behavior)) init_behavior = self._create_init_behavior() if init_behavior is not None: - behavior.add_child(oneshot_behavior(variable_name="InitialActorSettings", behaviour=init_behavior)) + behavior.add_child(oneshot_with_check(variable_name="InitialActorSettings", behaviour=init_behavior)) behavior.add_child(story_behavior) @@ -419,7 +419,7 @@ def _create_condition_container(self, node, name='Conditions Group', sequence=No get_xml_path(maneuver, condition) # See note in get_xml_path else: xml_path = get_xml_path(self.config.story, condition) - criterion = oneshot_behavior(variable_name=xml_path, behaviour=criterion) + criterion = oneshot_with_check(variable_name=xml_path, behaviour=criterion) condition_group_sequence.add_child(criterion) if condition_group_sequence.children: diff --git a/srunner/tools/openscenario_parser.py b/srunner/tools/openscenario_parser.py index 13f60e3f8..63bd4dc15 100644 --- a/srunner/tools/openscenario_parser.py +++ b/srunner/tools/openscenario_parser.py @@ -9,6 +9,8 @@ This module provides a parser for scenario configuration files based on OpenSCENARIO """ +from __future__ import print_function + from distutils.util import strtobool import copy import datetime @@ -66,6 +68,19 @@ from srunner.tools.py_trees_port import oneshot_behavior +def oneshot_with_check(variable_name, behaviour, name=None): + """ + Check if the blackboard contains already variable_name and + return a oneshot_behavior for behaviour. + """ + blackboard = py_trees.blackboard.Blackboard() + # check if the variable_name already exists in the blackboard + if blackboard.get(variable_name) is not None: + print("Warning: {} is already used before. Check your XOSC for duplicated names".format(variable_name)) + + return oneshot_behavior(variable_name, behaviour, name) + + class OpenScenarioParser(object): """ @@ -935,9 +950,9 @@ def convert_maneuver_to_atomic(action, actor, catalogs): policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ALL, name=maneuver_name) env_behavior.add_child( - oneshot_behavior(variable_name=maneuver_name + ">WeatherUpdate", behaviour=weather_behavior)) + oneshot_with_check(variable_name=maneuver_name + ">WeatherUpdate", behaviour=weather_behavior)) env_behavior.add_child( - oneshot_behavior(variable_name=maneuver_name + ">FrictionUpdate", behaviour=friction_behavior)) + oneshot_with_check(variable_name=maneuver_name + ">FrictionUpdate", behaviour=friction_behavior)) return env_behavior