From 7393a2832b2ad718389cea95e1efde7f062d8d47 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:10:23 +0200 Subject: [PATCH 01/15] feat: implement state manager --- engine/src/Utils/StoryBoardElementState.h | 26 ++++++++ .../Utils/StoryBoardElementStateManage.cpp | 65 +++++++++++++++++++ .../src/Utils/StoryBoardElementStateManager.h | 64 ++++++++++++++++++ .../src/Utils/StoryBoardElementTransition.h | 27 ++++++++ engine/src/Utils/StoryboardElementType.h | 29 +++++++++ 5 files changed, 211 insertions(+) create mode 100644 engine/src/Utils/StoryBoardElementState.h create mode 100644 engine/src/Utils/StoryBoardElementStateManage.cpp create mode 100644 engine/src/Utils/StoryBoardElementStateManager.h create mode 100644 engine/src/Utils/StoryBoardElementTransition.h create mode 100644 engine/src/Utils/StoryboardElementType.h diff --git a/engine/src/Utils/StoryBoardElementState.h b/engine/src/Utils/StoryBoardElementState.h new file mode 100644 index 00000000..b76edea6 --- /dev/null +++ b/engine/src/Utils/StoryBoardElementState.h @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#pragma once +#include <cstdint> + +namespace OpenScenarioEngine::v1_3 +{ +/// Definition of StoryBoardElementState +/// +/// \see https://publications.pages.asam.net/standards/ASAM_OpenSCENARIO/ASAM_OpenSCENARIO_XML/latest/generated/content/StoryboardElementState.html +enum class StoryBoardElementState : std::uint8_t +{ + kCompleteState, + kRunningState, + kStandbyState, + kUnknown +}; +} // namespace OpenScenarioEngine::v1_3 diff --git a/engine/src/Utils/StoryBoardElementStateManage.cpp b/engine/src/Utils/StoryBoardElementStateManage.cpp new file mode 100644 index 00000000..815b6b4b --- /dev/null +++ b/engine/src/Utils/StoryBoardElementStateManage.cpp @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#include "Utils/StoryBoardElementStateManager.h" + +namespace OpenScenarioEngine::v1_3 +{ + +void StoryBoardElementStateManager::Update(const StoryBoardElement& name, StoryBoardElementType type, StoryBoardElementState state) +{ + std::lock_guard<std::mutex> lock(mutex_); + states_[{name, type}] = state; +} + +void StoryBoardElementStateManager::Update(const StoryBoardElement& name, StoryBoardElementType type, StoryBoardElementTransition transition) +{ + std::lock_guard<std::mutex> lock(mutex_); + transitions_[{name, type}] = transition; +} + +void StoryBoardElementStateManager::ResetState(const StoryBoardElement& name, StoryBoardElementType type) +{ + std::lock_guard<std::mutex> lock(mutex_); + states_[{name, type}] = StoryBoardElementState::kUnknown; +} + +void StoryBoardElementStateManager::ResetTransition(const StoryBoardElement& name, StoryBoardElementType type) +{ + std::lock_guard<std::mutex> lock(mutex_); + transitions_[{name, type}] = StoryBoardElementTransition::kUnknown; +} + +std::optional<StoryBoardElementState> StoryBoardElementStateManager::GetState(const StoryBoardElement& name, StoryBoardElementType type) const +{ + std::lock_guard<std::mutex> lock(mutex_); + + StoryBoardElementKey key{name, type}; + auto it = states_.find(key); + if (it != states_.end()) + { + return it->second; + } + return std::nullopt; +} + +std::optional<StoryBoardElementTransition> StoryBoardElementStateManager::GetTransition(const StoryBoardElement& name, StoryBoardElementType type) const +{ + std::lock_guard<std::mutex> lock(mutex_); + + StoryBoardElementKey key{name, type}; + auto it = transitions_.find(key); + if (it != transitions_.end()) + { + return it->second; + } + return std::nullopt; +} +} // namespace OpenScenarioEngine::v1_3 diff --git a/engine/src/Utils/StoryBoardElementStateManager.h b/engine/src/Utils/StoryBoardElementStateManager.h new file mode 100644 index 00000000..4590e013 --- /dev/null +++ b/engine/src/Utils/StoryBoardElementStateManager.h @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#pragma once + +#include <openScenarioLib/generated/v1_3/api/EnumerationsV1_3.h> + +#include <mutex> +#include <optional> +#include <unordered_map> + +#include "Utils/StoryBoardElementState.h" +#include "Utils/StoryBoardElementTransition.h" +#include "Utils/StoryboardElementType.h" + +namespace OpenScenarioEngine::v1_3 +{ + +using StoryBoardElement = std::string; + +struct StoryBoardElementKey +{ + StoryBoardElement name; + StoryBoardElementType type; + + bool operator==(const StoryBoardElementKey& other) const + { + return name == other.name && type == other.type; + } +}; + +struct StoryBoardElementKeyHasher +{ + std::size_t operator()(const StoryBoardElementKey& key) const + { + std::size_t h1 = std::hash<std::string>{}(key.name); + std::size_t h2 = std::hash<std::underlying_type_t<StoryBoardElementType>>{}(static_cast<std::underlying_type_t<StoryBoardElementType>>(key.type)); + return h1 ^ (h2 << 1); + } +}; + +class StoryBoardElementStateManager +{ +public: + void Update(const StoryBoardElement& name, StoryBoardElementType type, StoryBoardElementState state); + void Update(const StoryBoardElement& name, StoryBoardElementType type, StoryBoardElementTransition transition); + void ResetState(const StoryBoardElement& name, StoryBoardElementType type); + void ResetTransition(const StoryBoardElement& name, StoryBoardElementType type); + [[nodiscard]] std::optional<StoryBoardElementState> GetState(const StoryBoardElement& name, StoryBoardElementType type) const; + [[nodiscard]] std::optional<StoryBoardElementTransition> GetTransition(const StoryBoardElement& name, StoryBoardElementType type) const; + +private: + mutable std::mutex mutex_; + std::unordered_map<StoryBoardElementKey, StoryBoardElementState, StoryBoardElementKeyHasher> states_; + std::unordered_map<StoryBoardElementKey, StoryBoardElementTransition, StoryBoardElementKeyHasher> transitions_; +}; +} // namespace OpenScenarioEngine::v1_3 diff --git a/engine/src/Utils/StoryBoardElementTransition.h b/engine/src/Utils/StoryBoardElementTransition.h new file mode 100644 index 00000000..998203b5 --- /dev/null +++ b/engine/src/Utils/StoryBoardElementTransition.h @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#pragma once +#include <cstdint> + +namespace OpenScenarioEngine::v1_3 +{ +/// Definition of StoryBoardElementTransition +/// +/// \see https://publications.pages.asam.net/standards/ASAM_OpenSCENARIO/ASAM_OpenSCENARIO_XML/latest/generated/content/StoryboardElementState.html +enum class StoryBoardElementTransition : std::uint8_t +{ + kEndTransition, + kSkipTransition, + kStartTransition, + kStopTransition, + kUnknown +}; +} // namespace OpenScenarioEngine::v1_3 diff --git a/engine/src/Utils/StoryboardElementType.h b/engine/src/Utils/StoryboardElementType.h new file mode 100644 index 00000000..512dda12 --- /dev/null +++ b/engine/src/Utils/StoryboardElementType.h @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#pragma once +#include <cstdint> + +namespace OpenScenarioEngine::v1_3 +{ +/// Definition of StoryBoardElementType +/// +/// \see https://publications.pages.asam.net/standards/ASAM_OpenSCENARIO/ASAM_OpenSCENARIO_XML/latest/generated/content/StoryboardElementType.html +enum class StoryBoardElementType : std::uint8_t +{ + kAct, + kAction, + kEvent, + kManeuver, + kManeuverGroup, + kStory, + kUnknown +}; +} // namespace OpenScenarioEngine::v1_3 -- GitLab From 876eb14d8d17c0845fed16cec5ca7cc91e706a52 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:11:59 +0200 Subject: [PATCH 02/15] feat: set manager in root node --- engine/src/Node/RootNode.cpp | 5 ++++- engine/src/Node/RootNode.h | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/engine/src/Node/RootNode.cpp b/engine/src/Node/RootNode.cpp index ae0a474b..fc22221f 100644 --- a/engine/src/Node/RootNode.cpp +++ b/engine/src/Node/RootNode.cpp @@ -1,5 +1,6 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -25,7 +26,8 @@ RootNode::RootNode(std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::IScenarioDefinit environment_{environment}, controller_service_{controller_service}, stochastics_{stochastics}, - engine_abort_flags_{engine_abort_flags} + engine_abort_flags_{engine_abort_flags}, + story_board_element_state_manager_{std::make_shared<StoryBoardElementStateManager>()} { if (auto storyboard = scenarioDefinition->GetStoryboard(); storyboard) { @@ -44,6 +46,7 @@ void RootNode::lookupAndRegisterData(yase::Blackboard& blackboard) blackboard.set("ControllerService", controller_service_); blackboard.set("Stochastics", stochastics_); blackboard.set("EngineAbortFlags", engine_abort_flags_); + blackboard.set("StoryBoardElementStateManager", story_board_element_state_manager_); } } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/RootNode.h b/engine/src/Node/RootNode.h index 9b4b7e65..91e76da3 100644 --- a/engine/src/Node/RootNode.h +++ b/engine/src/Node/RootNode.h @@ -1,5 +1,6 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -15,9 +16,9 @@ #include <memory> -#include "Utils/EngineAbortFlags.h" #include "Stochastics/StochasticsInterface.h" - +#include "Utils/EngineAbortFlags.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3 { @@ -45,8 +46,9 @@ private: std::shared_ptr<IControllerService> controller_service_; std::shared_ptr<StochasticsInterface> stochastics_; std::shared_ptr<EngineAbortFlags> engine_abort_flags_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; } // namespace Node -} // namespace OpenScenarioEngine::v1_3 \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3 -- GitLab From f7e17bca7cb6835dffcf7cfc8901f3e270aab068 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:13:08 +0200 Subject: [PATCH 03/15] feat: implement StoryBoardElementStateCondition --- .../StoryboardElementStateCondition.h | 10 ++- .../StoryboardElementStateCondition_impl.cpp | 11 +-- .../StoryboardElementStateCondition_impl.h | 7 +- .../ConvertScenarioStoryboardElement.h | 85 ++++++++++++++++++- 4 files changed, 101 insertions(+), 12 deletions(-) diff --git a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition.h b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition.h index 37d3519f..fcb081f7 100644 --- a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition.h +++ b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition.h @@ -17,6 +17,7 @@ #include <utility> #include "Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3::Node { @@ -41,12 +42,15 @@ private: void lookupAndRegisterData(yase::Blackboard& blackboard) final { auto environment = blackboard.get<std::shared_ptr<mantle_api::IEnvironment>>("Environment"); - + auto story_board_element_state_manager = blackboard.get<std::shared_ptr<StoryBoardElementStateManager>>("StoryBoardElementStateManager"); impl_ = std::make_unique<OpenScenarioEngine::v1_3::StoryboardElementStateCondition>( OpenScenarioEngine::v1_3::StoryboardElementStateCondition::Values{ - ConvertScenarioStoryboardElement(storyboardElementStateCondition_->GetStoryboardElementRef())}, + ConvertScenarioStoryboardElementState(storyboardElementStateCondition_->GetState()), + ConvertScenarioStoryboardElementTransition(storyboardElementStateCondition_->GetState()), + ConvertScenarioStoryboardElement(storyboardElementStateCondition_->GetStoryboardElementRef()), + ConvertScenarioStoryboardElement(storyboardElementStateCondition_->GetStoryboardElementType())}, OpenScenarioEngine::v1_3::StoryboardElementStateCondition::Interfaces{ - environment}); + environment, story_board_element_state_manager}); } std::unique_ptr<OpenScenarioEngine::v1_3::StoryboardElementStateCondition> impl_{nullptr}; diff --git a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.cpp b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.cpp index 0105b206..c1098eb3 100644 --- a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.cpp +++ b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.cpp @@ -17,11 +17,12 @@ namespace OpenScenarioEngine::v1_3 bool StoryboardElementStateCondition::IsSatisfied() const { - // Note: - // - Access to values parse to mantle/ose datatypes: this->values.xxx - // - Access to mantle interfaces: this->mantle.xxx - Logger::Error("Method StoryboardElementStateCondition::IsSatisfied() not implemented yet (returning \"true\" by default)"); - return true; + const auto& manager = mantle.story_board_element_state_manager; + const auto state_opt = manager->GetState(values.storyboardElementRef, values.storyboardElementType); + const auto transition_opt = manager->GetTransition(values.storyboardElementRef, values.storyboardElementType); + + return (state_opt && *state_opt == values.state) || + (transition_opt && *transition_opt == values.transition); } } // namespace OpenScenarioEngine::v1_3 diff --git a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.h b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.h index 9c5d4243..6f75ab15 100644 --- a/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.h +++ b/engine/gen/Storyboard/ByValueCondition/StoryboardElementStateCondition_impl.h @@ -13,6 +13,7 @@ #include <MantleAPI/Execution/i_environment.h> #include "Conversion/OscToMantle/ConvertScenarioStoryboardElement.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3 { @@ -22,11 +23,15 @@ class StoryboardElementStateCondition public: struct Values { + StoryBoardElementState state; + StoryBoardElementTransition transition; StoryboardElement storyboardElementRef; + StoryBoardElementType storyboardElementType; }; struct Interfaces { std::shared_ptr<mantle_api::IEnvironment> environment; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager; }; StoryboardElementStateCondition(Values values, Interfaces interfaces) @@ -40,4 +45,4 @@ private: Interfaces mantle; }; -} // namespace OpenScenarioEngine::v1_3 \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3 diff --git a/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h b/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h index bb965a11..8f7e1dc0 100644 --- a/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h +++ b/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h @@ -16,8 +16,13 @@ #include <memory> #include <string> +#include "Utils/StoryBoardElementState.h" +#include "Utils/StoryBoardElementTransition.h" +#include "Utils/StoryboardElementType.h" + namespace OpenScenarioEngine::v1_3 { + using StoryboardElement = std::string; inline StoryboardElement ConvertScenarioStoryboardElement(const std::shared_ptr<NET_ASAM_OPENSCENARIO::INamedReference<NET_ASAM_OPENSCENARIO::v1_3::IStoryboardElement>>& storyboardElement) @@ -25,9 +30,83 @@ inline StoryboardElement ConvertScenarioStoryboardElement(const std::shared_ptr< return storyboardElement->GetNameRef(); } -inline StoryboardElement ConvertScenarioStoryboardElement(const std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::IStoryboardElement>& /*storyboardElement*/) +inline StoryBoardElementType ConvertScenarioStoryboardElement( + const NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementType& type) +{ + using SourceType = NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementType::StoryboardElementTypeEnum; + + if (type == SourceType::ACT) + { + return StoryBoardElementType::kAct; + } + if (type == SourceType::ACTION) + { + return StoryBoardElementType::kAction; + } + if (type == SourceType::EVENT) + { + return StoryBoardElementType::kEvent; + } + if (type == SourceType::MANEUVER) + { + return StoryBoardElementType::kManeuver; + } + if (type == SourceType::MANEUVER_GROUP) + { + return StoryBoardElementType::kManeuverGroup; + } + if (type == SourceType::STORY) + { + return StoryBoardElementType::kStory; + } + + throw std::runtime_error("ConvertScenarioStoryBoardElement: Unsupported Element Type"); +} + +inline StoryBoardElementState ConvertScenarioStoryboardElementState( + const NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementState& state) { - return {}; + using SourceState = NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementState::StoryboardElementStateEnum; + + if (state == SourceState::COMPLETE_STATE) + { + return StoryBoardElementState::kCompleteState; + } + if (state == SourceState::RUNNING_STATE) + { + return StoryBoardElementState::kRunningState; + } + if (state == SourceState::STANDBY_STATE) + { + return StoryBoardElementState::kStandbyState; + } + + return StoryBoardElementState::kUnknown; +} + +inline StoryBoardElementTransition ConvertScenarioStoryboardElementTransition( + const NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementState& state) +{ + using SourceState = NET_ASAM_OPENSCENARIO::v1_3::StoryboardElementState::StoryboardElementStateEnum; + + if (state == SourceState::END_TRANSITION) + { + return StoryBoardElementTransition::kEndTransition; + } + if (state == SourceState::SKIP_TRANSITION) + { + return StoryBoardElementTransition::kSkipTransition; + } + if (state == SourceState::START_TRANSITION) + { + return StoryBoardElementTransition::kStartTransition; + } + if (state == SourceState::STOP_TRANSITION) + { + return StoryBoardElementTransition::kStopTransition; + } + + return StoryBoardElementTransition::kUnknown; } -} // namespace OpenScenarioEngine::v1_3 \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3 -- GitLab From 745fb057b88bae0d55078e96e02c10910e2252d7 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:14:03 +0200 Subject: [PATCH 04/15] feat: add original name in node --- engine/src/Node/TriggerableCompositeNode.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/engine/src/Node/TriggerableCompositeNode.h b/engine/src/Node/TriggerableCompositeNode.h index 5f932de2..e4c1c112 100644 --- a/engine/src/Node/TriggerableCompositeNode.h +++ b/engine/src/Node/TriggerableCompositeNode.h @@ -1,6 +1,7 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * 2021 Max Paul Bauer - Robert Bosch GmbH + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -111,7 +112,7 @@ class TriggerableCompositeNode : public yase::CompositeNode { public: explicit TriggerableCompositeNode(const std::string& name) - : CompositeNode{name} {}; + : CompositeNode{name}, original_name_(name){}; ~TriggerableCompositeNode() override = default; void onInit() override @@ -150,6 +151,8 @@ public: } } + [[nodiscard]] const std::string& getOriginalName() const { return original_name_; } + protected: using yase::CompositeNode::addChild; @@ -265,6 +268,7 @@ private: TransientNode::Ptr m_child_node{nullptr}; TransientNode::Ptr stop_trigger_node_{nullptr}; yase::NodeStatus stop_trigger_status_{yase::NodeStatus::kIdle}; + std::string original_name_; }; -} // namespace OpenScenarioEngine::v1_3::Node \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3::Node -- GitLab From e6105f8823b0d6079457af62626a06a0ab7a794f Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:14:54 +0200 Subject: [PATCH 05/15] feat: apply feature to ActNode --- engine/src/Node/ActNode.cpp | 66 +++++++++++++++++++++++++++++++++++++ engine/src/Node/ActNode.h | 19 +++++++---- 2 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 engine/src/Node/ActNode.cpp diff --git a/engine/src/Node/ActNode.cpp b/engine/src/Node/ActNode.cpp new file mode 100644 index 00000000..4b33e9ce --- /dev/null +++ b/engine/src/Node/ActNode.cpp @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#include "Node/ActNode.h" + +namespace OpenScenarioEngine::v1_3::Node +{ + +ActNode::ActNode(const std::string& name, + yase::BehaviorNode::Ptr maneuver_groups, + yase::BehaviorNode::Ptr start_trigger, + yase::BehaviorNode::Ptr stop_trigger) + : TriggerableCompositeNode{name}, start_trigger_(start_trigger), stop_trigger_(stop_trigger) +{ + set(std::move(maneuver_groups), StopTriggerPtr{std::move(stop_trigger)}, StartTriggerPtr{std::move(start_trigger)}); +} + +void ActNode::lookupAndRegisterData(yase::Blackboard& blackboard) +{ + story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kStandbyState); +} + +yase::NodeStatus ActNode::tick() +{ + // reset transition to unknown in every tick + story_board_element_state_manager_->ResetTransition(getOriginalName(), StoryBoardElementType::kAct); + + auto current_status = TriggerableCompositeNode::tick(); + + if (start_trigger_ == nullptr || start_trigger_->status() == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStartTransition); + } + if (stop_trigger_ != nullptr && stop_trigger_->status() == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStopTransition); + } + + if (current_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kCompleteState); + } + else if (current_status == yase::NodeStatus::kRunning) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kRunningState); + } + else + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kUnknown); + } + + return current_status; +} + +} // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/ActNode.h b/engine/src/Node/ActNode.h index 7ec0683a..ac8c7dda 100644 --- a/engine/src/Node/ActNode.h +++ b/engine/src/Node/ActNode.h @@ -1,6 +1,7 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * 2021 Max Paul Bauer - Robert Bosch GmbH + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -14,6 +15,7 @@ #include <utility> #include "Node/TriggerableCompositeNode.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3::Node { @@ -23,11 +25,16 @@ public: ActNode(const std::string& name, yase::BehaviorNode::Ptr maneuver_groups, yase::BehaviorNode::Ptr start_trigger = nullptr, - yase::BehaviorNode::Ptr stop_trigger = nullptr) - : TriggerableCompositeNode{name} - { - set(std::move(maneuver_groups), StopTriggerPtr{std::move(stop_trigger)}, StartTriggerPtr{std::move(start_trigger)}); - } + yase::BehaviorNode::Ptr stop_trigger = nullptr); + + void lookupAndRegisterData(yase::Blackboard& blackboard) override; + + yase::NodeStatus tick() override; + +private: + yase::BehaviorNode::Ptr start_trigger_; + yase::BehaviorNode::Ptr stop_trigger_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; -} // namespace OpenScenarioEngine::v1_3::Node \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3::Node -- GitLab From bbdde9ba23247914ecba961753d75d315e2c075d Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:15:57 +0200 Subject: [PATCH 06/15] feat: apply feature to maneuver node --- engine/src/Node/ManeuverNode.cpp | 31 ++++++++++++++++++++++++++++--- engine/src/Node/ManeuverNode.h | 6 ++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/engine/src/Node/ManeuverNode.cpp b/engine/src/Node/ManeuverNode.cpp index 30f70cb5..0398e046 100644 --- a/engine/src/Node/ManeuverNode.cpp +++ b/engine/src/Node/ManeuverNode.cpp @@ -15,19 +15,44 @@ namespace OpenScenarioEngine::v1_3::Node { ManeuverNode::ManeuverNode(const std::string& name) - : yase::DecoratorNode{name}, eventPrioritizer_{std::make_shared<EventPrioritizer>()} + : yase::DecoratorNode{name}, eventPrioritizer_{std::make_shared<EventPrioritizer>()}, original_name_(name) { } +const std::string& ManeuverNode::getOriginalName() const +{ + return original_name_; +} + yase::NodeStatus ManeuverNode::tick() { eventPrioritizer_->UpdateOverriddenEvents(); - return child().executeTick(); + + auto current_status = child().executeTick(); + + if (current_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kEndTransition); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kCompleteState); + } + else if (current_status == yase::NodeStatus::kRunning) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kRunningState); + } + else + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kUnknown); + } + + return current_status; } -void ManeuverNode::lookupAndRegisterData(yase::Blackboard &blackboard) +void ManeuverNode::lookupAndRegisterData(yase::Blackboard& blackboard) { blackboard.set("EventPrioritizer", eventPrioritizer_); + story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuverGroup, StoryBoardElementState::kStandbyState); } } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/ManeuverNode.h b/engine/src/Node/ManeuverNode.h index 9fbadfab..0e6855a8 100644 --- a/engine/src/Node/ManeuverNode.h +++ b/engine/src/Node/ManeuverNode.h @@ -12,6 +12,8 @@ #include <agnostic_behavior_tree/decorator_node.h> +#include "Utils/StoryBoardElementStateManager.h" + namespace OpenScenarioEngine::v1_3 { class IEventPrioritizer; @@ -28,11 +30,15 @@ public: /// @param name Name of the maneuver node explicit ManeuverNode(const std::string& name); + [[nodiscard]] const std::string& getOriginalName() const; + private: void lookupAndRegisterData(yase::Blackboard& blackboard) override; yase::NodeStatus tick() final; std::shared_ptr<IEventPrioritizer> eventPrioritizer_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; + std::string original_name_; }; } // namespace Node -- GitLab From 4e97e2f15f25f6e25f2bc1646a121a362de048c4 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:16:18 +0200 Subject: [PATCH 07/15] feat: apply feature to event node --- engine/src/Node/EventNode.cpp | 35 +++++++++++++++++++++++++++++++++-- engine/src/Node/EventNode.h | 2 ++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/engine/src/Node/EventNode.cpp b/engine/src/Node/EventNode.cpp index 532f5765..e14e5229 100644 --- a/engine/src/Node/EventNode.cpp +++ b/engine/src/Node/EventNode.cpp @@ -25,14 +25,28 @@ EventNode::EventNode(const std::string& name, void EventNode::lookupAndRegisterData(yase::Blackboard& blackboard) { - event_prioritizer_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::IEventPrioritizer> >("EventPrioritizer"); + event_prioritizer_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::IEventPrioritizer>>("EventPrioritizer"); event_prioritizer_->RegisterEvent(name(), event_priority_); + story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kStandbyState); } yase::NodeStatus EventNode::tick() { - if (event_prioritizer_->ShouldStopChild(name()) || event_prioritizer_->ShouldSkipChild(name())) + // reset transition to unknown in every tick + story_board_element_state_manager_->ResetTransition(getOriginalName(), StoryBoardElementType::kEvent); + + if (event_prioritizer_->ShouldStopChild(name())) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kStopTransition); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kCompleteState); + return yase::NodeStatus::kSuccess; + } + + if (event_prioritizer_->ShouldSkipChild(name())) { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kSkipTransition); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kStandbyState); return yase::NodeStatus::kSuccess; } @@ -40,9 +54,26 @@ yase::NodeStatus EventNode::tick() if (start_trigger_ == nullptr || start_trigger_->status() == yase::NodeStatus::kSuccess) { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kStartTransition); event_prioritizer_->EventStarted(name()); } + if (current_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kCompleteState); + } + else if (current_status == yase::NodeStatus::kRunning) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kRunningState); + } + else + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kUnknown); + } + return current_status; } diff --git a/engine/src/Node/EventNode.h b/engine/src/Node/EventNode.h index 2ea9f955..4aac076c 100644 --- a/engine/src/Node/EventNode.h +++ b/engine/src/Node/EventNode.h @@ -15,6 +15,7 @@ #include "Node/TriggerableCompositeNode.h" #include "Utils/EventPriority.h" #include "Utils/IEventPrioritizer.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3::Node { @@ -42,6 +43,7 @@ private: EventPriority event_priority_; yase::BehaviorNode::Ptr start_trigger_; std::shared_ptr<IEventPrioritizer> event_prioritizer_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; } // namespace OpenScenarioEngine::v1_3::Node -- GitLab From 219c9ffea962841cc7d76b81eef3a2c9a3c18eed Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:17:36 +0200 Subject: [PATCH 08/15] feat: apply feature to longitudinalAction --- .../MotionControlAction/SpeedAction.h | 17 ++++++++++++++ .../LongitudinalDistanceAction.h | 22 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/engine/gen/Storyboard/MotionControlAction/SpeedAction.h b/engine/gen/Storyboard/MotionControlAction/SpeedAction.h index b866ac69..d91295af 100644 --- a/engine/gen/Storyboard/MotionControlAction/SpeedAction.h +++ b/engine/gen/Storyboard/MotionControlAction/SpeedAction.h @@ -1,5 +1,6 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -19,6 +20,7 @@ #include "Storyboard/MotionControlAction/MotionControlAction.h" #include "Storyboard/MotionControlAction/SpeedAction_impl.h" #include "Utils/EntityBroker.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3::Node { @@ -38,6 +40,18 @@ private: { assert(impl_); const auto is_finished = impl_->Step(); + + if (is_finished) + { + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kCompleteState); + } + else + { + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kRunningState); + } + return is_finished ? yase::NodeStatus::kSuccess : yase::NodeStatus::kRunning; }; @@ -45,6 +59,8 @@ private: { auto environment = blackboard.get<std::shared_ptr<mantle_api::IEnvironment>>("Environment"); const auto entityBroker = blackboard.get<EntityBroker::Ptr>("EntityBroker"); + story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kStandbyState); impl_ = std::make_unique<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::SpeedAction>>( OpenScenarioEngine::v1_3::SpeedAction::Values{ @@ -58,6 +74,7 @@ private: std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::SpeedAction>> impl_{nullptr}; std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ISpeedAction> speedAction_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h b/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h index 67f7bcf1..0bc2a1f6 100644 --- a/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h +++ b/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h @@ -1,5 +1,6 @@ /******************************************************************************** * Copyright (c) 2021-2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2025 Ansys, Inc. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -19,6 +20,7 @@ #include "Storyboard/MotionControlAction/LongitudinalDistanceAction_impl.h" #include "Storyboard/MotionControlAction/MotionControlAction.h" #include "Utils/EntityBroker.h" +#include "Utils/StoryBoardElementStateManager.h" namespace OpenScenarioEngine::v1_3::Node { @@ -38,6 +40,18 @@ private: { assert(impl_); const auto is_finished = impl_->Step(); + + if (is_finished) + { + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kCompleteState); + } + else + { + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kRunningState); + } + return is_finished ? yase::NodeStatus::kSuccess : yase::NodeStatus::kRunning; }; @@ -45,13 +59,16 @@ private: { auto environment = blackboard.get<std::shared_ptr<mantle_api::IEnvironment>>("Environment"); const auto entityBroker = blackboard.get<EntityBroker::Ptr>("EntityBroker"); + story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kStandbyState); impl_ = std::make_unique<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::LongitudinalDistanceAction>>( OpenScenarioEngine::v1_3::LongitudinalDistanceAction::Values{ entityBroker->GetEntities(), longitudinalDistanceAction_->GetContinuous(), longitudinalDistanceAction_->GetFreespace(), - [=]() { + [=]() + { return ConvertScenarioLongitudinalDistance( environment, longitudinalDistanceAction_->IsSetDistance(), @@ -70,6 +87,7 @@ private: std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::LongitudinalDistanceAction>> impl_{nullptr}; std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ILongitudinalDistanceAction> longitudinalDistanceAction_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; -} // namespace OpenScenarioEngine::v1_3::Node \ No newline at end of file +} // namespace OpenScenarioEngine::v1_3::Node -- GitLab From 28f294e5ce4ad994323d1698bcfa1eeb58dab3b8 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:18:08 +0200 Subject: [PATCH 09/15] test: modify fake root node --- engine/tests/TestUtils.h | 204 ++++++++++++++++++++------------------- 1 file changed, 104 insertions(+), 100 deletions(-) diff --git a/engine/tests/TestUtils.h b/engine/tests/TestUtils.h index 7408a939..7ad4c21a 100644 --- a/engine/tests/TestUtils.h +++ b/engine/tests/TestUtils.h @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright (c) 2021-2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * Copyright (c) 2023 Ansys, Inc. + * Copyright (c) 2023-2025 Ansys, Inc. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -25,6 +25,7 @@ #include "Utils/ControllerCreator.h" #include "Utils/EngineAbortFlags.h" #include "Utils/EntityBroker.h" +#include "Utils/StoryBoardElementStateManager.h" namespace testing::OpenScenarioEngine::v1_3 { @@ -32,121 +33,124 @@ using namespace units::literals; class FakeRootNode : public yase::DecoratorNode { - public: - FakeRootNode(std::shared_ptr<mantle_api::IEnvironment> environment, - std::shared_ptr<::OpenScenarioEngine::v1_3::EngineAbortFlags> engine_abort_flags, - std::shared_ptr<::OpenScenarioEngine::v1_3::EntityBroker> entity_broker) - : yase::DecoratorNode{"OpenScenarioEngine"}, - environment_{environment}, - engine_abort_flags_{engine_abort_flags}, - entity_broker_{entity_broker} - { - distributeData(); - } - - private: - void lookupAndRegisterData(yase::Blackboard& blackboard) override - { - blackboard.set("Environment", environment_); - blackboard.set("EngineAbortFlags", engine_abort_flags_); - blackboard.set("EntityBroker", entity_broker_); - } - - yase::NodeStatus tick() final - { - return child().executeTick(); - } - - std::shared_ptr<mantle_api::IEnvironment> environment_; - std::shared_ptr<::OpenScenarioEngine::v1_3::EngineAbortFlags> engine_abort_flags_; - std::shared_ptr<::OpenScenarioEngine::v1_3::EntityBroker> entity_broker_; +public: + FakeRootNode(std::shared_ptr<mantle_api::IEnvironment> environment, + std::shared_ptr<::OpenScenarioEngine::v1_3::EngineAbortFlags> engine_abort_flags, + std::shared_ptr<::OpenScenarioEngine::v1_3::EntityBroker> entity_broker) + : yase::DecoratorNode{"OpenScenarioEngine"}, + environment_{environment}, + engine_abort_flags_{engine_abort_flags}, + entity_broker_{entity_broker}, + story_board_element_state_manager_{std::make_shared<::OpenScenarioEngine::v1_3::StoryBoardElementStateManager>()} + { + distributeData(); + } + +private: + void lookupAndRegisterData(yase::Blackboard& blackboard) override + { + blackboard.set("Environment", environment_); + blackboard.set("EngineAbortFlags", engine_abort_flags_); + blackboard.set("EntityBroker", entity_broker_); + blackboard.set("StoryBoardElementStateManager", story_board_element_state_manager_); + } + + yase::NodeStatus tick() final + { + return child().executeTick(); + } + + std::shared_ptr<mantle_api::IEnvironment> environment_; + std::shared_ptr<::OpenScenarioEngine::v1_3::EngineAbortFlags> engine_abort_flags_; + std::shared_ptr<::OpenScenarioEngine::v1_3::EntityBroker> entity_broker_; + std::shared_ptr<::OpenScenarioEngine::v1_3::StoryBoardElementStateManager> story_board_element_state_manager_; }; inline std::string GetScenariosPath(const std::string& test_file_path) { - std::filesystem::path file_path{test_file_path}; - return {file_path.remove_filename().string() + "data/Scenarios/"}; + std::filesystem::path file_path{test_file_path}; + return {file_path.remove_filename().string() + "data/Scenarios/"}; } class OpenScenarioEngineLibraryTestBase : public ::testing::Test { - protected: - void SetUp() override - { - env_ = std::make_shared<mantle_api::MockEnvironment>(); - ON_CALL(env_->GetControllerRepository(), Create(testing::_)).WillByDefault(testing::ReturnRef(controller_)); - } - - std::shared_ptr<mantle_api::MockEnvironment> env_; - mantle_api::MockController controller_; - std::string default_xosc_scenario_{ - "AutomatedLaneKeepingSystemScenarios/ALKS_Scenario_4.1_1_FreeDriving_TEMPLATE.xosc"}; +protected: + void SetUp() override + { + env_ = std::make_shared<mantle_api::MockEnvironment>(); + ON_CALL(env_->GetControllerRepository(), Create(testing::_)).WillByDefault(testing::ReturnRef(controller_)); + } + + std::shared_ptr<mantle_api::MockEnvironment> env_; + mantle_api::MockController controller_; + std::string default_xosc_scenario_{ + "AutomatedLaneKeepingSystemScenarios/ALKS_Scenario_4.1_1_FreeDriving_TEMPLATE.xosc"}; }; class EngineSubModuleTestBase : public OpenScenarioEngineLibraryTestBase { - protected: - virtual void LoadScenario(const std::string& scenario_file_path) - { - auto message_logger = - std::make_shared<NET_ASAM_OPENSCENARIO::SimpleMessageLogger>(NET_ASAM_OPENSCENARIO::ErrorLevel::INFO); - auto catalog_message_logger = - std::make_shared<NET_ASAM_OPENSCENARIO::SimpleMessageLogger>(NET_ASAM_OPENSCENARIO::ErrorLevel::INFO); - auto loader_factory = - NET_ASAM_OPENSCENARIO::v1_3::XmlScenarioImportLoaderFactory(catalog_message_logger, scenario_file_path); - auto loader = loader_factory.CreateLoader(std::make_shared<NET_ASAM_OPENSCENARIO::FileResourceLocator>()); - - scenario_ptr_ = std::static_pointer_cast<NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario>( - loader->Load(message_logger)->GetAdapter(typeid(NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario).name())); - } - - std::string GetScenariosPath(const std::string& test_file_path) const - { - std::filesystem::path file_path{test_file_path}; - // The first .parent_path() removes the filename, the second removes "/Utils" - return {file_path.parent_path().parent_path().string() + "/data/Scenarios/"}; - } - - std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario> scenario_ptr_; +protected: + virtual void LoadScenario(const std::string& scenario_file_path) + { + auto message_logger = + std::make_shared<NET_ASAM_OPENSCENARIO::SimpleMessageLogger>(NET_ASAM_OPENSCENARIO::ErrorLevel::INFO); + auto catalog_message_logger = + std::make_shared<NET_ASAM_OPENSCENARIO::SimpleMessageLogger>(NET_ASAM_OPENSCENARIO::ErrorLevel::INFO); + auto loader_factory = + NET_ASAM_OPENSCENARIO::v1_3::XmlScenarioImportLoaderFactory(catalog_message_logger, scenario_file_path); + auto loader = loader_factory.CreateLoader(std::make_shared<NET_ASAM_OPENSCENARIO::FileResourceLocator>()); + + scenario_ptr_ = std::static_pointer_cast<NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario>( + loader->Load(message_logger)->GetAdapter(typeid(NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario).name())); + } + + std::string GetScenariosPath(const std::string& test_file_path) const + { + std::filesystem::path file_path{test_file_path}; + // The first .parent_path() removes the filename, the second removes "/Utils" + return {file_path.parent_path().parent_path().string() + "/data/Scenarios/"}; + } + + std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::IOpenScenario> scenario_ptr_; }; class OpenScenarioEngineTestBase : public OpenScenarioEngineLibraryTestBase { - protected: - void SetUp() override - { - OpenScenarioEngineLibraryTestBase::SetUp(); - - mantle_api::VehicleProperties ego_properties{}; - ego_properties.type = mantle_api::EntityType::kVehicle; - ego_properties.classification = mantle_api::VehicleClass::kMedium_car; - ego_properties.model = "medium_car"; - ego_properties.bounding_box.dimension.length = 5.0_m; - ego_properties.bounding_box.dimension.width = 2.0_m; - ego_properties.bounding_box.dimension.height = 1.8_m; - ego_properties.bounding_box.geometric_center.x = 1.4_m; - ego_properties.bounding_box.geometric_center.y = 0.0_m; - ego_properties.bounding_box.geometric_center.z = 0.9_m; - ego_properties.performance.max_acceleration = 10_mps_sq; - ego_properties.performance.max_deceleration = 10_mps_sq; - ego_properties.performance.max_speed = 70_mps; - ego_properties.front_axle.bb_center_to_axle_center = {1.58_m, 0.0_m, -0.5_m}; - ego_properties.front_axle.max_steering = 0.5_rad; - ego_properties.front_axle.track_width = 1.68_m; - ego_properties.front_axle.wheel_diameter = 0.8_m; - ego_properties.rear_axle.bb_center_to_axle_center = {-1.4_m, 0.0_m, -0.5_m}; - ego_properties.rear_axle.max_steering = 0_rad; - ego_properties.rear_axle.track_width = 1.68_m; - ego_properties.rear_axle.wheel_diameter = 0.8_m; - ego_properties.is_host = true; - // Necessary because Create() is always called in engine init and will otherwise not return a MockVehicle ref - // which results in an exception - ON_CALL(dynamic_cast<mantle_api::MockEntityRepository&>(env_->GetEntityRepository()), - Create(testing::_, ego_properties)) - .WillByDefault(testing::ReturnRef(mock_vehicle_)); - } - - mantle_api::MockVehicle mock_vehicle_{}; +protected: + void SetUp() override + { + OpenScenarioEngineLibraryTestBase::SetUp(); + + mantle_api::VehicleProperties ego_properties{}; + ego_properties.type = mantle_api::EntityType::kVehicle; + ego_properties.classification = mantle_api::VehicleClass::kMedium_car; + ego_properties.model = "medium_car"; + ego_properties.bounding_box.dimension.length = 5.0_m; + ego_properties.bounding_box.dimension.width = 2.0_m; + ego_properties.bounding_box.dimension.height = 1.8_m; + ego_properties.bounding_box.geometric_center.x = 1.4_m; + ego_properties.bounding_box.geometric_center.y = 0.0_m; + ego_properties.bounding_box.geometric_center.z = 0.9_m; + ego_properties.performance.max_acceleration = 10_mps_sq; + ego_properties.performance.max_deceleration = 10_mps_sq; + ego_properties.performance.max_speed = 70_mps; + ego_properties.front_axle.bb_center_to_axle_center = {1.58_m, 0.0_m, -0.5_m}; + ego_properties.front_axle.max_steering = 0.5_rad; + ego_properties.front_axle.track_width = 1.68_m; + ego_properties.front_axle.wheel_diameter = 0.8_m; + ego_properties.rear_axle.bb_center_to_axle_center = {-1.4_m, 0.0_m, -0.5_m}; + ego_properties.rear_axle.max_steering = 0_rad; + ego_properties.rear_axle.track_width = 1.68_m; + ego_properties.rear_axle.wheel_diameter = 0.8_m; + ego_properties.is_host = true; + // Necessary because Create() is always called in engine init and will otherwise not return a MockVehicle ref + // which results in an exception + ON_CALL(dynamic_cast<mantle_api::MockEntityRepository&>(env_->GetEntityRepository()), + Create(testing::_, ego_properties)) + .WillByDefault(testing::ReturnRef(mock_vehicle_)); + } + + mantle_api::MockVehicle mock_vehicle_{}; }; } // namespace testing::OpenScenarioEngine::v1_3 -- GitLab From 171ab6cddb46926c4c19328e10ef3450c1530fa2 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 10 Apr 2025 18:18:32 +0200 Subject: [PATCH 10/15] feat: modify old tests for new feature --- engine/tests/Node/EventNodeTest.cpp | 18 +++++--- engine/tests/Node/ManeuverNodeTest.cpp | 62 +++++++++++++------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/engine/tests/Node/EventNodeTest.cpp b/engine/tests/Node/EventNodeTest.cpp index 899c66c4..2df19a3f 100644 --- a/engine/tests/Node/EventNodeTest.cpp +++ b/engine/tests/Node/EventNodeTest.cpp @@ -18,9 +18,11 @@ #include "Node/EventNode.h" #include "Node/Testing/FakeActionNode.h" #include "TestUtils/MockEventPrioritizer.h" +#include "Utils/StoryBoardElementStateManager.h" using OpenScenarioEngine::v1_3::EventPriority; using OpenScenarioEngine::v1_3::IEventPrioritizer; +using OpenScenarioEngine::v1_3::StoryBoardElementStateManager; using OpenScenarioEngine::v1_3::Node::EventNode; using testing::Return; using testing::OpenScenarioEngine::v1_3::FakeActionNode; @@ -30,13 +32,16 @@ class TreeWithPrioritizer { public: TreeWithPrioritizer() - : event_prioritizer_{std::make_shared<MockEventPrioritizer>()} + : event_prioritizer_{std::make_shared<MockEventPrioritizer>()}, story_board_element_state_manager_{std::make_shared<StoryBoardElementStateManager>()} { - auto declaration = std::make_unique< - yase::TypeDeclarer< - std::shared_ptr< - IEventPrioritizer>>>("EventPrioritizer", event_prioritizer_); - root_ = std::make_shared<yase::DataDeclarationNode>("RootWithEventPrioritizer", std::move(declaration)); + std::vector<yase::DataDeclaration::UPtr> declarations; + declarations.push_back(std::make_unique<yase::TypeDeclarer<std::shared_ptr<IEventPrioritizer>>>( + "EventPrioritizer", event_prioritizer_)); + declarations.push_back(std::make_unique<yase::TypeDeclarer<std::shared_ptr<StoryBoardElementStateManager>>>( + "StoryBoardElementStateManager", story_board_element_state_manager_)); + + root_ = std::make_shared<yase::DataDeclarationNode>( + "RootWithEventPrioritizer", std::move(declarations)); } yase::DecoratorNode& get_root() @@ -51,6 +56,7 @@ public: private: std::shared_ptr<MockEventPrioritizer> event_prioritizer_; + std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; yase::DataDeclarationNode::Ptr root_; }; diff --git a/engine/tests/Node/ManeuverNodeTest.cpp b/engine/tests/Node/ManeuverNodeTest.cpp index 310adc44..f4bdfcde 100644 --- a/engine/tests/Node/ManeuverNodeTest.cpp +++ b/engine/tests/Node/ManeuverNodeTest.cpp @@ -8,8 +8,8 @@ * SPDX-License-Identifier: EPL-2.0 ********************************************************************************/ -#include <agnostic_behavior_tree/decorator/data_declaration_node.h> #include <agnostic_behavior_tree/composite/parallel_node.h> +#include <agnostic_behavior_tree/decorator/data_declaration_node.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -18,12 +18,14 @@ #include "Node/EventNode.h" #include "Node/ManeuverNode.h" #include "Node/Testing/FakeActionNode.h" +#include "TestUtils.h" using OpenScenarioEngine::v1_3::EventPriority; using OpenScenarioEngine::v1_3::Node::EventNode; using OpenScenarioEngine::v1_3::Node::ManeuverNode; using testing::Return; using testing::OpenScenarioEngine::v1_3::FakeActionNode; +using testing::OpenScenarioEngine::v1_3::FakeRootNode; enum class OscStatus : std::uint8_t { @@ -42,6 +44,7 @@ protected: ManeuverNodeTest() { maneuver_node->setChild(events_node); + root_node->setChild(maneuver_node); } EventWithStartTrigger AddEventWithPriority(EventPriority priority) @@ -96,6 +99,7 @@ protected: std::shared_ptr<ManeuverNode> maneuver_node = std::make_shared<ManeuverNode>("Maneuver Node"); std::shared_ptr<yase::ParallelNode> events_node = std::make_shared<yase::ParallelNode>("Events Node"); + std::shared_ptr<FakeRootNode> root_node = std::make_shared<FakeRootNode>(nullptr, nullptr, nullptr); }; TEST_F(ManeuverNodeTest, GivenMultipleNodesWithParallelPriority_WhenManeuverTicks_ThenAllEventsRunning) @@ -103,14 +107,14 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithParallelPriority_WhenManeuverTick auto [event1, start_trigger1] = AddEventWithPriority(EventPriority::kParallel); auto [event2, start_trigger2] = AddEventWithPriority(EventPriority::kParallel); auto [event3, start_trigger3] = AddEventWithPriority(EventPriority::kParallel); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event3, start_trigger3), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kRunning); @@ -122,8 +126,8 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithParallelorSkipPriority_WhenManeuv auto [event1, start_trigger1] = AddEventWithPriority(EventPriority::kParallel); auto [event2, start_trigger2] = AddEventWithPriority(EventPriority::kSkip); auto [event3, start_trigger3] = AddEventWithPriority(EventPriority::kParallel); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -137,15 +141,15 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithOneOverridePriority_WhenManeuverT auto [event3, start_trigger3] = AddEventWithPriority(EventPriority::kParallel); auto [event4, start_trigger4] = AddEventWithPriority(EventPriority::kOverride); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); EXPECT_THAT(GetEventStatus(event3, start_trigger3), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event4, start_trigger4), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -157,28 +161,28 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithOneOverridePriority_WhenManeuverT { auto [event1, start_trigger1] = AddEventWithPriority(EventPriority::kParallel); EXPECT_CALL(start_trigger1, tick()) - .WillOnce(Return(yase::NodeStatus::kRunning)) - .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); + .WillOnce(Return(yase::NodeStatus::kRunning)) + .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); auto [event2, start_trigger2] = AddEventWithPriority(EventPriority::kSkip); auto [event3, start_trigger3] = AddEventWithPriority(EventPriority::kParallel); auto [event4, start_trigger4] = AddEventWithPriority(EventPriority::kOverride); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kStandby); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); EXPECT_THAT(GetEventStatus(event3, start_trigger3), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event4, start_trigger4), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); EXPECT_THAT(GetEventStatus(event3, start_trigger3), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event4, start_trigger4), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -186,7 +190,6 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithOneOverridePriority_WhenManeuverT EXPECT_THAT(GetEventStatus(event4, start_trigger4), OscStatus::kRunning); } - TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenManeuverTicks_ThenOnlyStartedEventsOverridden) { auto [event1, start_trigger1] = AddEventWithPriority(EventPriority::kParallel); @@ -195,16 +198,16 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenMane auto [event4, start_trigger4] = AddEventWithPriority(EventPriority::kOverride); auto [event5, start_trigger5] = AddEventWithPriority(EventPriority::kParallel); EXPECT_CALL(start_trigger5, tick()) - .WillOnce(Return(yase::NodeStatus::kRunning)) - .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); + .WillOnce(Return(yase::NodeStatus::kRunning)) + .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); auto [event6, start_trigger6] = AddEventWithPriority(EventPriority::kOverride); EXPECT_CALL(start_trigger6, tick()) - .WillOnce(Return(yase::NodeStatus::kRunning)) - .WillOnce(Return(yase::NodeStatus::kRunning)) - .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); + .WillOnce(Return(yase::NodeStatus::kRunning)) + .WillOnce(Return(yase::NodeStatus::kRunning)) + .WillRepeatedly(Return(yase::NodeStatus::kSuccess)); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -213,7 +216,7 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenMane EXPECT_THAT(GetEventStatus(event5, start_trigger5), OscStatus::kStandby); EXPECT_THAT(GetEventStatus(event6, start_trigger6), OscStatus::kStandby); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -222,7 +225,7 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenMane EXPECT_THAT(GetEventStatus(event5, start_trigger5), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event6, start_trigger6), OscStatus::kStandby); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -231,7 +234,7 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenMane EXPECT_THAT(GetEventStatus(event5, start_trigger5), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event6, start_trigger6), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); @@ -241,7 +244,6 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithMultipleOverridePriority_WhenMane EXPECT_THAT(GetEventStatus(event6, start_trigger6), OscStatus::kRunning); } - TEST_F(ManeuverNodeTest, GivenMultipleNodesWithOneOverwritePriority_WhenManeuverTicks_ThenParallelEventsOverridden) { auto [event1, start_trigger1] = AddEventWithPriority(EventPriority::kParallel); @@ -249,15 +251,15 @@ TEST_F(ManeuverNodeTest, GivenMultipleNodesWithOneOverwritePriority_WhenManeuver auto [event3, start_trigger3] = AddEventWithPriority(EventPriority::kParallel); auto [event4, start_trigger4] = AddEventWithPriority(EventPriority::kOverwrite); - maneuver_node->distributeData(); - maneuver_node->executeTick(); + root_node->distributeData(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); EXPECT_THAT(GetEventStatus(event3, start_trigger3), OscStatus::kRunning); EXPECT_THAT(GetEventStatus(event4, start_trigger4), OscStatus::kRunning); - maneuver_node->executeTick(); + root_node->executeTick(); EXPECT_THAT(GetEventStatus(event1, start_trigger1), OscStatus::kSuccess); EXPECT_THAT(GetEventStatus(event2, start_trigger2), OscStatus::kSkipped); -- GitLab From bb9e49f6730dd53f8b708014250b5443f115896d Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Fri, 11 Apr 2025 10:11:55 +0200 Subject: [PATCH 11/15] fix: correct typos --- .../Conversion/OscToMantle/ConvertScenarioStoryboardElement.h | 2 +- ...ElementStateManage.cpp => StoryBoardElementStateManager.cpp} | 0 engine/src/Utils/StoryBoardElementStateManager.h | 2 +- .../Utils/{StoryboardElementType.h => StoryBoardElementType.h} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename engine/src/Utils/{StoryBoardElementStateManage.cpp => StoryBoardElementStateManager.cpp} (100%) rename engine/src/Utils/{StoryboardElementType.h => StoryBoardElementType.h} (100%) diff --git a/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h b/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h index 8f7e1dc0..79250253 100644 --- a/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h +++ b/engine/src/Conversion/OscToMantle/ConvertScenarioStoryboardElement.h @@ -18,7 +18,7 @@ #include "Utils/StoryBoardElementState.h" #include "Utils/StoryBoardElementTransition.h" -#include "Utils/StoryboardElementType.h" +#include "Utils/StoryBoardElementType.h" namespace OpenScenarioEngine::v1_3 { diff --git a/engine/src/Utils/StoryBoardElementStateManage.cpp b/engine/src/Utils/StoryBoardElementStateManager.cpp similarity index 100% rename from engine/src/Utils/StoryBoardElementStateManage.cpp rename to engine/src/Utils/StoryBoardElementStateManager.cpp diff --git a/engine/src/Utils/StoryBoardElementStateManager.h b/engine/src/Utils/StoryBoardElementStateManager.h index 4590e013..e945d1ae 100644 --- a/engine/src/Utils/StoryBoardElementStateManager.h +++ b/engine/src/Utils/StoryBoardElementStateManager.h @@ -18,7 +18,7 @@ #include "Utils/StoryBoardElementState.h" #include "Utils/StoryBoardElementTransition.h" -#include "Utils/StoryboardElementType.h" +#include "Utils/StoryBoardElementType.h" namespace OpenScenarioEngine::v1_3 { diff --git a/engine/src/Utils/StoryboardElementType.h b/engine/src/Utils/StoryBoardElementType.h similarity index 100% rename from engine/src/Utils/StoryboardElementType.h rename to engine/src/Utils/StoryBoardElementType.h -- GitLab From 3a2aad4a1108fd0bed26aff3dee4f994effe2e58 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Fri, 11 Apr 2025 10:12:15 +0200 Subject: [PATCH 12/15] build: update cmake --- engine/cmake/generated_files.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/engine/cmake/generated_files.cmake b/engine/cmake/generated_files.cmake index 6644cd17..ee4160f1 100644 --- a/engine/cmake/generated_files.cmake +++ b/engine/cmake/generated_files.cmake @@ -242,6 +242,7 @@ list(APPEND ${PROJECT_NAME}_SOURCES src/Utils/EntityUtils.cpp src/Utils/EventPrioritizer.cpp src/Utils/Logger.cpp + src/Utils/StoryBoardElementStateManager.cpp src/Utils/TrafficSignalBuilder.cpp ) @@ -610,5 +611,9 @@ list(APPEND ${PROJECT_NAME}_HEADERS src/Utils/IControllerService.h src/Utils/IEventPrioritizer.h src/Utils/Logger.h + src/Utils/StoryBoardElementState.h + src/Utils/StoryBoardElementStateManager.h + src/Utils/StoryBoardElementTransition.h + src/Utils/StoryBoardElementType.h src/Utils/TrafficSignalBuilder.h ) -- GitLab From 4915df6744974fb6146ec54fea3b3e4ade9181b0 Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Fri, 11 Apr 2025 10:44:52 +0200 Subject: [PATCH 13/15] build: add actNode --- engine/cmake/generated_files.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/cmake/generated_files.cmake b/engine/cmake/generated_files.cmake index ee4160f1..ee0ea943 100644 --- a/engine/cmake/generated_files.cmake +++ b/engine/cmake/generated_files.cmake @@ -190,6 +190,7 @@ list(APPEND ${PROJECT_NAME}_SOURCES src/Conversion/OscToNode/ParseStory.cpp src/Conversion/OscToNode/ParseStoryboard.cpp src/Conversion/OscToNode/ParseTrafficSignals.cpp + src/Node/ActNode.cpp src/Node/ByEntityConditionNode.cpp src/Node/ConditionGroupsNode.cpp src/Node/ConditionNode.cpp -- GitLab From 748f6df171dd5482109d384212d648c163f4623a Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Tue, 15 Apr 2025 14:57:15 +0200 Subject: [PATCH 14/15] feat: add StateAwareActionNode --- engine/cmake/generated_files.cmake | 1 + .../MotionControlAction/SpeedAction.h | 42 +++++--------- engine/src/Node/StateAwareActionNode.h | 56 +++++++++++++++++++ .../LongitudinalDistanceAction.h | 37 ++++-------- 4 files changed, 81 insertions(+), 55 deletions(-) create mode 100644 engine/src/Node/StateAwareActionNode.h diff --git a/engine/cmake/generated_files.cmake b/engine/cmake/generated_files.cmake index ee0ea943..4582b70e 100644 --- a/engine/cmake/generated_files.cmake +++ b/engine/cmake/generated_files.cmake @@ -572,6 +572,7 @@ list(APPEND ${PROJECT_NAME}_HEADERS src/Node/PrivateNode.h src/Node/RepeatingSequenceNode.h src/Node/RootNode.h + src/Node/StateAwareActionNode.h src/Node/StoryboardNode.h src/Node/TrafficSignalPhaseNode.h src/Node/TriggerableCompositeNode.h diff --git a/engine/gen/Storyboard/MotionControlAction/SpeedAction.h b/engine/gen/Storyboard/MotionControlAction/SpeedAction.h index d91295af..95a9f4c1 100644 --- a/engine/gen/Storyboard/MotionControlAction/SpeedAction.h +++ b/engine/gen/Storyboard/MotionControlAction/SpeedAction.h @@ -17,6 +17,7 @@ #include <cassert> #include <utility> +#include "Node/StateAwareActionNode.h" #include "Storyboard/MotionControlAction/MotionControlAction.h" #include "Storyboard/MotionControlAction/SpeedAction_impl.h" #include "Utils/EntityBroker.h" @@ -24,57 +25,42 @@ namespace OpenScenarioEngine::v1_3::Node { -class SpeedAction : public yase::ActionNode +class SpeedAction : public StateAwareActionNode { public: - SpeedAction(std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ISpeedAction> speedAction) - : yase::ActionNode{"SpeedAction"}, - speedAction_{speedAction} + explicit SpeedAction(std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ISpeedAction> speedAction) + : StateAwareActionNode("SpeedAction", [this]() + { + assert(impl_); + return impl_->Step(); }), + speedAction_{std::move(speedAction)} { } void onInit() override{}; private: - yase::NodeStatus tick() override + void lookupAndRegisterData(yase::Blackboard& blackboard) override { - assert(impl_); - const auto is_finished = impl_->Step(); + StateAwareActionNode::lookupAndRegisterData(blackboard); - if (is_finished) - { - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementTransition::kEndTransition); - // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kCompleteState); - } - else - { - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kRunningState); - } - - return is_finished ? yase::NodeStatus::kSuccess : yase::NodeStatus::kRunning; - }; - - void lookupAndRegisterData(yase::Blackboard& blackboard) final - { auto environment = blackboard.get<std::shared_ptr<mantle_api::IEnvironment>>("Environment"); const auto entityBroker = blackboard.get<EntityBroker::Ptr>("EntityBroker"); - story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kStandbyState); impl_ = std::make_unique<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::SpeedAction>>( OpenScenarioEngine::v1_3::SpeedAction::Values{ entityBroker->GetEntities(), ConvertScenarioTransitionDynamics(speedAction_->GetSpeedActionDynamics()), [=]() - { return ConvertScenarioSpeedActionTarget(environment, speedAction_->GetSpeedActionTarget()); }}, + { + return ConvertScenarioSpeedActionTarget(environment, speedAction_->GetSpeedActionTarget()); + }}, OpenScenarioEngine::v1_3::SpeedAction::Interfaces{ environment}); } - std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::SpeedAction>> impl_{nullptr}; + std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::SpeedAction>> impl_; std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ISpeedAction> speedAction_; - std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/StateAwareActionNode.h b/engine/src/Node/StateAwareActionNode.h new file mode 100644 index 00000000..7c2834f1 --- /dev/null +++ b/engine/src/Node/StateAwareActionNode.h @@ -0,0 +1,56 @@ +/******************************************************************************** + * Copyright (c) 2025 Ansys, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ + +#pragma once + +#include <agnostic_behavior_tree/action_node.h> + +#include "Utils/StoryBoardElementStateManager.h" + +namespace OpenScenarioEngine::v1_3::Node +{ + +using ImplStepFunction = std::function<bool()>; + +class StateAwareActionNode : public yase::ActionNode +{ +public: + StateAwareActionNode(const std::string& name, ImplStepFunction step_fn) + : yase::ActionNode{name}, step_fn_{std::move(step_fn)} {} + + yase::NodeStatus tick() override + { + const bool is_finished = step_fn_(); + + if (is_finished) + { + state_manager_->Update(name(), type_, StoryBoardElementTransition::kEndTransition); + state_manager_->Update(name(), type_, StoryBoardElementState::kCompleteState); + return yase::NodeStatus::kSuccess; + } + + state_manager_->Update(name(), type_, StoryBoardElementState::kRunningState); + return yase::NodeStatus::kRunning; + } + + void lookupAndRegisterData(yase::Blackboard& blackboard) override + { + state_manager_ = blackboard.get<std::shared_ptr<StoryBoardElementStateManager>>("StoryBoardElementStateManager"); + state_manager_->Update(name(), type_, StoryBoardElementState::kStandbyState); + } + +protected: + StoryBoardElementType type_{StoryBoardElementType::kAction}; + +private: + ImplStepFunction step_fn_; + std::shared_ptr<StoryBoardElementStateManager> state_manager_; +}; +} // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h b/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h index 0bc2a1f6..0adcd69c 100644 --- a/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h +++ b/engine/src/Storyboard/MotionControlAction/LongitudinalDistanceAction.h @@ -17,6 +17,7 @@ #include <cassert> #include <utility> +#include "Node/StateAwareActionNode.h" #include "Storyboard/MotionControlAction/LongitudinalDistanceAction_impl.h" #include "Storyboard/MotionControlAction/MotionControlAction.h" #include "Utils/EntityBroker.h" @@ -24,11 +25,14 @@ namespace OpenScenarioEngine::v1_3::Node { -class LongitudinalDistanceAction : public yase::ActionNode +class LongitudinalDistanceAction : public StateAwareActionNode { public: explicit LongitudinalDistanceAction(std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ILongitudinalDistanceAction> longitudinalDistanceAction) - : yase::ActionNode{"LongitudinalDistanceAction"}, + : StateAwareActionNode("LongitudinalDistanceAction", [this]() + { + assert(impl_); + return impl_->Step(); }), longitudinalDistanceAction_{std::move(longitudinalDistanceAction)} { } @@ -36,31 +40,12 @@ public: void onInit() override{}; private: - yase::NodeStatus tick() override + void lookupAndRegisterData(yase::Blackboard& blackboard) override { - assert(impl_); - const auto is_finished = impl_->Step(); + StateAwareActionNode::lookupAndRegisterData(blackboard); - if (is_finished) - { - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementTransition::kEndTransition); - // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kCompleteState); - } - else - { - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kRunningState); - } - - return is_finished ? yase::NodeStatus::kSuccess : yase::NodeStatus::kRunning; - }; - - void lookupAndRegisterData(yase::Blackboard& blackboard) final - { auto environment = blackboard.get<std::shared_ptr<mantle_api::IEnvironment>>("Environment"); const auto entityBroker = blackboard.get<EntityBroker::Ptr>("EntityBroker"); - story_board_element_state_manager_ = blackboard.get<std::shared_ptr<OpenScenarioEngine::v1_3::StoryBoardElementStateManager>>("StoryBoardElementStateManager"); - story_board_element_state_manager_->Update(name(), StoryBoardElementType::kAction, StoryBoardElementState::kStandbyState); impl_ = std::make_unique<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::LongitudinalDistanceAction>>( OpenScenarioEngine::v1_3::LongitudinalDistanceAction::Values{ @@ -81,13 +66,11 @@ private: ConvertScenarioDynamicConstraints(longitudinalDistanceAction_->IsSetDynamicConstraints(), longitudinalDistanceAction_->GetDynamicConstraints()), ConvertScenarioEntity(longitudinalDistanceAction_->GetEntityRef()), ConvertScenarioCoordinateSystem(longitudinalDistanceAction_->GetCoordinateSystem())}, - OpenScenarioEngine::v1_3::LongitudinalDistanceAction::Interfaces{ - environment}); + OpenScenarioEngine::v1_3::LongitudinalDistanceAction::Interfaces{environment}); } - std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::LongitudinalDistanceAction>> impl_{nullptr}; + std::unique_ptr<OpenScenarioEngine::v1_3::MotionControlAction<OpenScenarioEngine::v1_3::LongitudinalDistanceAction>> impl_; std::shared_ptr<NET_ASAM_OPENSCENARIO::v1_3::ILongitudinalDistanceAction> longitudinalDistanceAction_; - std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; }; } // namespace OpenScenarioEngine::v1_3::Node -- GitLab From 5d5c741b05fc064c0ae611e1a3e6d18c1db2971c Mon Sep 17 00:00:00 2001 From: "ziqi.zhou" <ziqi.zhou@ansys.com> Date: Thu, 22 May 2025 17:22:23 +0200 Subject: [PATCH 15/15] refactor: refactor based on the comments --- engine/src/Node/ActNode.cpp | 72 ++++++++++++++++------ engine/src/Node/ActNode.h | 4 ++ engine/src/Node/EventNode.cpp | 58 +++++++++++------ engine/src/Node/EventNode.h | 2 + engine/src/Node/ManeuverNode.cpp | 35 ++++++----- engine/src/Node/ManeuverNode.h | 4 +- engine/src/Node/TriggerableCompositeNode.h | 4 +- 7 files changed, 122 insertions(+), 57 deletions(-) diff --git a/engine/src/Node/ActNode.cpp b/engine/src/Node/ActNode.cpp index 4b33e9ce..9b2e32af 100644 --- a/engine/src/Node/ActNode.cpp +++ b/engine/src/Node/ActNode.cpp @@ -30,37 +30,69 @@ void ActNode::lookupAndRegisterData(yase::Blackboard& blackboard) yase::NodeStatus ActNode::tick() { - // reset transition to unknown in every tick + // Reset transition to unknown in every tick story_board_element_state_manager_->ResetTransition(getOriginalName(), StoryBoardElementType::kAct); auto current_status = TriggerableCompositeNode::tick(); - if (start_trigger_ == nullptr || start_trigger_->status() == yase::NodeStatus::kSuccess) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStartTransition); - } - if (stop_trigger_ != nullptr && stop_trigger_->status() == yase::NodeStatus::kSuccess) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStopTransition); - } + UpdateTriggerBasedTransitions(); + UpdateElementState(current_status); - if (current_status == yase::NodeStatus::kSuccess) + return current_status; +} + +void ActNode::UpdateTriggerBasedTransitions() +{ + yase::NodeStatus current_start_trigger_status = start_trigger_ ? start_trigger_->status() : yase::NodeStatus::kSuccess; + if (current_start_trigger_status != last_start_trigger_status_) { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kEndTransition); - // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kCompleteState); + if (current_start_trigger_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStartTransition); + } + last_start_trigger_status_ = current_start_trigger_status; } - else if (current_status == yase::NodeStatus::kRunning) + + if (stop_trigger_) { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kRunningState); + yase::NodeStatus current_stop_trigger_status = stop_trigger_->status(); + if (current_stop_trigger_status != last_stop_trigger_status_) + { + if (current_stop_trigger_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kStopTransition); + } + last_stop_trigger_status_ = current_stop_trigger_status; + } } - else +} + +void ActNode::UpdateElementState(yase::NodeStatus current_status) +{ + switch (current_status) { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kUnknown); - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kUnknown); - } + case yase::NodeStatus::kSuccess: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather than kStandbyState. + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kCompleteState); + break; - return current_status; + case yase::NodeStatus::kRunning: + if (start_trigger_ && start_trigger_->status() == yase::NodeStatus::kRunning) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kStandbyState); + } + else + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kRunningState); + } + break; + + default: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kAct, StoryBoardElementState::kUnknown); + break; + } } } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/ActNode.h b/engine/src/Node/ActNode.h index ac8c7dda..0e19c4c7 100644 --- a/engine/src/Node/ActNode.h +++ b/engine/src/Node/ActNode.h @@ -32,9 +32,13 @@ public: yase::NodeStatus tick() override; private: + void UpdateTriggerBasedTransitions(); + void UpdateElementState(yase::NodeStatus current_status); yase::BehaviorNode::Ptr start_trigger_; yase::BehaviorNode::Ptr stop_trigger_; std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; + yase::NodeStatus last_start_trigger_status_{yase::NodeStatus::kIdle}; + yase::NodeStatus last_stop_trigger_status_{yase::NodeStatus::kIdle}; }; } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/EventNode.cpp b/engine/src/Node/EventNode.cpp index e14e5229..41f6735c 100644 --- a/engine/src/Node/EventNode.cpp +++ b/engine/src/Node/EventNode.cpp @@ -46,35 +46,55 @@ yase::NodeStatus EventNode::tick() if (event_prioritizer_->ShouldSkipChild(name())) { story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kSkipTransition); - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kStandbyState); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather than kStandbyState. + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kCompleteState); return yase::NodeStatus::kSuccess; } auto current_status = TriggerableCompositeNode::tick(); - if (start_trigger_ == nullptr || start_trigger_->status() == yase::NodeStatus::kSuccess) + yase::NodeStatus current_start_status = start_trigger_ ? start_trigger_->status() : yase::NodeStatus::kSuccess; + if (current_start_status != last_start_trigger_status_) { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kStartTransition); - event_prioritizer_->EventStarted(name()); + if (current_start_status == yase::NodeStatus::kSuccess) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kStartTransition); + event_prioritizer_->EventStarted(name()); + } + last_start_trigger_status_ = current_start_status; } - if (current_status == yase::NodeStatus::kSuccess) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kEndTransition); - // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather that kStandbyState. - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kCompleteState); - } - else if (current_status == yase::NodeStatus::kRunning) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kRunningState); - } - else - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kUnknown); - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kUnknown); - } + UpdateElementState(current_status); return current_status; } +void EventNode::UpdateElementState(yase::NodeStatus current_status) +{ + switch (current_status) + { + case yase::NodeStatus::kSuccess: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kEndTransition); + // Since maximumExecutionCount is not supported, after status is kSuccess, the state will be updated to kCompleteState rather than kStandbyState. + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kCompleteState); + break; + + case yase::NodeStatus::kRunning: + if (start_trigger_ && start_trigger_->status() == yase::NodeStatus::kRunning) + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kStandbyState); + } + else + { + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kRunningState); + } + break; + + default: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kEvent, StoryBoardElementState::kUnknown); + break; + } +} + } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/EventNode.h b/engine/src/Node/EventNode.h index 4aac076c..0e5ce7bd 100644 --- a/engine/src/Node/EventNode.h +++ b/engine/src/Node/EventNode.h @@ -40,10 +40,12 @@ public: yase::NodeStatus tick() override; private: + void UpdateElementState(yase::NodeStatus current_status); EventPriority event_priority_; yase::BehaviorNode::Ptr start_trigger_; std::shared_ptr<IEventPrioritizer> event_prioritizer_; std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; + yase::NodeStatus last_start_trigger_status_{yase::NodeStatus::kIdle}; }; } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/ManeuverNode.cpp b/engine/src/Node/ManeuverNode.cpp index 0398e046..524e4f55 100644 --- a/engine/src/Node/ManeuverNode.cpp +++ b/engine/src/Node/ManeuverNode.cpp @@ -30,20 +30,7 @@ yase::NodeStatus ManeuverNode::tick() auto current_status = child().executeTick(); - if (current_status == yase::NodeStatus::kSuccess) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kEndTransition); - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kCompleteState); - } - else if (current_status == yase::NodeStatus::kRunning) - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kRunningState); - } - else - { - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kUnknown); - story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kUnknown); - } + UpdateElementState(current_status); return current_status; } @@ -55,4 +42,24 @@ void ManeuverNode::lookupAndRegisterData(yase::Blackboard& blackboard) story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuverGroup, StoryBoardElementState::kStandbyState); } +void ManeuverNode::UpdateElementState(yase::NodeStatus current_status) +{ + switch (current_status) + { + case yase::NodeStatus::kSuccess: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kEndTransition); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kCompleteState); + break; + + case yase::NodeStatus::kRunning: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kRunningState); + break; + + default: + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementTransition::kUnknown); + story_board_element_state_manager_->Update(getOriginalName(), StoryBoardElementType::kManeuver, StoryBoardElementState::kUnknown); + break; + } +} + } // namespace OpenScenarioEngine::v1_3::Node diff --git a/engine/src/Node/ManeuverNode.h b/engine/src/Node/ManeuverNode.h index 0e6855a8..207ee2dd 100644 --- a/engine/src/Node/ManeuverNode.h +++ b/engine/src/Node/ManeuverNode.h @@ -30,11 +30,11 @@ public: /// @param name Name of the maneuver node explicit ManeuverNode(const std::string& name); - [[nodiscard]] const std::string& getOriginalName() const; - private: void lookupAndRegisterData(yase::Blackboard& blackboard) override; yase::NodeStatus tick() final; + void UpdateElementState(yase::NodeStatus current_status); + [[nodiscard]] const std::string& getOriginalName() const; std::shared_ptr<IEventPrioritizer> eventPrioritizer_; std::shared_ptr<StoryBoardElementStateManager> story_board_element_state_manager_; diff --git a/engine/src/Node/TriggerableCompositeNode.h b/engine/src/Node/TriggerableCompositeNode.h index e4c1c112..c4a633e8 100644 --- a/engine/src/Node/TriggerableCompositeNode.h +++ b/engine/src/Node/TriggerableCompositeNode.h @@ -151,8 +151,6 @@ public: } } - [[nodiscard]] const std::string& getOriginalName() const { return original_name_; } - protected: using yase::CompositeNode::addChild; @@ -195,6 +193,8 @@ protected: return tickWithStopTrigger(); } + [[nodiscard]] const std::string& getOriginalName() const { return original_name_; } + private: void setTransientNode(const std::string& name, yase::BehaviorNode::Ptr child, TransientNode::Ptr& member) { -- GitLab