AutoAPMS
Streamlining behaviors in ROS 2
Loading...
Searching...
No Matches
node_registration_options.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 <chrono>
18#include <map>
19#include <string>
20
21#include "auto_apms_util/exceptions.hpp"
22#include "auto_apms_util/yaml.hpp"
23
25{
26
32{
33 static const std::string PARAM_NAME_CLASS;
34 static const std::string PARAM_NAME_ROS2TOPIC;
35 static const std::string PARAM_NAME_DESCRIPTION;
36 static const std::string PARAM_NAME_PORT_ALIAS;
37 static const std::string PARAM_NAME_PORT_DEFAULT;
38 static const std::string PARAM_NAME_WAIT_TIMEOUT;
39 static const std::string PARAM_NAME_REQUEST_TIMEOUT;
40 static const std::string PARAM_NAME_ALLOW_UNREACHABLE;
41 static const std::string PARAM_NAME_LOGGER_LEVEL;
42 static const std::string PARAM_NAME_HIDDEN_PORTS;
43 static const std::string PARAM_NAME_EXTRA;
44
49
51
52
53 std::string class_name;
55 std::string description = "No description provided.";
78 std::string topic = "(input:topic)";
98 std::map<std::string, std::string> port_alias = {};
109 std::map<std::string, std::string> port_default = {};
111 std::vector<std::string> hidden_ports = {};
114 std::chrono::duration<double> wait_timeout = std::chrono::duration<double>(3);
116 std::chrono::duration<double> request_timeout = std::chrono::duration<double>(2);
119 bool allow_unreachable = false;
121 std::string logger_level = "";
124 YAML::Node extra;
125
130 bool valid() const;
131};
132
133} // namespace auto_apms_behavior_tree::core
134
135// #####################################################################################################################
136// ################################ DEFINITIONS ##############################################
137// #####################################################################################################################
138
140namespace YAML
141{
142template <>
144{
146 inline static Node encode(const Options & rhs)
147 {
148 Node node(NodeType::Map);
149 node[Options::PARAM_NAME_CLASS] = rhs.class_name;
150 node[Options::PARAM_NAME_DESCRIPTION] = rhs.description;
151 node[Options::PARAM_NAME_ROS2TOPIC] = rhs.topic;
152 node[Options::PARAM_NAME_PORT_ALIAS] = rhs.port_alias;
153 node[Options::PARAM_NAME_PORT_DEFAULT] = rhs.port_default;
154 node[Options::PARAM_NAME_HIDDEN_PORTS] = rhs.hidden_ports;
155 node[Options::PARAM_NAME_WAIT_TIMEOUT] = rhs.wait_timeout.count();
156 node[Options::PARAM_NAME_REQUEST_TIMEOUT] = rhs.request_timeout.count();
157 node[Options::PARAM_NAME_ALLOW_UNREACHABLE] = rhs.allow_unreachable;
158 node[Options::PARAM_NAME_LOGGER_LEVEL] = rhs.logger_level;
159 node[Options::PARAM_NAME_EXTRA] = rhs.extra;
160 return node;
161 }
162 inline static bool decode(const Node & node, Options & rhs)
163 {
164 if (!node.IsMap())
165 throw auto_apms_util::exceptions::YAMLFormatError(
166 "YAML::Node for auto_apms_behavior_tree::core::NodeRegistrationOptions must be map but is type " +
167 std::to_string(node.Type()) + " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
168
169 for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) {
170 const std::string key = it->first.as<std::string>();
171 const Node val = it->second;
172
173 if (key == Options::PARAM_NAME_EXTRA) {
174 // Any valid yaml is allowed as extra options
175 rhs.extra = val;
176 continue;
177 }
178
179 if (key == Options::PARAM_NAME_PORT_ALIAS) {
180 if (!val.IsMap()) {
181 throw auto_apms_util::exceptions::YAMLFormatError(
182 "Value for key '" + key + "' must be a map but is type " + std::to_string(val.Type()) +
183 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
184 }
185 rhs.port_alias = val.as<std::map<std::string, std::string>>();
186 continue;
187 }
188
189 if (key == Options::PARAM_NAME_PORT_DEFAULT) {
190 if (!val.IsMap()) {
191 throw auto_apms_util::exceptions::YAMLFormatError(
192 "Value for key '" + key + "' must be a map but is type " + std::to_string(val.Type()) +
193 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
194 }
195 rhs.port_default = val.as<std::map<std::string, std::string>>();
196 continue;
197 }
198
199 if (key == Options::PARAM_NAME_HIDDEN_PORTS) {
200 if (!val.IsSequence()) {
201 throw auto_apms_util::exceptions::YAMLFormatError(
202 "Value for key '" + key + "' must be a sequence but is type " + std::to_string(val.Type()) +
203 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
204 }
205 rhs.hidden_ports = val.as<std::vector<std::string>>();
206 continue;
207 }
208
209 if (key == Options::PARAM_NAME_CLASS) {
210 if (!val.IsScalar()) {
211 throw auto_apms_util::exceptions::YAMLFormatError(
212 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
213 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
214 }
215 rhs.class_name = val.as<std::string>();
216 continue;
217 }
218 if (key == Options::PARAM_NAME_DESCRIPTION) {
219 if (!val.IsScalar()) {
220 throw auto_apms_util::exceptions::YAMLFormatError(
221 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
222 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
223 }
224 rhs.description = val.as<std::string>();
225 continue;
226 }
227 if (key == Options::PARAM_NAME_ROS2TOPIC) {
228 if (!val.IsScalar()) {
229 throw auto_apms_util::exceptions::YAMLFormatError(
230 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
231 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
232 }
233 rhs.topic = val.as<std::string>();
234 continue;
235 }
236 if (key == Options::PARAM_NAME_WAIT_TIMEOUT) {
237 if (!val.IsScalar()) {
238 throw auto_apms_util::exceptions::YAMLFormatError(
239 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
240 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
241 }
242 rhs.wait_timeout = std::chrono::duration<double>(val.as<double>());
243 continue;
244 }
245 if (key == Options::PARAM_NAME_REQUEST_TIMEOUT) {
246 if (!val.IsScalar()) {
247 throw auto_apms_util::exceptions::YAMLFormatError(
248 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
249 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
250 }
251 rhs.request_timeout = std::chrono::duration<double>(val.as<double>());
252 continue;
253 }
254 if (key == Options::PARAM_NAME_ALLOW_UNREACHABLE) {
255 if (!val.IsScalar()) {
256 throw auto_apms_util::exceptions::YAMLFormatError(
257 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
258 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
259 }
260 rhs.allow_unreachable = val.as<bool>();
261 continue;
262 }
263 if (key == Options::PARAM_NAME_LOGGER_LEVEL) {
264 if (!val.IsScalar()) {
265 throw auto_apms_util::exceptions::YAMLFormatError(
266 "Value for key '" + key + "' must be scalar but is type " + std::to_string(val.Type()) +
267 " (0: Undefined - 1: Null - 2: Scalar - 3: Sequence - 4: Map).");
268 }
269 rhs.logger_level = val.as<std::string>();
270 continue;
271 }
272
273 // Unkown parameter
274 throw auto_apms_util::exceptions::YAMLFormatError("Unkown parameter name '" + key + "'.");
275 }
276 return true;
277 }
278};
279
280} // namespace YAML
#define AUTO_APMS_UTIL_DEFINE_YAML_CONVERSION_METHODS(ClassType)
Macro for defining YAML encode/decode methods for a class.
Definition yaml.hpp:32
Core API for AutoAPMS's behavior tree implementation.
Definition behavior.hpp:32
Powerful tooling for incorporating behavior trees for task development.
Definition behavior.hpp:32
Parameters for loading and registering a behavior tree node class from a shared library using e....
std::string description
Short description of the behavior tree node's purpose and use-case.
bool valid() const
Verify that the options are valid (e.g. all required values are set).
NodeRegistrationOptions()=default
Create the default node registration options.
std::string topic
Name of the ROS 2 communication interface to connect with.
std::chrono::duration< double > request_timeout
Period [s] (measured from sending a goal request) after the node aborts waiting for a server response...
std::map< std::string, std::string > port_default
Provides the possibility to define custom default values for the ports implemented by class_name.
std::vector< std::string > hidden_ports
List of port names to hide in the node model for visualization tools like Groot2.
std::map< std::string, std::string > port_alias
Provides the possibility to rename ports implemented by class_name.
std::string class_name
Fully qualified name of the behavior tree node plugin class.
std::string logger_level
Minimum ROS 2 logging severity level for this particular node. Empty means to inherit the parent logg...