3#include "behaviortree_cpp/basic_types.h"
4#include "behaviortree_cpp/contrib/json.hpp"
5#include "behaviortree_cpp/exceptions.h"
6#include "behaviortree_cpp/utils/locked_reference.hpp"
7#include "behaviortree_cpp/utils/polymorphic_cast_registry.hpp"
8#include "behaviortree_cpp/utils/safe_any.hpp"
12#include <shared_mutex>
14#include <unordered_map>
31
32
33
41 Blackboard(
Blackboard::Ptr parent) : parent_bb_(parent)
54 StringConverter string_converter;
55 mutable std::mutex entry_mutex;
57 uint64_t sequence_id = 0;
61 Entry(
const TypeInfo& _info) : info(_info)
65 Entry(
const Entry&) =
delete;
67 Entry(
Entry&&) =
delete;
72
73
76 return std::shared_ptr<Blackboard>(
new Blackboard(parent));
79 virtual ~Blackboard() =
default;
81 void enableAutoRemapping(
bool remapping);
83 [[
nodiscard]]
const std::shared_ptr<
Entry> getEntry(
const std::string& key)
const;
87 [[
nodiscard]] AnyPtrLocked getAnyLocked(
const std::string& key);
89 [[
nodiscard]] AnyPtrLocked getAnyLocked(
const std::string& key)
const;
92 getAny(
const std::string& key)
const;
94 [[
deprecated(
"Use getAnyLocked instead")]]
Any* getAny(
const std::string& key);
97
98
100 [[nodiscard]]
bool get(
const std::string& key, T& value)
const;
102 template <
typename T>
103 [[nodiscard]] Expected<Timestamp> getStamped(
const std::string& key, T& value)
const;
106
107
108 template <
typename T>
109 [[nodiscard]] T
get(
const std::string& key)
const;
111 template <
typename T>
112 [[nodiscard]] Expected<StampedValue<T>> getStamped(
const std::string& key)
const;
115 template <
typename T>
116 void set(
const std::string& key,
const T& value);
118 void unset(
const std::string& key);
122 void addSubtreeRemapping(StringView internal, StringView external);
124 void debugMessage()
const;
126 [[
nodiscard]] std::vector<StringView> getKeys()
const;
128 [[
deprecated(
"This command is unsafe. Consider using Backup/Restore instead")]]
void
131 void createEntry(
const std::string& key,
const TypeInfo& info);
134
135
136
137
138
139
140
141
152
153
154
155
156
159 polymorphic_registry_ = std::move(registry);
163
164
167 return polymorphic_registry_.get();
171
172
173
174
175
176 template <
typename T>
180 mutable std::shared_mutex storage_mutex_;
181 std::unordered_map<std::string, std::shared_ptr<Entry>> storage_;
183 std::unordered_map<std::string, std::string> internal_to_external_;
185 std::shared_ptr<
Entry> createEntryImpl(
const std::string& key,
const TypeInfo& info);
187 bool autoremapping_ =
false;
194
195
196
197
201
202
203
204
213 auto result = any->tryCast<T>();
216 return result.value();
222 if(polymorphic_registry_)
224 auto poly_result = any->tryCastWithRegistry<T>(*polymorphic_registry_);
227 return poly_result.value();
232 return nonstd::make_unexpected(result.error());
238 if(
auto any_ref = getAnyLocked(key))
240 const auto& any = any_ref.get();
243 throw RuntimeError(
"Blackboard::get() error. Entry [", key,
244 "] hasn't been initialized, yet");
246 auto result = tryCastWithPolymorphicFallback<T>(any);
249 throw std::runtime_error(result.error());
251 return result.value();
253 throw RuntimeError(
"Blackboard::get() error. Missing key [", key,
"]");
256inline void Blackboard::unset(
const std::string& key)
258 std::unique_lock storage_lock(storage_mutex_);
261 auto it = storage_.find(key);
262 if(it == storage_.end())
272inline void Blackboard::
set(
const std::string& key,
const T& value)
274 if(StartWith(key,
'@'))
276 rootBlackboard()->set(key.substr(1, key.size() - 1), value);
279 std::shared_lock storage_lock(storage_mutex_);
282 auto it = storage_.find(key);
283 if(it == storage_.end())
286 Any new_value(value);
287 storage_lock.unlock();
290 if constexpr(std::is_same_v<std::string, T>)
292 entry = createEntryImpl(key, PortInfo(PortDirection::INOUT));
296 PortInfo new_port(PortDirection::INOUT, new_value.type(),
297 GetAnyFromStringFunctor<T>());
298 entry = createEntryImpl(key, new_port);
303 std::scoped_lock entry_lock(entry->entry_mutex);
304 entry->value = new_value;
305 entry->sequence_id++;
306 entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
314 auto entry_ptr = it->second;
315 storage_lock.unlock();
316 Entry& entry = *entry_ptr;
318 std::scoped_lock scoped_lock(entry.entry_mutex);
320 Any& previous_any = entry.value;
321 Any new_value(value);
324 if(!entry.info.isStronglyTyped())
329 entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
330 previous_any = std::move(new_value);
334 std::type_index previous_type = entry.info.type();
337 if(previous_type != std::type_index(
typeid(T)) && previous_type != new_value.type())
339 bool mismatching =
true;
340 if(std::is_constructible<StringView, T>::value)
342 Any any_from_string = entry.info.parseString(value);
343 if(any_from_string.empty() ==
false)
346 new_value = std::move(any_from_string);
352 if constexpr(std::is_arithmetic_v<T>)
354 if(mismatching && isCastingSafe(previous_type, value))
364 auto msg = StrCat(
"Blackboard::set(", key,
366 "the type of a port shall not change. "
367 "Previously declared type [",
368 BT::demangle(previous_type),
"], current type [",
369 BT::demangle(
typeid(T)),
"]");
370 throw LogicError(msg);
374 if constexpr(std::is_same_v<Any, T>)
376 previous_any = new_value;
381 new_value.copyInto(previous_any);
384 entry.stamp = std::chrono::steady_clock::now().time_since_epoch();
389inline bool Blackboard::
get(
const std::string& key, T& value)
const
391 if(
auto any_ref = getAnyLocked(key))
393 const auto& any = any_ref.get();
398 auto result = tryCastWithPolymorphicFallback<T>(any);
401 throw std::runtime_error(result.error());
403 value = result.value();
410inline Expected<Timestamp>
Blackboard::getStamped(
const std::string& key, T& value)
const
412 if(
auto entry = getEntry(key))
414 std::unique_lock lk(entry->entry_mutex);
415 if(entry->value.empty())
417 return nonstd::make_unexpected(StrCat(
"Blackboard::getStamped() error. Entry [",
418 key,
"] hasn't been initialized, yet"));
420 auto result = tryCastWithPolymorphicFallback<T>(&entry->value);
423 value = result.value();
424 return Timestamp{ entry->sequence_id, entry->stamp };
426 return nonstd::make_unexpected(result.error());
428 return nonstd::make_unexpected(
429 StrCat(
"Blackboard::getStamped() error. Missing key [", key,
"]"));
433inline Expected<StampedValue<T>>
Blackboard::getStamped(
const std::string& key)
const
436 if(
auto res = getStamped<T>(key, out.value))
443 return nonstd::make_unexpected(res.error());
Definition: safe_any.hpp:50
The Blackboard is the mechanism used by BehaviorTrees to exchange typed data.
Definition: blackboard.h:35
void set(const std::string &key, const T &value)
Update the entry with the given key.
Definition: blackboard.h:272
T get(const std::string &key) const
Definition: blackboard.h:236
const PolymorphicCastRegistry * polymorphicCastRegistry() const
Get the polymorphic cast registry (may be null).
Definition: blackboard.h:165
void setPolymorphicCastRegistry(std::shared_ptr< PolymorphicCastRegistry > registry)
Set the polymorphic cast registry for this blackboard.
Definition: blackboard.h:157
Expected< T > tryCastWithPolymorphicFallback(const Any *any) const
Cast Any value with polymorphic fallback for shared_ptr types.
Definition: blackboard.h:210
bool get(const std::string &key, T &value) const
Definition: blackboard.h:389
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:74
void cloneInto(Blackboard &dst) const
cloneInto copies the values of the entries into another blackboard. Known limitations:
The LockedPtr class is used to share a pointer to an object and a mutex that protects the read/write ...
Definition: locked_reference.hpp:18
Registry for polymorphic shared_ptr cast relationships.
Definition: polymorphic_cast_registry.hpp:47
Definition: basic_types.h:404
Definition: basic_types.h:357
Definition: action_node.h:24
void ImportBlackboardFromJSON(const nlohmann::json &json, Blackboard &blackboard)
ImportBlackboardFromJSON will append elements to the blackboard, using the values parsed from the JSO...
nlohmann::json ExportBlackboardToJSON(const Blackboard &blackboard)
ExportBlackboardToJSON will create a JSON that contains the current values of the blackboard....
Definition: blackboard.h:51
Definition: blackboard.h:25
Definition: basic_types.h:340
Definition: safe_any.hpp:39