MemoryBase.h
Go to the documentation of this file.
1#pragma once
2
3#include <map>
4#include <string>
5
6#include "CoreSegmentBase.h"
8#include "detail/Predictive.h"
11
12namespace armarx::armem::base
13{
14
15 /**
16 * @brief Data of a memory consisting of multiple core segments.
17 */
18 template <class _CoreSegmentT, class _Derived>
19 class MemoryBase :
20 public detail::MemoryContainerBase<std::map<std::string, _CoreSegmentT>, _Derived>,
21 public detail::PredictiveContainer<_Derived>,
24 public detail::ForEachEntityMixin<_Derived>,
26 public detail::GetFindInstanceMixin<_Derived>,
27 public detail::GetFindSnapshotMixin<_Derived>,
28 public detail::GetFindEntityMixin<_Derived>,
30 {
32
33 public:
34 using typename Base::ContainerT;
35 using typename Base::DerivedT;
36
37 using CoreSegmentT = _CoreSegmentT;
38 using ProviderSegmentT = typename CoreSegmentT::ProviderSegmentT;
39 using EntityT = typename ProviderSegmentT::EntityT;
40 using EntitySnapshotT = typename EntityT::EntitySnapshotT;
41 using EntityInstanceT = typename EntitySnapshotT::EntityInstanceT;
42
44
67
68 public:
70 {
71 }
72
73 explicit MemoryBase(const std::string& name,
74 const std::vector<PredictionEngine>& predictionEngines = {}) :
75 MemoryBase(MemoryID().withMemoryName(name), predictionEngines)
76 {
77 }
78
79 explicit MemoryBase(const MemoryID& id,
80 const std::vector<PredictionEngine>& predictionEngines = {}) :
81 Base(id), detail::PredictiveContainer<_Derived>(predictionEngines)
82 {
83 }
84
85 MemoryBase(const MemoryBase& other) = default;
86 MemoryBase(MemoryBase&& other) = default;
87 MemoryBase& operator=(const MemoryBase& other) = default;
88 MemoryBase& operator=(MemoryBase&& other) = default;
89
90 // READ ACCESS
91
92 // Get key
93 inline std::string&
95 {
96 return this->id().memoryName;
97 }
98
99 inline const std::string&
100 name() const
101 {
102 return this->id().memoryName;
103 }
104
105 // Has child by key
106 bool
107 hasCoreSegment(const std::string& name) const
108 {
109 return this->findCoreSegment(name) != nullptr;
110 }
111
112 // Has child by MemoryID
113 bool
114 hasCoreSegment(const MemoryID& coreSegmentID) const
115 {
116 return this->findCoreSegment(coreSegmentID) != nullptr;
117 }
118
119 // Find child by key
121 findCoreSegment(const std::string& name)
122 {
124 }
125
126 const CoreSegmentT*
127 findCoreSegment(const std::string& name) const
128 {
130 }
131
132 // Get child by key
134 getCoreSegment(const std::string& name)
135 {
136 return detail::getChildByKey(name, this->_container, *this);
137 }
138
139 const CoreSegmentT&
140 getCoreSegment(const std::string& name) const
141 {
142 return detail::getChildByKey(name, this->_container, *this);
143 }
144
145 // Find child by MemoryID
147 findCoreSegment(const MemoryID& coreSegmentID)
148 {
149 detail::checkHasCoreSegmentName(coreSegmentID);
150 return this->findCoreSegment(coreSegmentID.coreSegmentName);
151 }
152
153 const CoreSegmentT*
154 findCoreSegment(const MemoryID& coreSegmentID) const
155 {
156 detail::checkHasCoreSegmentName(coreSegmentID);
157 return this->findCoreSegment(coreSegmentID.coreSegmentName);
158 }
159
160 // Get child by MemoryID
162 getCoreSegment(const MemoryID& coreSegmentID)
163 {
164 detail::checkHasCoreSegmentName(coreSegmentID);
165 return this->getCoreSegment(coreSegmentID.coreSegmentName);
166 }
167
168 const CoreSegmentT&
169 getCoreSegment(const MemoryID& coreSegmentID) const
170 {
171 detail::checkHasCoreSegmentName(coreSegmentID);
172 return this->getCoreSegment(coreSegmentID.coreSegmentName);
173 }
174
175 // get/findInstance are provided by GetFindInstanceMixin
176 // get/findSnapshot are provided by GetFindSnapshotMixin
177 // get/findEntity are provided by GetFindEntityMixin
178 // get/findProviderSegment are provided by GetFindProviderSegmentMixin
179
180
181 // ITERATION
182
183 /**
184 * @param func Function like: bool process(CoreSegmentT& coreSeg)
185 */
186 template <class CoreSegmentFunctionT>
187 bool
188 forEachCoreSegment(CoreSegmentFunctionT&& func)
189 {
190 return this->forEachChild(func);
191 }
192
193 /**
194 * @param func Function like: bool process(const CoreSegmentT& coreSeg)
195 */
196 template <class CoreSegmentFunctionT>
197 bool
198 forEachCoreSegment(CoreSegmentFunctionT&& func) const
199 {
200 return this->forEachChild(func);
201 }
202
203 // forEachProviderSegment() is provided by ForEachProviderSegmentMixin.
204 // forEachEntity() is provided by ForEachEntityMixin.
205 // forEachSnapshot() is provided by ForEachEntitySnapshotMixin.
206 // forEachInstance() is provided by ForEachEntityInstanceMixin.
207
208
209 /**
210 * @param func Function like void process(EntityInstanceT& instance)>
211 */
212 template <class InstanceFunctionT>
213 bool
214 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func)
215 {
217 id,
218 func,
219 *this,
220 id.hasCoreSegmentName(),
221 id.hasCoreSegmentName() ? this->findCoreSegment(id.coreSegmentName) : nullptr);
222 }
223
224 /**
225 * @param func Function like void process(EntityInstanceT& instance)>
226 */
227 template <class InstanceFunctionT>
228 bool
229 forEachInstanceIn(const MemoryID& id, InstanceFunctionT&& func) const
230 {
232 id,
233 func,
234 *this,
235 id.hasCoreSegmentName(),
236 id.hasCoreSegmentName() ? this->findCoreSegment(id.coreSegmentName) : nullptr);
237 }
238
239 std::vector<std::string>
241 {
242 return simox::alg::get_keys(this->_container);
243 }
244
245 // MODIFICATION
246
247 void
248 setName(const std::string& name)
249 {
250 this->id().memoryName = name;
251 }
252
253 /**
254 * @brief Add an empty core segment with the given name, type and prediction engines.
255 * @param name The core segment name.
256 * @param coreSegmentType The core segment type (optional).
257 * @param predictionEngines The prediction engines supported by the core segment (optional).
258 * @return The added core segment.
259 */
261 addCoreSegment(const std::string& name,
262 aron::type::ObjectPtr coreSegmentType = nullptr,
263 const std::vector<PredictionEngine>& predictionEngines = {})
264 {
265 ARMARX_DEBUG << "Adding core segment " << name << " with type "
266 << (coreSegmentType != nullptr);
267 CoreSegmentT& c =
268 this->_derived().addCoreSegment(name, name, coreSegmentType, predictionEngines);
269 if (coreSegmentType != nullptr)
270 {
271 c.setAronType(coreSegmentType);
272 }
273 ARMARX_DEBUG << "Newly added core segment " << name << " has type: " << c.hasAronType();
274 return c;
275 }
276
277 /// Copy and insert a core segment.
279 addCoreSegment(const CoreSegmentT& coreSegment)
280 {
281 return this->_derived().addCoreSegment(coreSegment.name(), CoreSegmentT(coreSegment));
282 }
283
284 /// Move and insert a core segment.
287 {
288 const std::string name = coreSegment.name(); // Copy before move.
289 return this->_derived().addCoreSegment(name, std::move(coreSegment));
290 }
291
292 /// Move and insert a core segment.
293 template <class... Args>
295 addCoreSegment(const std::string& name, Args... args)
296 {
297 CoreSegmentT& child = this->template _addChild<ChildT>(name, args...);
298 child.id() = this->id().withCoreSegmentName(name);
299 ARMARX_DEBUG << "Templated copy of core segment with name " << name
300 << " has aron type: " << child.hasAronType();
301 return child;
302 }
303
304 /**
305 * @brief Store all updates in `commit`.
306 * @param commit The commit.
307 * @return The resulting memory IDs.
308 */
309 std::vector<UpdateResult>
310 update(const Commit& commit,
311 const bool addMissingCoreSegmentDuringUpdate = false,
312 const bool checkMemoryName = true)
313 {
314 std::vector<UpdateResult> results;
315 for (const EntityUpdate& update : commit.updates)
316 {
317 results.push_back(
318 this->update(update, addMissingCoreSegmentDuringUpdate, checkMemoryName));
319 }
320 return results;
321 }
322
323 /**
324 * @brief Store the given update.
325 * @param update The update.
326 * @return The resulting entity snapshot's ID.
327 */
328 UpdateResult
330 const bool addMissingCoreSegmentDuringUpdate = false,
331 const bool checkMemoryName = true)
332 {
333 if (checkMemoryName)
334 {
335 this->_checkContainerName(update.entityID.memoryName, this->name());
336 }
337
338 ARMARX_DEBUG << "Adding update for " << update.entityID.coreSegmentName;
339
340 auto [inserted, coreSeg] = _addCoreSegmentIfMissing(update.entityID.coreSegmentName,
341 addMissingCoreSegmentDuringUpdate);
342
343 // Update entry.
344 UpdateResult ret(coreSeg->update(update));
345 if (inserted)
346 {
347 ARMARX_DEBUG << "Inserted new core segment";
348 ret.memoryUpdateType = UpdateType::InsertedNew;
349 }
350 else
351 {
352 ret.memoryUpdateType = UpdateType::UpdatedExisting;
353 }
354 return ret;
355 }
356
357 /**
358 * @brief Merge another memory into this one. Append all data and types if possible
359 * @param m The other memory
360 */
361 template <class OtherDerivedT>
362 void
363 append(const OtherDerivedT& other)
364 {
365 other.forEachCoreSegment(
366 [this](const auto& coreSeg)
367 {
368 auto it = this->_container.find(coreSeg.name());
369 if (it == this->_container.end())
370 {
371 it = this->_container
372 .emplace(coreSeg.name(),
373 this->id().withCoreSegmentName(coreSeg.name()))
374 .first;
375 it->second.aronType() = coreSeg.aronType();
376 }
377
378 /*TODO: if (it->second.aronType() != coreSeg.aronType())
379 {
380 ARMARX_WARNING << "When appending a wm to another wm type conflicts have "
381 "been found. Setting the type to NULL...";
382 it->second.aronType() = nullptr;
383 }*/
384
385 it->second.append(coreSeg);
386 return true;
387 });
388 }
389
390 bool
391 equalsDeep(const MemoryBase& other) const
392
393 {
394 //std::cout << "Memory::equalsDeep" << std::endl;
395 if (this->size() != other.size())
396 {
397 return false;
398 }
399 for (const auto& [key, core] : this->_container)
400 {
401 if (not other.hasCoreSegment(key))
402 {
403 return false;
404 }
405 if (not core.equalsDeep(other.getCoreSegment(key)))
406 {
407 return false;
408 }
409 }
410 return true;
411 }
412
413 static std::string
415 {
416 return "memory";
417 }
418
419 std::string
421 {
422 return this->name();
423 }
424
425
426 protected:
427 std::pair<bool, CoreSegmentT*>
428 _addCoreSegmentIfMissing(const std::string& coreSegmentName,
429 const bool addMissingCoreSegmentDuringUpdate)
430 {
431 CoreSegmentT* coreSeg = nullptr;
432
433 ARMARX_DEBUG << "Checking for CoreSegment for " << coreSegmentName << ": "
434 << this->hasCoreSegment(coreSegmentName);
435
436 if (!this->hasCoreSegment(coreSegmentName))
437 {
438 if (addMissingCoreSegmentDuringUpdate)
439 {
440 ARMARX_DEBUG << "adding empty core segment " << coreSegmentName << " to "
441 << this->id();
442 // Insert into map.
443 coreSeg = &addCoreSegment(coreSegmentName);
444 return {true, coreSeg};
445 }
446 else
447 {
448 throw error::MissingEntry::create<CoreSegmentT>(coreSegmentName, *this);
449 }
450 }
451 else
452 {
453 auto memID = this->id().withCoreSegmentName(coreSegmentName);
454 coreSeg = &this->getCoreSegment(coreSegmentName);
455 return {false, coreSeg};
456 }
457 }
458 };
459} // namespace armarx::armem::base
constexpr T c
std::string coreSegmentName
Definition MemoryID.h:51
MemoryID withCoreSegmentName(const std::string &name) const
Definition MemoryID.cpp:409
std::string memoryName
Definition MemoryID.h:50
Data of a memory consisting of multiple core segments.
Definition MemoryBase.h:30
MemoryBase & operator=(MemoryBase &&other)=default
bool forEachCoreSegment(CoreSegmentFunctionT &&func)
Definition MemoryBase.h:188
CoreSegmentT & addCoreSegment(const std::string &name, Args... args)
Move and insert a core segment.
Definition MemoryBase.h:295
typename ProviderSegmentT::EntityT EntityT
Definition MemoryBase.h:39
typename EntityT::EntitySnapshotT EntitySnapshotT
Definition MemoryBase.h:40
std::pair< bool, CoreSegmentT * > _addCoreSegmentIfMissing(const std::string &coreSegmentName, const bool addMissingCoreSegmentDuringUpdate)
Definition MemoryBase.h:428
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func)
Definition MemoryBase.h:214
CoreSegmentT * findCoreSegment(const std::string &name)
Definition MemoryBase.h:121
const std::string & name() const
Definition MemoryBase.h:100
const CoreSegmentT * findCoreSegment(const MemoryID &coreSegmentID) const
Definition MemoryBase.h:154
CoreSegmentT & getCoreSegment(const MemoryID &coreSegmentID)
Definition MemoryBase.h:162
CoreSegmentT & addCoreSegment(CoreSegmentT &&coreSegment)
Move and insert a core segment.
Definition MemoryBase.h:286
bool hasCoreSegment(const MemoryID &coreSegmentID) const
Definition MemoryBase.h:114
bool hasCoreSegment(const std::string &name) const
Definition MemoryBase.h:107
MemoryBase(MemoryBase &&other)=default
UpdateResult update(const EntityUpdate &update, const bool addMissingCoreSegmentDuringUpdate=false, const bool checkMemoryName=true)
Store the given update.
Definition MemoryBase.h:329
const CoreSegmentT & getCoreSegment(const std::string &name) const
Definition MemoryBase.h:140
MemoryBase(const MemoryBase &other)=default
CoreSegmentT & addCoreSegment(const std::string &name, aron::type::ObjectPtr coreSegmentType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
Add an empty core segment with the given name, type and prediction engines.
Definition MemoryBase.h:261
const CoreSegmentT & getCoreSegment(const MemoryID &coreSegmentID) const
Definition MemoryBase.h:169
bool forEachInstanceIn(const MemoryID &id, InstanceFunctionT &&func) const
Definition MemoryBase.h:229
void setName(const std::string &name)
Definition MemoryBase.h:248
static std::string getLevelName()
Definition MemoryBase.h:414
void append(const OtherDerivedT &other)
Merge another memory into this one.
Definition MemoryBase.h:363
bool equalsDeep(const MemoryBase &other) const
Definition MemoryBase.h:391
typename EntitySnapshotT::EntityInstanceT EntityInstanceT
Definition MemoryBase.h:41
typename CoreSegmentT::ProviderSegmentT ProviderSegmentT
Definition MemoryBase.h:38
std::vector< UpdateResult > update(const Commit &commit, const bool addMissingCoreSegmentDuringUpdate=false, const bool checkMemoryName=true)
Store all updates in commit.
Definition MemoryBase.h:310
CoreSegmentT & addCoreSegment(const CoreSegmentT &coreSegment)
Copy and insert a core segment.
Definition MemoryBase.h:279
CoreSegmentT * findCoreSegment(const MemoryID &coreSegmentID)
Definition MemoryBase.h:147
MemoryBase & operator=(const MemoryBase &other)=default
MemoryBase(const std::string &name, const std::vector< PredictionEngine > &predictionEngines={})
Definition MemoryBase.h:73
std::string getKeyString() const
Definition MemoryBase.h:420
std::vector< std::string > getCoreSegmentNames() const
Definition MemoryBase.h:240
CoreSegmentT & getCoreSegment(const std::string &name)
Definition MemoryBase.h:134
const CoreSegmentT * findCoreSegment(const std::string &name) const
Definition MemoryBase.h:127
MemoryBase(const MemoryID &id, const std::vector< PredictionEngine > &predictionEngines={})
Definition MemoryBase.h:79
bool forEachCoreSegment(CoreSegmentFunctionT &&func) const
Definition MemoryBase.h:198
Provides default implmentations of MemoryContainer, as well as iterators (which requires a template).
void _checkContainerName(const std::string &gottenName, const std::string &actualName, bool emptyOk=true) const
Something that supports a set of prediction engines.
Definition Predictive.h:89
const std::vector< PredictionEngine > & predictionEngines() const
Definition Predictive.h:46
static MissingEntry create(const std::string &missingKey, const ContainerT &container)
Definition ArMemError.h:79
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
auto & getChildByKey(const KeyT &key, ContainerT &&container, const ParentT &owner, KeyStringFn &&keyStringFn)
Retrieve a child in a container by its key.
bool forEachInstanceIn(const MemoryID &id, FunctionT &&func, ParentT &parent, bool single, ChildT *child)
void checkHasCoreSegmentName(const MemoryID &coreSegmentID)
Throw armem::error::InvalidMemoryID if the given ID has core segment name.
auto * findChildByKey(const KeyT &key, ContainerT &&container)
Find a child in a container by its key.
UpdateType
The type of an update.
Definition Commit.h:17
std::shared_ptr< Object > ObjectPtr
Definition Object.h:36
A bundle of updates to be sent to the memory.
Definition Commit.h:90
std::vector< EntityUpdate > updates
The entity updates.
Definition Commit.h:97
An update of an entity for a specific point in time.
Definition Commit.h:26
MemoryID entityID
The entity's ID.
Definition Commit.h:28
UpdateResult(const typename CoreSegmentT::UpdateResult &c)
Definition MemoryBase.h:57
std::vector< EntitySnapshotT > updatedSnapshots
Definition MemoryBase.h:53
armarx::armem::UpdateType coreSegmentUpdateType
Definition MemoryBase.h:48
armarx::armem::UpdateType entityUpdateType
Definition MemoryBase.h:50
std::vector< EntitySnapshotT > removedSnapshots
Definition MemoryBase.h:52
armarx::armem::UpdateType memoryUpdateType
Definition MemoryBase.h:47
armarx::armem::UpdateType providerSegmentUpdateType
Definition MemoryBase.h:49