BehaviorTree
Core Library to create and execute Behavior Trees
Loading...
Searching...
No Matches
tree_node.h
1/* Copyright (C) 2015-2018 Michele Colledanchise - All Rights Reserved
2* Copyright (C) 2018-2025 Davide Faconti - All Rights Reserved
3*
4* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
5* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8*
9* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
11* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12*/
13
14#pragma once
15
16#include "behaviortree_cpp/basic_types.h"
17#include "behaviortree_cpp/blackboard.h"
18#include "behaviortree_cpp/scripting/script_parser.hpp"
19#include "behaviortree_cpp/utils/signal.h"
20#include "behaviortree_cpp/utils/strcat.hpp"
21#include "behaviortree_cpp/utils/wakeup_signal.hpp"
22
23#include <charconv>
24#include <exception>
25#include <map>
26#include <utility>
27
28#ifdef _MSC_VER
29#pragma warning(disable : 4127)
30#endif
31
32namespace BT
33{
34
35/// This information is used mostly by the XMLParser.
37{
38 NodeType type;
39 std::string registration_ID;
40 PortsList ports;
41 KeyValueVector metadata;
42};
43
46
47/**
48 * @brief Pre-conditions that can be attached to any node via XML attributes.
49 *
50 * Pre-conditions are evaluated in the order defined by this enum (FAILURE_IF first,
51 * then SUCCESS_IF, then SKIP_IF, then WHILE_TRUE).
52 *
53 * **Important**: FAILURE_IF, SUCCESS_IF, and SKIP_IF are evaluated **only once**
54 * when the node transitions from IDLE (or SKIPPED) to another state.
55 * They are NOT re-evaluated while the node is RUNNING.
56 *
57 * - `_failureIf="<script>"`: If true when node is IDLE, return FAILURE immediately (node's tick() is not called).
58 * - `_successIf="<script>"`: If true when node is IDLE, return SUCCESS immediately (node's tick() is not called).
59 * - `_skipIf="<script>"`: If true when node is IDLE, return SKIPPED immediately (node's tick() is not called).
60 * - `_while="<script>"`: Checked both on IDLE and RUNNING states.
61 *
62 * If false when IDLE, return SKIPPED. If false when RUNNING, halt the node
63 * and return SKIPPED. This is the only pre-condition that can interrupt
64 * a running node.
65 *
66 * If you need a condition to be re-evaluated on every tick, use the
67 * `<Precondition>` decorator node with `else="RUNNING"` instead of these attributes.
68 */
69enum class PreCond
70{
71 FAILURE_IF = 0,
72 SUCCESS_IF,
73 SKIP_IF,
74 WHILE_TRUE,
75 COUNT_
76};
77
78static const std::array<std::string, 4> PreCondNames = { //
79 "_failureIf", "_successIf", "_skipIf", "_while"
80};
81
82enum class PostCond
83{
84 // order of the enums also tell us the execution order
85 ON_HALTED = 0,
86 ON_FAILURE,
87 ON_SUCCESS,
88 ALWAYS,
89 COUNT_
90};
91
92static const std::array<std::string, 4> PostCondNames = { //
93 "_onHalted", "_onFailure", "_onSuccess", "_post"
94};
95
96template <>
97[[nodiscard]] std::string toStr<BT::PostCond>(const BT::PostCond& cond);
98
99template <>
100[[nodiscard]] std::string toStr<BT::PreCond>(const BT::PreCond& cond);
101
103
104struct NodeConfig
105{
106 NodeConfig()
107 {}
108
109 // Pointer to the blackboard used by this node
110 Blackboard::Ptr blackboard;
111 // List of enums available for scripting
112 std::shared_ptr<ScriptingEnumsRegistry> enums;
113 // input ports
114 PortsRemapping input_ports;
115 // output ports
116 PortsRemapping output_ports;
117
118 // Any other attributes found in the xml that are not parsed as ports
119 // or built-in identifier (e.g. anything with a leading '_')
120 NonPortAttributes other_attributes;
121
122 const TreeNodeManifest* manifest = nullptr;
123
124 // Numeric unique identifier
125 uint16_t uid = 0;
126 // Unique human-readable name, that encapsulate the subtree
127 // hierarchy, for instance, given 2 nested trees, it should be:
128 //
129 // main_tree/nested_tree/my_action
130 std::string path;
131
132 std::map<PreCond, std::string> pre_conditions;
133 std::map<PostCond, std::string> post_conditions;
134};
135
136// back compatibility
137using NodeConfiguration = NodeConfig;
138
139template <typename T>
140inline constexpr bool hasNodeNameCtor()
141{
142 return std::is_constructible<T, const std::string&>::value;
143}
144
145template <typename T, typename... ExtraArgs>
146inline constexpr bool hasNodeFullCtor()
147{
148 return std::is_constructible<T, const std::string&, const NodeConfig&,
149 ExtraArgs...>::value;
150}
151
152/// Abstract base class for Behavior Tree Nodes
153class TreeNode
154{
155public:
156 typedef std::shared_ptr<TreeNode> Ptr;
157
158 /**
159 * @brief TreeNode main constructor.
160 *
161 * @param name name of the instance, not the type.
162 * @param config information about input/output ports. See NodeConfig
163 *
164 * Note: If your custom node has ports, the derived class must implement:
165 *
166 * static PortsList providedPorts();
167 */
168 TreeNode(std::string name, NodeConfig config);
169
170 TreeNode(const TreeNode& other) = delete;
171 TreeNode& operator=(const TreeNode& other) = delete;
172
173 TreeNode(TreeNode&& other) noexcept;
174 TreeNode& operator=(TreeNode&& other) noexcept;
175
176 virtual ~TreeNode();
177
178 /// The method that should be used to invoke tick() and setStatus();
179 virtual BT::NodeStatus executeTick();
180
181 void haltNode();
182
183 [[nodiscard]] bool isHalted() const;
184
185 [[nodiscard]] NodeStatus status() const;
186
187 /// Name of the instance, not the type
188 [[nodiscard]] const std::string& name() const;
189
190 /// Blocking function that will sleep until the setStatus() is called with
191 /// either RUNNING, FAILURE or SUCCESS.
193
194 virtual NodeType type() const = 0;
195
196 using StatusChangeSignal = Signal<TimePoint, const TreeNode&, NodeStatus, NodeStatus>;
199
200 using PreTickCallback = std::function<NodeStatus(TreeNode&)>;
201 using PostTickCallback = std::function<NodeStatus(TreeNode&, NodeStatus)>;
202 using TickMonitorCallback =
203 std::function<void(TreeNode&, NodeStatus, std::chrono::microseconds)>;
204
205 /**
206 * @brief subscribeToStatusChange is used to attach a callback to a status change.
207 * When StatusChangeSubscriber goes out of scope (it is a shared_ptr) the callback
208 * is unsubscribed automatically.
209 *
210 * @param callback The callback to be execute when status change.
211 *
212 * @return the subscriber handle.
213 */
216
217 /** This method attaches to the TreeNode a callback with signature:
218 *
219 * NodeStatus callback(TreeNode& node)
220 *
221 * This callback is executed BEFORE the tick() and, if it returns SUCCESS or FAILURE,
222 * the actual tick() will NOT be executed and this result will be returned instead.
223 *
224 * This is useful to inject a "dummy" implementation of the TreeNode at run-time
225 */
226 void setPreTickFunction(PreTickCallback callback);
227
228 /**
229 * This method attaches to the TreeNode a callback with signature:
230 *
231 * NodeStatus myCallback(TreeNode& node, NodeStatus status)
232 *
233 * This callback is executed AFTER the tick() and, if it returns SUCCESS or FAILURE,
234 * the value returned by the actual tick() is overridden with this one.
235 */
236 void setPostTickFunction(PostTickCallback callback);
237
238 /**
239 * This method attaches to the TreeNode a callback with signature:
240 *
241 * void myCallback(TreeNode& node, NodeStatus status, std::chrono::microseconds duration)
242 *
243 * This callback is executed AFTER the tick() and will inform the user about its status and
244 * the execution time. Works only if the tick was not substituted by a pre-condition.
245 */
246 void setTickMonitorCallback(TickMonitorCallback callback);
247
248 /// The unique identifier of this instance of treeNode.
249 /// It is assigneld by the factory
250 [[nodiscard]] uint16_t UID() const;
251
252 /// Human readable identifier, that includes the hierarchy of Subtrees
253 /// See tutorial 10 as an example.
254 [[nodiscard]] const std::string& fullPath() const;
255
256 /// registrationName is the ID used by BehaviorTreeFactory to create an instance.
257 [[nodiscard]] const std::string& registrationName() const;
258
259 /// Configuration passed at construction time. Can never change after the
260 /// creation of the TreeNode instance.
261 [[nodiscard]] const NodeConfig& config() const;
262
263 /** Read an input port, which, in practice, is an entry in the blackboard.
264 * If the blackboard contains a std::string and T is not a string,
265 * convertFromString<T>() is used automatically to parse the text.
266 *
267 * @param key the name of the port.
268 * @param destination reference to the object where the value should be stored
269 * @return false if an error occurs.
270 */
271 template <typename T>
272 Result getInput(const std::string& key, T& destination) const;
273
274 /**
275 * @brief getInputStamped is similar to getInput(dey, destination),
276 * but it returns also the Timestamp object, that can be used to check if
277 * a value was updated and when.
278 *
279 * @param key the name of the port.
280 * @param destination reference to the object where the value should be stored
281 */
282 template <typename T>
283 [[nodiscard]] Expected<Timestamp> getInputStamped(const std::string& key,
284 T& destination) const;
285
286 /** Same as bool getInput(const std::string& key, T& destination)
287 * but using optional.
288 *
289 * @param key the name of the port.
290 */
291 template <typename T>
292 [[nodiscard]] Expected<T> getInput(const std::string& key) const
293 {
294 T out{};
295 auto res = getInput(key, out);
296 return (res) ? Expected<T>(out) : nonstd::make_unexpected(res.error());
297 }
298
299 /** Same as bool getInputStamped(const std::string& key, T& destination)
300 * but return StampedValue<T>
301 *
302 * @param key the name of the port.
303 */
304 template <typename T>
305 [[nodiscard]] Expected<StampedValue<T>> getInputStamped(const std::string& key) const
306 {
307 StampedValue<T> out;
308 if(auto res = getInputStamped(key, out.value))
309 {
310 out.stamp = *res;
311 return out;
312 }
313 else
314 {
315 return nonstd::make_unexpected(res.error());
316 }
317 }
318
319 /**
320 * @brief setOutput modifies the content of an Output port
321 * @param key the name of the port.
322 * @param value new value
323 * @return valid Result, if successful.
324 */
325 template <typename T>
326 Result setOutput(const std::string& key, const T& value);
327
328 /**
329 * @brief getLockedPortContent should be used when:
330 *
331 * - your port contains an object with reference semantic (usually a smart pointer)
332 * - you want to modify the object we are pointing to.
333 * - you are concerned about thread-safety.
334 *
335 * For example, if your port has type std::shared_ptr<Foo>,
336 * the code below is NOT thread safe:
337 *
338 * auto foo_ptr = getInput<std::shared_ptr<Foo>>("port_name");
339 * // modifying the content of foo_ptr is NOT thread-safe
340 *
341 * What you must do, instead, to guaranty thread-safety, is:
342 *
343 * if(auto any_ref = getLockedPortContent("port_name")) {
344 * Any* any = any_ref.get();
345 * auto foo_ptr = any->cast<std::shared_ptr<Foo>>();
346 * // modifying the content of foo_ptr inside this scope IS thread-safe
347 * }
348 *
349 * It is important to destroy the object AnyPtrLocked, to release the lock.
350 *
351 * NOTE: this method doesn't work, if the port contains a static string, instead
352 * of a blackboard pointer.
353 *
354 * @param key the identifier of the port.
355 * @return empty AnyPtrLocked if the blackboard entry doesn't exist or the content
356 * of the port was a static string.
357 */
358 [[nodiscard]] AnyPtrLocked getLockedPortContent(const std::string& key);
359
360 // function provided mostly for debugging purpose to see the raw value
361 // in the port (no remapping and no conversion to a type)
362 [[nodiscard]] StringView getRawPortValue(const std::string& key) const;
363
364 /// Check a string and return true if it matches the pattern: {...}
365 [[nodiscard]] static bool isBlackboardPointer(StringView str,
366 StringView* stripped_pointer = nullptr);
367
368 [[nodiscard]] static StringView stripBlackboardPointer(StringView str);
369
370 [[nodiscard]] static Expected<StringView> getRemappedKey(StringView port_name,
371 StringView remapped_port);
372
373 /// Notify that the tree should be ticked again()
374 void emitWakeUpSignal();
375
376 [[nodiscard]] bool requiresWakeUp() const;
377
378 /** Used to inject config into a node, even if it doesn't have the proper
379 * constructor
380 */
381 template <class DerivedT, typename... ExtraArgs>
383 const NodeConfig& config,
384 ExtraArgs... args)
385 {
386 static_assert(hasNodeFullCtor<DerivedT, ExtraArgs...>() ||
387 hasNodeNameCtor<DerivedT>());
388
389 if constexpr(hasNodeFullCtor<DerivedT, ExtraArgs...>())
390 {
391 return std::make_unique<DerivedT>(name, config, args...);
392 }
393 else if constexpr(hasNodeNameCtor<DerivedT>())
394 {
395 auto node_ptr = std::make_unique<DerivedT>(name, args...);
396 node_ptr->config() = config;
397 return node_ptr;
398 }
399 }
400
401protected:
402 friend class BehaviorTreeFactory;
403 friend class DecoratorNode;
404 friend class ControlNode;
405 friend class Tree;
406
407 [[nodiscard]] NodeConfig& config();
408
409 /// Method to be implemented by the user
410 virtual BT::NodeStatus tick() = 0;
411
412 /// Set the status to IDLE
413 void resetStatus();
414
415 // Only BehaviorTreeFactory should call this
416 void setRegistrationID(StringView ID);
417
418 void setWakeUpInstance(std::shared_ptr<WakeUpSignal> instance);
419
420 void modifyPortsRemapping(const PortsRemapping& new_remapping);
421
422 /**
423 * @brief setStatus changes the status of the node.
424 * it will throw if you try to change the status to IDLE, because
425 * your parent node should do that, not the user!
426 */
427 void setStatus(NodeStatus new_status);
428
431
432 PreScripts& preConditionsScripts();
433 PostScripts& postConditionsScripts();
434
435 template <typename T>
436 T parseString(const std::string& str) const;
437
438private:
439 struct PImpl;
440 std::unique_ptr<PImpl> _p;
441
442 Expected<NodeStatus> checkPreConditions();
443 void checkPostConditions(NodeStatus status);
444
445 /// The method used to interrupt the execution of a RUNNING node.
446 /// Only Async nodes that may return RUNNING should implement it.
447 virtual void halt() = 0;
448};
449
450//-------------------------------------------------------
451
452template <typename T>
453T TreeNode::parseString(const std::string& str) const
454{
455 if constexpr(std::is_enum_v<T> && !std::is_same_v<T, NodeStatus>)
456 {
457 // Check the ScriptingEnumsRegistry first, if available.
458 if(config().enums)
459 {
460 auto it = config().enums->find(str);
461 if(it != config().enums->end())
462 {
463 return static_cast<T>(it->second);
464 }
465 }
466 // Try numeric conversion (e.g. "2" for an enum value).
467 int tmp = 0;
468 auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), tmp);
469 if(ec == std::errc() && ptr == str.data() + str.size())
470 {
471 return static_cast<T>(tmp);
472 }
473 // Fall back to convertFromString<T>, which uses a user-provided
474 // specialization if one exists. Issue #948.
475 return convertFromString<T>(str);
476 }
477 return convertFromString<T>(str);
478}
479
480template <typename T>
482 T& destination) const
483{
484 std::string port_value_str;
485
486 auto input_port_it = config().input_ports.find(key);
487 if(input_port_it != config().input_ports.end())
488 {
489 port_value_str = input_port_it->second;
490 }
491 else if(!config().manifest)
492 {
493 return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(),
494 "' failed because the manifest is "
495 "nullptr (WTF?) and the key: [",
496 key, "] is missing"));
497 }
498 else
499 {
500 // maybe it is declared with a default value in the manifest
501 auto port_manifest_it = config().manifest->ports.find(key);
502 if(port_manifest_it == config().manifest->ports.end())
503 {
504 return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(),
505 "' failed because the manifest doesn't "
506 "contain the key: [",
507 key, "]"));
508 }
509 const auto& port_info = port_manifest_it->second;
510 // there is a default value
511 if(port_info.defaultValue().empty())
512 {
513 return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(),
514 "' failed because nor the manifest or the "
515 "XML contain the key: [",
516 key, "]"));
517 }
518 if(port_info.defaultValue().isString())
519 {
520 port_value_str = port_info.defaultValue().cast<std::string>();
521 }
522 else
523 {
524 destination = port_info.defaultValue().cast<T>();
525 return Timestamp{};
526 }
527 }
528
529 // Helper lambda to parse string using the stored converter if available,
530 // otherwise fall back to convertFromString<T>. This fixes the plugin issue
531 // where convertFromString<T> specializations are not visible across shared
532 // library boundaries (issue #953).
533 auto parseStringWithConverter = [this, &key](const std::string& str) -> T {
534 if(config().manifest)
535 {
536 auto port_it = config().manifest->ports.find(key);
537 if(port_it != config().manifest->ports.end())
538 {
539 const auto& converter = port_it->second.converter();
540 if(converter)
541 {
542 return converter(str).template cast<T>();
543 }
544 }
545 }
546 // Fall back to parseString which calls convertFromString
547 return parseString<T>(str);
548 };
549
550 auto blackboard_ptr = getRemappedKey(key, port_value_str);
551 try
552 {
553 // pure string, not a blackboard key
554 if(!blackboard_ptr)
555 {
556 try
557 {
558 destination = parseStringWithConverter(port_value_str);
559 }
560 catch(std::exception& ex)
561 {
562 return nonstd::make_unexpected(StrCat("getInput(): ", ex.what()));
563 }
564 return Timestamp{};
565 }
566 const auto& blackboard_key = blackboard_ptr.value();
567
568 if(!config().blackboard)
569 {
570 return nonstd::make_unexpected("getInput(): trying to access "
571 "an invalid Blackboard");
572 }
573
574 if(auto entry = config().blackboard->getEntry(std::string(blackboard_key)))
575 {
576 std::unique_lock lk(entry->entry_mutex);
577 auto& any_value = entry->value;
578
579 // support getInput<Any>()
580 if constexpr(std::is_same_v<T, Any>)
581 {
582 destination = any_value;
583 return Timestamp{ entry->sequence_id, entry->stamp };
584 }
585
586 if(!entry->value.empty())
587 {
588 if(!std::is_same_v<T, std::string> && any_value.isString())
589 {
590 destination = parseStringWithConverter(any_value.cast<std::string>());
591 }
592 else
593 {
594 auto result =
595 config().blackboard->tryCastWithPolymorphicFallback<T>(&any_value);
596 if(!result)
597 {
598 throw std::runtime_error(result.error());
599 }
600 destination = result.value();
601 }
602 return Timestamp{ entry->sequence_id, entry->stamp };
603 }
604 }
605
606 return nonstd::make_unexpected(StrCat("getInput() failed because it was unable to "
607 "find the key [",
608 key, "] remapped to [", blackboard_key, "]"));
609 }
610 catch(std::exception& err)
611 {
612 return nonstd::make_unexpected(err.what());
613 }
614}
615
616template <typename T>
617inline Result TreeNode::getInput(const std::string& key, T& destination) const
618{
619 auto res = getInputStamped(key, destination);
620 if(!res)
621 {
622 return nonstd::make_unexpected(res.error());
623 }
624 return {};
625}
626
627template <typename T>
628inline Result TreeNode::setOutput(const std::string& key, const T& value)
629{
630 if(!config().blackboard)
631 {
632 return nonstd::make_unexpected("setOutput() failed: trying to access a "
633 "Blackboard(BB) entry, but BB is invalid");
634 }
635
636 auto remap_it = config().output_ports.find(key);
637 if(remap_it == config().output_ports.end())
638 {
639 return nonstd::make_unexpected(StrCat("setOutput() failed: "
640 "NodeConfig::output_ports "
641 "does not contain the key: [",
642 key, "]"));
643 }
644 StringView remapped_key = remap_it->second;
645 if(remapped_key == "{=}" || remapped_key == "=")
646 {
647 config().blackboard->set(static_cast<std::string>(key), value);
648 return {};
649 }
650
651 if(!isBlackboardPointer(remapped_key))
652 {
653 return nonstd::make_unexpected("setOutput requires a blackboard pointer. Use {}");
654 }
655
656 if constexpr(std::is_same_v<BT::Any, T>)
657 {
658 auto port_type = config().manifest->ports.at(key).type();
659 if(port_type != typeid(BT::Any) && port_type != typeid(BT::AnyTypeAllowed))
660 {
661 throw LogicError("setOutput<Any> is not allowed, unless the port "
662 "was declared using OutputPort<Any>");
663 }
664 }
665
666 remapped_key = stripBlackboardPointer(remapped_key);
667 config().blackboard->set(static_cast<std::string>(remapped_key), value);
668
669 return {};
670}
671
672// Utility function to fill the list of ports using T::providedPorts();
673template <typename T>
674inline void assignDefaultRemapping(NodeConfig& config)
675{
676 for(const auto& it : getProvidedPorts<T>())
677 {
678 const auto& port_name = it.first;
679 const auto direction = it.second.direction();
680 if(direction != PortDirection::OUTPUT)
681 {
682 // PortDirection::{INPUT,INOUT}
683 config.input_ports[port_name] = "{=}";
684 }
685 if(direction != PortDirection::INPUT)
686 {
687 // PortDirection::{OUTPUT,INOUT}
688 config.output_ports[port_name] = "{=}";
689 }
690 }
691}
692
693} // namespace BT
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:227
The Blackboard is the mechanism used by BehaviorTrees to exchange typed data.
Definition: blackboard.h:35
The ControlNode is the base class for nodes that can have multiple children.
Definition: control_node.h:32
The DecoratorNode is the base class for nodes that have exactly one child.
Definition: decorator_node.h:19
Definition: signal.h:16
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:96
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:154
void emitWakeUpSignal()
Notify that the tree should be ticked again()
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
virtual BT::NodeStatus tick()=0
Method to be implemented by the user.
const std::string & registrationName() const
registrationName is the ID used by BehaviorTreeFactory to create an instance.
static std::unique_ptr< TreeNode > Instantiate(const std::string &name, const NodeConfig &config, ExtraArgs... args)
Definition: tree_node.h:382
Expected< Timestamp > getInputStamped(const std::string &key, T &destination) const
getInputStamped is similar to getInput(dey, destination), but it returns also the Timestamp object,...
Definition: tree_node.h:481
Result setOutput(const std::string &key, const T &value)
setOutput modifies the content of an Output port
Definition: tree_node.h:628
const NodeConfig & config() const
void resetStatus()
Set the status to IDLE.
uint16_t UID() const
const std::string & fullPath() const
Expected< T > getInput(const std::string &key) const
Definition: tree_node.h:292
static bool isBlackboardPointer(StringView str, StringView *stripped_pointer=nullptr)
Check a string and return true if it matches the pattern: {...}.
Expected< StampedValue< T > > getInputStamped(const std::string &key) const
Definition: tree_node.h:305
void setStatus(NodeStatus new_status)
setStatus changes the status of the node. it will throw if you try to change the status to IDLE,...
AnyPtrLocked getLockedPortContent(const std::string &key)
getLockedPortContent should be used when:
const std::string & name() const
Name of the instance, not the type.
Result getInput(const std::string &key, T &destination) const
Definition: tree_node.h:617
void setPreTickFunction(PreTickCallback callback)
TreeNode(std::string name, NodeConfig config)
TreeNode main constructor.
BT::NodeStatus waitValidStatus()
StatusChangeSubscriber subscribeToStatusChange(StatusChangeCallback callback)
subscribeToStatusChange is used to attach a callback to a status change. When StatusChangeSubscriber ...
void setTickMonitorCallback(TickMonitorCallback callback)
void setPostTickFunction(PostTickCallback callback)
Definition: wakeup_signal.hpp:13
Definition: action_node.h:24
NodeStatus
Definition: basic_types.h:34
NodeType
Enumerates the possible types of nodes.
Definition: basic_types.h:21
PreCond
Pre-conditions that can be attached to any node via XML attributes.
Definition: tree_node.h:70
Definition: tree_node.h:105
Definition: blackboard.h:25
This information is used mostly by the XMLParser.
Definition: tree_node.h:37