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  rootBlackboard()->createEntryImpl(key.substr(1, key.size() - 1), info);
147  }
148  else
149  {
150  createEntryImpl(key, info);
151  }
152 }
153 
155 {
156  std::unique_lock lk1(mutex_);
157  std::unique_lock lk2(dst.mutex_);
158 
159  // keys that are not updated must be removed.
160  std::unordered_set<std::string> keys_to_remove;
161  auto& dst_storage = dst.storage_;
162  for(const auto& [key, _] : dst_storage)
163  {
164  keys_to_remove.insert(key);
165  }
166 
167  // update or create entries in dst_storage
168  for(const auto& [src_key, src_entry] : storage_)
169  {
170  keys_to_remove.erase(src_key);
171 
172  auto it = dst_storage.find(src_key);
173  if(it != dst_storage.end())
174  {
175  // overwite
176  auto& dst_entry = it->second;
177  dst_entry->string_converter = src_entry->string_converter;
178  dst_entry->value = src_entry->value;
179  dst_entry->info = src_entry->info;
180  dst_entry->sequence_id++;
181  dst_entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
182  }
183  else
184  {
185  // create new
186  auto new_entry = std::make_shared<Entry>(src_entry->info);
187  new_entry->value = src_entry->value;
188  new_entry->string_converter = src_entry->string_converter;
189  dst_storage.insert({ src_key, new_entry });
190  }
191  }
192 
193  for(const auto& key : keys_to_remove)
194  {
195  dst_storage.erase(key);
196  }
197 }
198 
200 {
201  if(auto parent = parent_bb_.lock())
202  {
203  return parent;
204  }
205  return {};
206 }
207 
208 std::shared_ptr<Blackboard::Entry> Blackboard::createEntryImpl(const std::string& key,
209  const TypeInfo& info)
210 {
211  std::unique_lock<std::mutex> lock(mutex_);
212  // This function might be called recursively, when we do remapping, because we move
213  // to the top scope to find already existing entries
214 
215  // search if exists already
216  auto storage_it = storage_.find(key);
217  if(storage_it != storage_.end())
218  {
219  const auto& prev_info = storage_it->second->info;
220  if(prev_info.type() != info.type() && prev_info.isStronglyTyped() &&
221  info.isStronglyTyped())
222  {
223  auto msg = StrCat("Blackboard entry [", key,
224  "]: once declared, the type of a port"
225  " shall not change. Previously declared type [",
226  BT::demangle(prev_info.type()), "], current type [",
227  BT::demangle(info.type()), "]");
228 
229  throw LogicError(msg);
230  }
231  return storage_it->second;
232  }
233 
234  // manual remapping first
235  auto remapping_it = internal_to_external_.find(key);
236  if(remapping_it != internal_to_external_.end())
237  {
238  const auto& remapped_key = remapping_it->second;
239  if(auto parent = parent_bb_.lock())
240  {
241  return parent->createEntryImpl(remapped_key, info);
242  }
243  throw RuntimeError("Missing parent blackboard");
244  }
245  // autoremapping second (excluding private keys)
246  if(autoremapping_ && !IsPrivateKey(key))
247  {
248  if(auto parent = parent_bb_.lock())
249  {
250  return parent->createEntryImpl(key, info);
251  }
252  throw RuntimeError("Missing parent blackboard");
253  }
254  // not remapped, not found. Create locally.
255 
256  auto entry = std::make_shared<Entry>(info);
257  // even if empty, let's assign to it a default type
258  entry->value = Any(info.type());
259  storage_.insert({ key, entry });
260  return entry;
261 }
262 
264 {
265  nlohmann::json dest;
266  for(auto entry_name : blackboard.getKeys())
267  {
268  std::string name(entry_name);
269  if(auto any_ref = blackboard.getAnyLocked(name))
270  {
271  if(auto any_ptr = any_ref.get())
272  {
273  JsonExporter::get().toJson(*any_ptr, dest[name]);
274  }
275  }
276  }
277  return dest;
278 }
279 
281 {
282  for(auto it = json.begin(); it != json.end(); ++it)
283  {
284  if(auto res = JsonExporter::get().fromJson(it.value()))
285  {
286  auto entry = blackboard.getEntry(it.key());
287  if(!entry)
288  {
289  blackboard.createEntry(it.key(), res->second);
290  entry = blackboard.getEntry(it.key());
291  }
292  entry->value = res->first;
293  }
294  }
295 }
296 
298 {
299  value = other.value;
300  info = other.info;
302  sequence_id = other.sequence_id;
303  stamp = other.stamp;
304  return *this;
305 }
306 
308 {
309  auto bb = static_cast<const Blackboard&>(*this).rootBlackboard();
310  return const_cast<Blackboard*>(bb);
311 }
312 
314 {
315  const Blackboard* bb = this;
317  while(prev)
318  {
319  bb = prev.get();
320  prev = bb->parent_bb_.lock();
321  }
322  return bb;
323 }
324 
325 } // 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:208
BT::Blackboard::parent
Blackboard::Ptr parent()
Definition: blackboard.cpp:199
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:280
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:297
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:263
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:154
BT::Blackboard::rootBlackboard
Blackboard * rootBlackboard()
Definition: blackboard.cpp:307
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:464
json
basic_json<> json
default specialization
Definition: json.hpp:3422
BT::TypeInfo
Definition: basic_types.h:345
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 Jun 28 2024 02:20:07