BehaviorTree
Core Library to create and execute Behavior Trees
Loading...
Searching...
No Matches
set_blackboard_node.h
1/* Copyright (C) 2018-2025 Davide Faconti, Eurecat - All Rights Reserved
2*
3* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5* 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:
6* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7*
8* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9* 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,
10* 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.
11*/
12
13#ifndef ACTION_SETBLACKBOARD_NODE_H
14#define ACTION_SETBLACKBOARD_NODE_H
15
16#include "behaviortree_cpp/action_node.h"
17
18#include <mutex>
19
20namespace BT
21{
22/**
23 * @brief The SetBlackboard is action used to store a string
24 * into an entry of the Blackboard specified in "output_key".
25 *
26 * Example usage:
27 *
28 * <SetBlackboard value="42" output_key="the_answer" />
29 *
30 * Will store the string "42" in the entry with key "the_answer".
31 *
32 * Alternatively, you can use it to copy one port inside another port:
33 *
34 * <SetBlackboard value="{src_port}" output_key="dst_port" />
35 *
36 * This will copy the type and content of {src_port} into {dst_port}
37 */
39{
40public:
41 SetBlackboardNode(const std::string& name, const NodeConfig& config)
42 : SyncActionNode(name, config)
43 {
44 setRegistrationID("SetBlackboard");
45 }
46
47 static PortsList providedPorts()
48 {
49 return { InputPort("value", "Value to be written into the output_key"),
50 BidirectionalPort("output_key", "Name of the blackboard entry where the "
51 "value should be written") };
52 }
53
54private:
55 virtual BT::NodeStatus tick() override
56 {
57 std::string output_key;
58 if(!getInput("output_key", output_key))
59 {
60 throw RuntimeError("missing port [output_key]");
61 }
62
63 const std::string value_str = config().input_ports.at("value");
64
65 StringView stripped_key;
66 BT::Any out_value;
67
68 std::shared_ptr<Blackboard::Entry> dst_entry =
69 config().blackboard->getEntry(output_key);
70
71 if(isBlackboardPointer(value_str, &stripped_key))
72 {
73 const auto input_key = std::string(stripped_key);
74 std::shared_ptr<Blackboard::Entry> src_entry =
75 config().blackboard->getEntry(input_key);
76
77 if(!src_entry)
78 {
79 throw RuntimeError("Can't find the port referred by [value]");
80 }
81 // Entry::value and Entry::info are shared with any thread that writes
82 // the same entry (Blackboard::set holds entry_mutex while reassigning
83 // them), so they must be copied under the same mutex.
84 std::unique_lock src_lock(src_entry->entry_mutex);
85 out_value = src_entry->value;
86 const TypeInfo src_info = src_entry->info;
87 src_lock.unlock();
88 if(!dst_entry)
89 {
90 config().blackboard->createEntry(output_key, src_info);
91 dst_entry = config().blackboard->getEntry(output_key);
92 }
93 }
94 else
95 {
96 out_value = BT::Any(value_str);
97 }
98
99 if(out_value.empty())
100 return NodeStatus::FAILURE;
101
102 // avoid type issues when port is remapped: current implementation of the set might be a little bit problematic for initialized on the fly values
103 // this still does not attack math issues
104 if(dst_entry && out_value.isString())
105 {
106 // same as above: Entry::info may be reassigned under entry_mutex by a
107 // concurrent Blackboard::set, so take a copy under the same mutex.
108 std::unique_lock dst_lock(dst_entry->entry_mutex);
109 const TypeInfo dst_info = dst_entry->info;
110 dst_lock.unlock();
111 if(dst_info.type() != typeid(std::string))
112 {
113 try
114 {
115 out_value = dst_info.parseString(out_value.cast<std::string>());
116 }
117 catch(const std::exception& e)
118 {
119 throw LogicError("Can't convert string [", out_value.cast<std::string>(),
120 "] to type [", BT::demangle(dst_info.type()), "]: ", e.what());
121 }
122 }
123 }
124
125 config().blackboard->set(output_key, out_value);
126
127 return NodeStatus::SUCCESS;
128 }
129};
130} // namespace BT
131
132#endif
Definition: safe_any.hpp:57
The Blackboard is the mechanism used by BehaviorTrees to exchange typed data.
Definition: blackboard.h:39
Definition: exceptions.h:48
The SetBlackboard is action used to store a string into an entry of the Blackboard specified in "outp...
Definition: set_blackboard_node.h:39
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn't require a...
Definition: action_node.h:57
Definition: basic_types.h:377
Definition: action_node.h:24
NodeStatus
Definition: basic_types.h:34
Definition: blackboard.h:55
Definition: tree_node.h:105