AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
mission_config.hpp
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#pragma once
16
17#include <utility>
18#include <vector>
19
20#include "auto_apms_behavior_tree_core/behavior.hpp"
21#include "auto_apms_behavior_tree_core/tree/tree_resource.hpp"
22#include "auto_apms_util/exceptions.hpp"
23#include "auto_apms_util/yaml.hpp"
24
25namespace auto_apms_mission
26{
27
28struct MissionConfigResourceIdentity : public auto_apms_behavior_tree::core::BehaviorResourceIdentity
29{
37 MissionConfigResourceIdentity(const std::string & identity);
38
46 MissionConfigResourceIdentity(const char * identity);
47
53 MissionConfigResourceIdentity() = default;
54};
55
60struct MissionConfig
61{
62 using TreeResourceIdentity = auto_apms_behavior_tree::core::TreeResourceIdentity;
63
64 static const std::string YAML_KEY_BRINGUP;
65 static const std::string YAML_KEY_MISSION;
66 static const std::string YAML_KEY_CONTINGENCY;
67 static const std::string YAML_KEY_EMERGENCY;
68 static const std::string YAML_KEY_SHUTDOWN;
69
70 MissionConfig() = default;
71
73
74
84 static MissionConfig fromResource(const MissionConfigResourceIdentity & identity);
85
86 std::vector<TreeResourceIdentity> bringup;
87 std::vector<TreeResourceIdentity> mission;
88 std::vector<std::pair<TreeResourceIdentity, TreeResourceIdentity>> contingency;
89 std::vector<std::pair<TreeResourceIdentity, TreeResourceIdentity>> emergency;
90 std::vector<TreeResourceIdentity> shutdown;
91};
92
93class MissionConfigResource
94: public auto_apms_behavior_tree::core::BehaviorResourceTemplate<MissionConfigResourceIdentity>
95{
96 friend class MissionConfig;
97
98public:
99 using BehaviorResourceTemplate::BehaviorResourceTemplate;
100};
101
102} // namespace auto_apms_mission
103
104// #####################################################################################################################
105// ################################ DEFINITIONS ##############################################
106// #####################################################################################################################
107
109namespace YAML
110{
111template <>
112struct convert<auto_apms_mission::MissionConfig>
113{
114 using Config = auto_apms_mission::MissionConfig;
115 inline static Node encode(const Config & rhs)
116 {
117 Node node(NodeType::Map);
118 node[Config::YAML_KEY_BRINGUP] = rhs.bringup;
119 node[Config::YAML_KEY_MISSION] = rhs.mission;
120 Node contingency_node = node[Config::YAML_KEY_CONTINGENCY];
121 for (const auto & [key, val] : rhs.contingency) {
122 contingency_node[key.str()] = val;
123 }
124 Node emergency_node = node[Config::YAML_KEY_EMERGENCY];
125 for (const auto & [key, val] : rhs.emergency) {
126 emergency_node[key.str()] = val;
127 }
128 node[Config::YAML_KEY_SHUTDOWN] = rhs.shutdown;
129 return node;
130 }
131 inline static bool decode(const Node & node, Config & rhs)
132 {
133 if (!node.IsMap())
134 throw auto_apms_util::exceptions::YAMLFormatError(
135 "YAML::Node for auto_apms_mission::MissionConfig must be map but is type " + std::to_string(node.Type()) +
136 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
137
138 for (auto it = node.begin(); it != node.end(); ++it) {
139 const std::string key = it->first.as<std::string>();
140 const Node val = it->second;
141
142 if (key == Config::YAML_KEY_BRINGUP) {
143 if (val.IsNull()) continue;
144 if (!val.IsSequence()) {
145 throw auto_apms_util::exceptions::YAMLFormatError(
146 "Value for key '" + key + "' must be a sequence but is type " + std::to_string(val.Type()) +
147 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
148 }
149 rhs.bringup = val.as<std::vector<Config::TreeResourceIdentity>>();
150 continue;
151 }
152
153 if (key == Config::YAML_KEY_MISSION) {
154 if (!val.IsSequence()) {
155 throw auto_apms_util::exceptions::YAMLFormatError(
156 "Value for key '" + key + "' must be a sequence but is type " + std::to_string(val.Type()) +
157 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
158 }
159 rhs.mission = val.as<std::vector<Config::TreeResourceIdentity>>();
160 continue;
161 }
162
163 if (key == Config::YAML_KEY_CONTINGENCY) {
164 if (val.IsNull()) continue;
165 if (!val.IsMap()) {
166 throw auto_apms_util::exceptions::YAMLFormatError(
167 "Value for key '" + key + "' must be a map but is type " + std::to_string(val.Type()) +
168 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
169 }
170 for (YAML::const_iterator it2 = val.begin(); it2 != val.end(); ++it2) {
171 const std::string monitor_id = it2->first.as<std::string>();
172 if (!it2->second.IsScalar()) {
173 throw auto_apms_util::exceptions::YAMLFormatError(
174 "Value for key '" + monitor_id + "' in the CONTINGENCY group must be scalar but is type " +
175 std::to_string(val.Type()) + " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
176 }
177 rhs.contingency.push_back(
178 {Config::TreeResourceIdentity(monitor_id), it2->second.as<Config::TreeResourceIdentity>()});
179 }
180 continue;
181 }
182
183 if (key == Config::YAML_KEY_EMERGENCY) {
184 if (val.IsNull()) continue;
185 if (!val.IsMap()) {
186 throw auto_apms_util::exceptions::YAMLFormatError(
187 "Value for key '" + key + "' must be a map but is type " + std::to_string(val.Type()) +
188 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
189 }
190 for (YAML::const_iterator it2 = val.begin(); it2 != val.end(); ++it2) {
191 const std::string monitor_id = it2->first.as<std::string>();
192 if (!it2->second.IsScalar()) {
193 throw auto_apms_util::exceptions::YAMLFormatError(
194 "Value for key '" + monitor_id + "' in the EMERGENCY group must be scalar but is type " +
195 std::to_string(val.Type()) + " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
196 }
197 rhs.emergency.push_back(
198 {Config::TreeResourceIdentity(monitor_id), it2->second.as<Config::TreeResourceIdentity>()});
199 }
200 continue;
201 }
202
203 if (key == Config::YAML_KEY_SHUTDOWN) {
204 if (val.IsNull()) continue;
205 if (!val.IsSequence()) {
206 throw auto_apms_util::exceptions::YAMLFormatError(
207 "Value for key '" + key + "' must be a sequence but is type " + std::to_string(val.Type()) +
208 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
209 }
210 rhs.shutdown = val.as<std::vector<Config::TreeResourceIdentity>>();
211 continue;
212 }
213
214 // Unkown parameter
215 throw auto_apms_util::exceptions::YAMLFormatError("Unkown parameter name '" + key + "'.");
216 }
217 return true;
218 }
219};
220} // namespace YAML
Helper temlpate class for creating behavior resource abstractions.
Definition behavior.hpp:120
#define AUTO_APMS_UTIL_DEFINE_YAML_CONVERSION_METHODS(ClassType)
Macro for defining YAML encode/decode methods for a class.
Definition yaml.hpp:32
Mission design utilities incorporating behavior trees to model the complexity of arbitrary operations...
Struct that encapsulates the identity string for a registered behavior tree.
Configuration parameters for generic missions supported by AutoAPMS.
static MissionConfig fromResource(const MissionConfigResourceIdentity &identity)
Create a mission configuration from an installed resource.