AutoAPMS
Resilient Robot Mission Management
Loading...
Searching...
No Matches
mission_builder.cpp
1// Copyright 2024 Robin Müller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "auto_apms_mission/mission_builder_base.hpp"
16#include "auto_apms_util/container.hpp"
17
18namespace auto_apms_mission
19{
20
21class SingleNodeMissionBuildHandler : public MissionBuildHandlerBase
22{
23public:
24 using MissionBuildHandlerBase::MissionBuildHandlerBase;
25
26private:
27 void buildMission(
28 TreeDocument::TreeElement & sub_tree, const std::vector<TreeResource::Identity> & trees) override final
29 {
30 sub_tree.removeChildren();
31 for (const TreeResource::Identity & r : trees) {
32 sub_tree.insertTreeFromResource(r);
33 }
34 }
35};
36
37class MultipleNodesMissionBuildHandler : public MissionBuildHandlerBase
38{
39public:
40 using MissionBuildHandlerBase::MissionBuildHandlerBase;
41
42private:
43 void buildMission(
44 TreeDocument::TreeElement & sub_tree, const std::vector<TreeResource::Identity> & trees) override final
45 {
46 TreeDocument doc;
47 TreeDocument::TreeElement mission_tree = doc.newTree("Mission");
48 TreeDocument::NodeElement mission_sequence = mission_tree.insertNode<model::SequenceWithMemory>();
49 for (const TreeResource::Identity & r : trees) {
50 mission_sequence.insertTreeFromResource(r);
51 }
52
53 sub_tree.removeChildren();
55 .setName("Mission")
56 .set_attach(true)
57 .set_clear_blackboard(true)
58 .set_executor(MISSION_EXECUTOR_NAME);
59 }
60
61 void buildEventMonitor(
63 const std::vector<std::pair<TreeResource::Identity, TreeResource::Identity>> & contingencies,
64 const std::vector<std::pair<TreeResource::Identity, TreeResource::Identity>> & emergencies) override final
65 {
66 TreeDocument doc;
67 TreeDocument::TreeElement event_monitor_tree = doc.newTree(sub_tree);
68 MissionBuildHandlerBase::buildEventMonitor(event_monitor_tree, contingencies, emergencies);
69 event_monitor_tree.getFirstNode()
70 .setName(event_monitor_tree.getName())
71 .setConditionalScript(BT::PostCond::ON_SUCCESS, "@event_id = event_id")
72 .setConditionalScript(BT::PostCond::ON_FAILURE, "@event_id = ''");
73 TreeDocument::TreeElement main_tree = doc.newTree("InfiniteLoopEventMonitor");
74 main_tree.insertNode<model::KeepRunningUntilFailure>().insertNode<model::ForceSuccess>().insertTree(
75 event_monitor_tree);
76
77 // Retrieve the event ID from the event monitor executor
78 model::Sequence seq = sub_tree.removeChildren().insertNode<model::Sequence>();
79 model::Sequence run_once_seq = seq.insertNode<model::RunOnce>().insertNode<model::Sequence>();
80 run_once_seq.insertNode<model::SetParameterString>()
81 .set_node(EVENT_MONITOR_EXECUTOR_NAME)
82 .set_parameter("bb.event_id")
83 .set_value("");
85 .setName("StartDetachedEventMonitor")
86 .set_attach(false)
87 .set_clear_blackboard(false)
88 .set_executor(EVENT_MONITOR_EXECUTOR_NAME);
89 seq.insertNode<model::GetParameterString>()
90 .set_node(EVENT_MONITOR_EXECUTOR_NAME)
91 .set_parameter("bb.event_id")
92 .set_value("{event_id}");
93 }
94
95 void buildContingencyHandling(
97 const std::vector<std::pair<TreeResource::Identity, TreeResource::Identity>> & contingencies) override final
98 {
99 TreeDocument doc;
100 TreeDocument::TreeElement handler_tree = doc.newTree(sub_tree.getName());
101 model::Parallel parallel = handler_tree.insertNode<model::Parallel>().set_success_count(1).set_failure_count(1);
102 parallel.insertNode<model::KeepRunningUntilFailure>()
103 .insertNode<model::GetParameterString>()
104 .set_node(EVENT_MONITOR_EXECUTOR_NAME)
105 .set_parameter("bb.event_id")
106 .set_value("{event_id}");
107 TreeDocument::TreeElement base_tree = doc.newTree("HandlerBaseTree");
108 MissionBuildHandlerBase::buildContingencyHandling(base_tree, contingencies);
109 parallel.insertNode<model::WaitValueUpdate>().set_entry("{event_id}").insertTree(base_tree);
110
111 auto_apms_behavior_tree::insertStartExecutorFromString(sub_tree.removeChildren(), handler_tree)
112 .setName(handler_tree.getName())
113 .set_attach(true)
114 .set_clear_blackboard(true)
115 .set_executor(EVENT_HANDLER_EXECUTOR_NAME);
116 }
117
118 void buildEmergencyHandling(
119 TreeDocument::TreeElement & sub_tree,
120 const std::vector<std::pair<TreeResource::Identity, TreeResource::Identity>> & emergencies) override final
121 {
122 TreeDocument doc;
123 TreeDocument::TreeElement handler_tree = doc.newTree(sub_tree.getName());
124 model::Parallel parallel = handler_tree.insertNode<model::Parallel>().set_success_count(1).set_failure_count(1);
125 parallel.insertNode<model::KeepRunningUntilFailure>()
126 .insertNode<model::GetParameterString>()
127 .set_node(EVENT_MONITOR_EXECUTOR_NAME)
128 .set_parameter("bb.event_id")
129 .set_value("{event_id}");
130 TreeDocument::TreeElement base_tree = doc.newTree("HandlerBaseTree");
131 MissionBuildHandlerBase::buildEmergencyHandling(base_tree, emergencies);
132 parallel.insertNode<model::WaitValueUpdate>().set_entry("{event_id}").insertTree(base_tree);
133
134 auto_apms_behavior_tree::insertStartExecutorFromString(sub_tree.removeChildren(), handler_tree)
135 .setName(handler_tree.getName())
136 .set_attach(true)
137 .set_clear_blackboard(true)
138 .set_executor(EVENT_HANDLER_EXECUTOR_NAME);
139 }
140
141 void buildShutDown(TreeDocument::TreeElement & sub_tree, const std::vector<TreeResource::Identity> & trees)
142 {
143 // First thing: Terminate detached event monitor executor
144 model::SequenceWithMemory seq = sub_tree.removeChildren().insertNode<model::SequenceWithMemory>();
145 seq.insertNode<model::TerminateExecutor>().set_executor(EVENT_MONITOR_EXECUTOR_NAME);
146
147 // Afterwards, execute everything else
148 TreeDocument doc;
149 TreeDocument::TreeElement temp = doc.newTree("TempTree");
150 MissionBuildHandlerBase::buildShutDown(temp, trees);
151 seq.insertTree(temp);
152 }
153};
154
155} // namespace auto_apms_mission
156
157AUTO_APMS_BEHAVIOR_TREE_DECLARE_BUILD_HANDLER(auto_apms_mission::SingleNodeMissionBuildHandler)
158AUTO_APMS_BEHAVIOR_TREE_DECLARE_BUILD_HANDLER(auto_apms_mission::MultipleNodesMissionBuildHandler)
Handle for a single node of a TreeDocument.
virtual NodeElement & setName(const std::string &instance_name)
Assign a name for this specific node instance.
NodeElement insertTree(const TreeElement &tree, const NodeElement *before_this=nullptr)
Concatenate a tree and add its first child node to the children of this node.
NodeElement insertNode(const std::string &name, const NodeElement *before_this=nullptr)
Add a new node to the children of this node.
NodeElement & removeChildren()
Recursively remove all children of this node element.
Handle for a single behavior tree of a TreeDocument.
Base class for behavior tree build handlers that are used to configure missions including fallback me...
#define AUTO_APMS_BEHAVIOR_TREE_DECLARE_BUILD_HANDLER(type)
Macro for registering a behavior tree build handler plugin which may be loaded at runtime to build a ...
model::StartExecutor insertStartExecutorFromString(core::TreeDocument::NodeElement &parent, const std::string &tree_str, const core::TreeDocument::NodeElement *before_this=nullptr)
Helper that extends the children of a given parent node by a StartExecutor node for a specific behavi...
Definition node.cpp:19
Mission design utilities incorporating behavior trees to model the complexity of arbitrary operations...