blackboard.cpp
Go to the documentation of this file.
2 #include <unordered_set>
4 
5 namespace BT
6 {
7 
9 {
10  return str.size() >= 1 && str.data()[0] == '_';
11 }
12 
13 void Blackboard::enableAutoRemapping(bool remapping)
14 {
15  autoremapping_ = remapping;
16 }
17 
18 AnyPtrLocked Blackboard::getAnyLocked(const std::string& key)
19 {
20  if(auto entry = getEntry(key))
21  {
22  return AnyPtrLocked(&entry->value, &entry->entry_mutex);
23  }
24  return {};
25 }
26 
27 AnyPtrLocked Blackboard::getAnyLocked(const std::string& key) const
28 {
29  if(auto entry = getEntry(key))
30  {
31  return AnyPtrLocked(&entry->value, const_cast<std::mutex*>(&entry->entry_mutex));
32  }
33  return {};
34 }
35 
36 const Any* Blackboard::getAny(const std::string& key) const
37 {
38  return getAnyLocked(key).get();
39 }
40 
41 Any* Blackboard::getAny(const std::string& key)
42 {
43  return const_cast<Any*>(getAnyLocked(key).get());
44 }
45 
46 const std::shared_ptr<Blackboard::Entry>
47 Blackboard::getEntry(const std::string& key) const
48 {
49  // special syntax: "@" will always refer to the root BB
50  if(StartWith(key, '@'))
51  {
52  return rootBlackboard()->getEntry(key.substr(1, key.size() - 1));
53  }
54 
55  std::unique_lock<std::mutex> lock(mutex_);
56  auto it = storage_.find(key);
57  if(it != storage_.end())
58  {
59  return it->second;
60  }
61  // not found. Try autoremapping
62  if(auto parent = parent_bb_.lock())
63  {
64  auto remap_it = internal_to_external_.find(key);
65  if(remap_it != internal_to_external_.cend())
66  {
67  auto const& new_key = remap_it->second;
68  return parent->getEntry(new_key);
69  }
70  if(autoremapping_ && !IsPrivateKey(key))
71  {
72  return parent->getEntry(key);
73  }
74  }
75  return {};
76 }
77 
78 std::shared_ptr<Blackboard::Entry> Blackboard::getEntry(const std::string& key)
79 {
80  return static_cast<const Blackboard&>(*this).getEntry(key);
81 }
82 
83 const TypeInfo* Blackboard::entryInfo(const std::string& key)
84 {
85  auto entry = getEntry(key);
86  return (!entry) ? nullptr : &(entry->info);
87 }
88 
90 {
91  internal_to_external_.insert(
92  { static_cast<std::string>(internal), static_cast<std::string>(external) });
93 }
94 
96 {
97  for(const auto& [key, entry] : storage_)
98  {
99  auto port_type = entry->info.type();
100  if(port_type == typeid(void))
101  {
102  port_type = entry->value.type();
103  }
104 
105  std::cout << key << " (" << BT::demangle(port_type) << ")" << std::endl;
106  }
107 
108  for(const auto& [from, to] : internal_to_external_)
109  {
110  std::cout << "[" << from << "] remapped to port of parent tree [" << to << "]"
111  << std::endl;
112  continue;
113  }
114 }
115 
116 std::vector<StringView> Blackboard::getKeys() const
117 {
118  if(storage_.empty())
119  {
120  return {};
121  }
122  std::vector<StringView> out;
123  out.reserve(storage_.size());
124  for(const auto& entry_it : storage_)
125  {
126  out.push_back(entry_it.first);
127  }
128  return out;
129 }
130 
132 {
133  std::unique_lock<std::mutex> lock(mutex_);
134  storage_.clear();
135 }
136 
137 std::recursive_mutex& Blackboard::entryMutex() const
138 {
139  return entry_mutex_;
140 }
141 
142 void Blackboard::createEntry(const std::string& key, const TypeInfo& info)
143 {
144  if(StartWith(key, '@'))
145  {
146  if(key.find('@', 1) != std::string::npos)
147  {
148  throw LogicError("Character '@' used multiple times in the key");
149  }
150  rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
151  }
152  else
153  {
154  createEntryImpl(key, info);
155  }
156 }
157 
159 {
160  std::unique_lock lk1(mutex_);
161  std::unique_lock lk2(dst.mutex_);
162 
163  // keys that are not updated must be removed.
164  std::unordered_set<std::string> keys_to_remove;
165  auto& dst_storage = dst.storage_;
166  for(const auto& [key, _] : dst_storage)
167  {
168  keys_to_remove.insert(key);
169  }
170 
171  // update or create entries in dst_storage
172  for(const auto& [src_key, src_entry] : storage_)
173  {
174  keys_to_remove.erase(src_key);
175 
176  auto it = dst_storage.find(src_key);
177  if(it != dst_storage.end())
178  {
179  // overwite
180  auto& dst_entry = it->second;
181  dst_entry->string_converter = src_entry->string_converter;
182  dst_entry->value = src_entry->value;
183  dst_entry->info = src_entry->info;
184  dst_entry->sequence_id++;
185  dst_entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
186  }
187  else
188  {
189  // create new
190  auto new_entry = std::make_shared<Entry>(src_entry->info);
191  new_entry->value = src_entry->value;
192  new_entry->string_converter = src_entry->string_converter;
193  dst_storage.insert({ src_key, new_entry });
194  }
195  }
196 
197  for(const auto& key : keys_to_remove)
198  {
199  dst_storage.erase(key);
200  }
201 }
202 
204 {
205  if(auto parent = parent_bb_.lock())
206  {
207  return parent;
208  }
209  return {};
210 }
211 
212 std::shared_ptr<Blackboard::Entry> Blackboard::createEntryImpl(const std::string& key,
213  const TypeInfo& info)
214 {
215  std::unique_lock<std::mutex> lock(mutex_);
216  // This function might be called recursively, when we do remapping, because we move
217  // to the top scope to find already existing entries
218 
219  // search if exists already
220  auto storage_it = storage_.find(key);
221  if(storage_it != storage_.end())
222  {
223  const auto& prev_info = storage_it->second->info;
224  if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
225  info.isStronglyTyped())
226  {
227  auto msg = StrCat("Blackboard entry [", key,
228  "]: once declared, the type of a port"
229  " shall not change. Previously declared type [",
230  BT::demangle(prev_info.type()), "], current type [",
231  BT::demangle(info.type()), "]");
232 
233  throw LogicError(msg);
234  }
235  return storage_it->second;
236  }
237 
238  // manual remapping first
239  auto remapping_it = internal_to_external_.find(key);
240  if(remapping_it != internal_to_external_.end())
241  {
242  const auto& remapped_key = remapping_it->second;
243  if(auto parent = parent_bb_.lock())
244  {
245  return parent->createEntryImpl(remapped_key, info);
246  }
247  throw RuntimeError("Missing parent blackboard");
248  }
249  // autoremapping second (excluding private keys)
250  if(autoremapping_ && !IsPrivateKey(key))
251  {
252  if(auto parent = parent_bb_.lock())
253  {
254  return parent->createEntryImpl(key, info);
255  }
256  throw RuntimeError("Missing parent blackboard");
257  }
258  // not remapped, not found. Create locally.
259 
260  auto entry = std::make_shared<Entry>(info);
261  // even if empty, let's assign to it a default type
262  entry->value = Any(info.type());
263  storage_.insert({ key, entry });
264  return entry;
265 }
266 
268 {
269  nlohmann::json dest;
270  for(auto entry_name : blackboard.getKeys())
271  {
272  std::string name(entry_name);
273  if(auto any_ref = blackboard.getAnyLocked(name))
274  {
275  if(auto any_ptr = any_ref.get())
276  {
277  JsonExporter::get().toJson(*any_ptr, dest[name]);
278  }
279  }
280  }
281  return dest;
282 }
283 
285 {
286  for(auto it = json.begin(); it != json.end(); ++it)
287  {
288  if(auto res = JsonExporter::get().fromJson(it.value()))
289  {
290  auto entry = blackboard.getEntry(it.key());
291  if(!entry)
292  {
293  blackboard.createEntry(it.key(), res->second);
294  entry = blackboard.getEntry(it.key());
295  }
296  entry->value = res->first;
297  }
298  }
299 }
300 
302 {
303  value = other.value;
304  info = other.info;
306  sequence_id = other.sequence_id;
307  stamp = other.stamp;
308  return *this;
309 }
310 
312 {
313  auto bb = static_cast<const Blackboard&>(*this).rootBlackboard();
314  return const_cast<Blackboard*>(bb);
315 }
316 
318 {
319  const Blackboard* bb = this;
321  while(prev)
322  {
323  bb = prev.get();
324  prev = bb->parent_bb_.lock();
325  }
326  return bb;
327 }
328 
329 } // namespace BT
BT
Definition: ex01_wrap_legacy.cpp:29
BT::Blackboard::parent_bb_
std::weak_ptr< Blackboard > parent_bb_
Definition: blackboard.h:147
BT::demangle
std::string demangle(char const *name)
Definition: demangle_util.h:74
BT::Blackboard::Entry::sequence_id
uint64_t sequence_id
Definition: blackboard.h:50
BT::Blackboard::clear
void clear()
Definition: blackboard.cpp:131
BT::JsonExporter::toJson
bool toJson(const BT::Any &any, nlohmann::json &destination) const
toJson adds the content of "any" to the JSON "destination".
Definition: json_export.cpp:12
BT::Blackboard::Entry::info
TypeInfo info
Definition: blackboard.h:46
BT::Any
Definition: safe_any.hpp:36
BT::Blackboard::entry_mutex_
std::recursive_mutex entry_mutex_
Definition: blackboard.h:145
BT::Blackboard::createEntryImpl
std::shared_ptr< Entry > createEntryImpl(const std::string &key, const TypeInfo &info)
Definition: blackboard.cpp:212
BT::Blackboard::parent
Blackboard::Ptr parent()
Definition: blackboard.cpp:203
BT::StringView
std::string_view StringView
Definition: basic_types.h:59
BT::Blackboard::mutex_
std::mutex mutex_
Definition: blackboard.h:144
BT::IsPrivateKey
bool IsPrivateKey(StringView str)
Definition: blackboard.cpp:8
BT::ImportBlackboardFromJSON
void ImportBlackboardFromJSON(const nlohmann::json &json, Blackboard &blackboard)
ImportBlackboardFromJSON will append elements to the blackboard, using the values parsed from the JSO...
Definition: blackboard.cpp:284
BT::Blackboard::createEntry
void createEntry(const std::string &key, const TypeInfo &info)
Definition: blackboard.cpp:142
BT::Blackboard::Entry::operator=
Entry & operator=(const Entry &other)
Definition: blackboard.cpp:301
BT::Blackboard::storage_
std::unordered_map< std::string, std::shared_ptr< Entry > > storage_
Definition: blackboard.h:146
BT::Blackboard::getEntry
const std::shared_ptr< Entry > getEntry(const std::string &key) const
Definition: blackboard.cpp:47
basic_json
namespace for Niels Lohmann
Definition: json.hpp:3411
BT::Blackboard::getKeys
std::vector< StringView > getKeys() const
Definition: blackboard.cpp:116
lexy::_detail::any_ref
any_base * any_ref
Definition: any_ref.hpp:43
BT::LogicError
Definition: exceptions.h:45
BT::Blackboard::getAny
const Any * getAny(const std::string &key) const
Definition: blackboard.cpp:36
BT::ExportBlackboardToJSON
nlohmann::json ExportBlackboardToJSON(const Blackboard &blackboard)
ExportBlackboardToJSON will create a JSON that contains the current values of the blackboard....
Definition: blackboard.cpp:267
BT::Blackboard::debugMessage
void debugMessage() const
Definition: blackboard.cpp:95
mutex
static pthread_mutex_t mutex
Definition: minitrace.cpp:77
BT::Blackboard::Ptr
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:35
BT::Blackboard::entryInfo
const TypeInfo * entryInfo(const std::string &key)
Definition: blackboard.cpp:83
BT::Blackboard::enableAutoRemapping
void enableAutoRemapping(bool remapping)
Definition: blackboard.cpp:13
BT::Blackboard::Entry
Definition: blackboard.h:43
lexyd::bit::_
constexpr auto _
Matches any bit.
Definition: bits.hpp:91
BT::AnyPtrLocked
LockedPtr< Any > AnyPtrLocked
Definition: blackboard.h:19
BT::Blackboard::entryMutex
std::recursive_mutex & entryMutex() const
Definition: blackboard.cpp:137
BT::Blackboard::cloneInto
void cloneInto(Blackboard &dst) const
cloneInto copies the values of the entries into another blackboard. Known limitations:
Definition: blackboard.cpp:158
BT::Blackboard::rootBlackboard
Blackboard * rootBlackboard()
Definition: blackboard.cpp:311
BT::Blackboard::addSubtreeRemapping
void addSubtreeRemapping(StringView internal, StringView external)
Definition: blackboard.cpp:89
BT::RuntimeError
Definition: exceptions.h:58
json_export.h
cx::prev
constexpr It prev(It it)
Definition: wildcards.hpp:631
BT::JsonExporter::get
static JsonExporter & get()
Definition: json_export.cpp:6
BT::Blackboard
The Blackboard is the mechanism used by BehaviorTrees to exchange typed data.
Definition: blackboard.h:32
BT::LockedPtr
The LockedPtr class is used to share a pointer to an object and a mutex that protects the read/write ...
Definition: locked_reference.hpp:16
BT::StrCat
std::string StrCat()
Definition: strcat.hpp:46
BT::Blackboard::Entry::value
Any value
Definition: blackboard.h:45
BT::StartWith
bool StartWith(StringView str, StringView prefix)
Definition: basic_types.cpp:476
json
basic_json<> json
default specialization
Definition: json.hpp:3422
BT::TypeInfo
Definition: basic_types.h:347
BT::Blackboard::Entry::string_converter
StringConverter string_converter
Definition: blackboard.h:47
BT::Blackboard::internal_to_external_
std::unordered_map< std::string, std::string > internal_to_external_
Definition: blackboard.h:148
BT::Blackboard::Entry::stamp
std::chrono::nanoseconds stamp
Definition: blackboard.h:52
blackboard.h
BT::Blackboard::autoremapping_
bool autoremapping_
Definition: blackboard.h:152
BT::LockedPtr::get
const T * get() const
Definition: locked_reference.hpp:70
lexy::_detail::any_base::get
constexpr T & get() noexcept
Definition: any_ref.hpp:25
BT::Blackboard::getAnyLocked
AnyPtrLocked getAnyLocked(const std::string &key)
Definition: blackboard.cpp:18


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Feb 28 2025 03:19:18