Segment.cpp
Go to the documentation of this file.
1 #include "Segment.h"
2 
3 #include <filesystem>
4 #include <sstream>
5 
6 #include <sys/inotify.h>
7 
8 #include <Eigen/Dense>
9 #include <Eigen/Geometry>
10 
11 #include <SimoxUtility/algorithm/get_map_keys_values.h>
12 #include <SimoxUtility/algorithm/string.h>
13 #include <SimoxUtility/json.h>
14 #include <SimoxUtility/math/pose/pose.h>
15 #include <SimoxUtility/math/regression/linear.h>
16 
24 
27 #include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
38 #include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
39 #include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
47 
49 {
50 
51  void
53  {
54  defs->optional(robotName,
55  prefix + "robotName",
56  "Name of robot whose note can be calibrated.\n"
57  "If not given, the 'fallbackName' is used.");
58  defs->optional(robotNode, prefix + "robotNode", "Robot node which can be calibrated.");
59  defs->optional(offset, prefix + "offset", "Offset for the node to be calibrated.");
60  }
61 
63  SpecializedCoreSegment(memoryToIceAdapter,
64  objects::instaceSegmentID.coreSegmentName,
65  arondto::ObjectInstance::ToAronType(),
66  64)
67  {
68  oobbCache.setFetchFn(
69  [this](const ObjectID& id) -> std::optional<simox::OrientedBoxf>
70  {
71  // Try to get OOBB from repository.
72  if (std::optional<ObjectInfo> objectInfo = objectFinder.findObject(id))
73  {
74  try
75  {
76  objectInfo->setLogError(false); // Don't log missing files
77  return objectInfo->loadOOBB();
78  }
79  catch (const std::ios_base::failure& e)
80  {
81  // Give up - no OOBB information.
82  ARMARX_WARNING << "Could not get OOBB of object " << id << ".\n- "
83  << e.what();
84  return std::nullopt;
85  }
86  }
87  else
88  {
89  return std::nullopt;
90  }
91  });
92 
93  classNameToDatasetCache.setFetchFn(
94  [this](const std::string& className)
95  {
96  std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className);
97  return objectInfo ? objectInfo->dataset() : "";
98  });
99  }
100 
101  Segment::~Segment()
102  {
103  }
104 
105  void
106  Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
107  {
108  SpecializedCoreSegment::defineProperties(defs, prefix);
109 
110  defs->optional(
111  p.discardSnapshotsWhileAttached,
112  prefix + "DiscardSnapshotsWhileAttached",
113  "If true, no new snapshots are stored while an object is attached to a robot node.\n"
114  "If false, new snapshots are stored, but the attachment is kept in the new snapshots.");
115 
116  defs->optional(robots.fallbackName,
117  prefix + "robots.FallbackName",
118  "Robot name to use as fallback if the robot name is not specified "
119  "in a provided object pose.");
120 
121  defs->optional(
122  p.sceneSnapshotsPackage,
123  prefix + "scene.10_Package",
124  "ArmarX package containing the scene snapshots.\n"
125  "Scene snapshots are expected to be located in Package/data/Package/Scenes/*.json.");
126  defs->optional(p.sceneSnapshotsDirectory,
127  prefix + "scene.11_Directory",
128  "Directory in Package/data/Package/ containing the scene snapshots.");
129 
130  std::vector<std::string> sceneSnapshotToLoadDescription = {
131  "Scene(s) to load on startup.",
132  "Specify multiple scenes in a ; separated list.",
133  "Each entry must be one of the following:",
134  "(1) A scene file in 'Package/scenes/' (with or without '.json' extension), "
135  "e.g. 'MyScene', 'MyScene.json'",
136  "(2) A path to a scene file relative to 'Package/scenes/' (with or without '.json' "
137  "extension), "
138  "e.g. 'path/to/MyScene', 'path/to/MyScene.json'",
139  "(3) An ArmarX data path to a scene file, e.g. 'Package/scenes/path/to/MyScene.json'",
140  };
141  defs->optional(p.sceneSnapshotsToLoad,
142  prefix + "scene.12_SnapshotToLoad",
143  simox::alg::join(sceneSnapshotToLoadDescription, " \n"));
144 
145  defs->optional(p.autoReloadSceneSnapshotsOnFileChange,
146  prefix + "scene.13_autoReloadSceneSnapshotsOnFileChange");
147 
148  decay.defineProperties(defs, prefix + "decay.");
149  }
150 
151  std::vector<std::string>
152  Segment::Properties::getSceneSnapshotsToLoad() const
153  {
154  if (sceneSnapshotsToLoad.empty())
155  {
156  return {};
157  }
158  bool trim = true;
159  return simox::alg::split(sceneSnapshotsToLoad, ";", trim);
160  }
161 
162  void
163  Segment::init()
164  {
165  SpecializedCoreSegment::init();
166 
167  const std::vector<std::string> scenes = p.getSceneSnapshotsToLoad();
168  for (const std::string& scene : scenes)
169  {
170  const bool lockMemory = false;
171  commitSceneSnapshotFromFilename(scene, lockMemory);
172  }
173 
174  robots.setTag(Logging::tag);
175 
176  if (p.autoReloadSceneSnapshotsOnFileChange)
177  {
178 
179  int inotifyFd;
180 
181  // init inotify
182  {
183 
184  inotifyFd = inotify_init();
185  if (inotifyFd == -1)
186  {
187  ARMARX_WARNING << "inotify_init failed";
188  }
189  }
190 
191  std::map<int, std::string> wds;
192 
193  // set up inotify watchers
194  for (const auto& scene : scenes)
195  {
196  if (std::optional<std::filesystem::path> path = resolveSceneFilepath(scene))
197  {
198  auto wd = inotify_add_watch(inotifyFd, path.value().c_str(), IN_MODIFY);
199  if (wd == -1)
200  {
201  ARMARX_WARNING << "inotify_add_watch for scene: " << scene << "` failed.";
202  }
203 
204  ARMARX_INFO << "inotify_add_watch for scene: " << scene << "` added.";
205  wds.emplace(wd, scene);
206  }
207  else
208  {
209  ARMARX_WARNING << "Faild to add file watcher for scene: `" << scene << "`.";
210  }
211  }
212 
213  ARMARX_INFO << "Set up inotify events.";
214 
215  fileWatcherTask = new SimpleRunningTask<>(
216  [this, inotifyFd, wds]()
217  {
218  constexpr std::size_t BUF_LEN = (10 * (sizeof(inotify_event) + NAME_MAX + 1));
219  char buf[BUF_LEN];
220 
221 
222  for (;;)
223  {
224  ssize_t numRead;
225 
226  numRead = read(inotifyFd, buf, BUF_LEN);
227  if (numRead == 0)
228  {
229  ARMARX_WARNING << "read() from inotify fd returned 0!";
230  }
231 
232  if (numRead == -1)
233  {
234  ARMARX_VERBOSE << "read";
235  }
236 
237  ARMARX_DEBUG << VAROUT(numRead);
238 
239  for (char* p = buf; p < buf + numRead;)
240  {
241  auto* event = reinterpret_cast<inotify_event*>(p);
242 
243  const auto& scene = wds.at(event->wd);
244  ARMARX_INFO << "File changed: " << VAROUT(scene);
245 
246  p += sizeof(struct inotify_event) + event->len;
247 
248  const bool lockMemory = true;
249  commitSceneSnapshotFromFilename(scene, lockMemory);
250  }
251  }
252  });
253 
254  fileWatcherTask->start();
255  }
256  }
257 
258  void
259  Segment::connect(viz::Client arviz)
260  {
261  (void)arviz;
262  // ARMARX_INFO << "ArticulatedObjectVisu";
263  // this->visu = std::make_unique<ArticulatedObjectVisu>(arviz, *this);
264  // visu->init();
265  }
266 
268  Segment::commitObjectPoses(const std::string& providerName,
269  const objpose::data::ProvidedObjectPoseSeq& providedPoses,
270  const Calibration& calibration,
271  std::optional<armem::Time> discardUpdatesUntil)
272  {
273  CommitStats stats;
274 
275  // Build new poses.
276  objpose::ObjectPoseSeq newObjectPoses;
277  stats.numUpdated = 0;
278 
279  // timestamp used to reduce the rpc calls for robot sync
280  Time robotSyncTimestamp = Time::Invalid();
281 
282  for (const objpose::data::ProvidedObjectPose& provided : providedPoses)
283  {
284  const Time timestamp = armarx::fromIce<Time>(provided.timestamp);
285 
286  // Check whether we have an old snapshot for this object.
287  std::optional<objpose::ObjectPose> previousPose;
288  const wm::Entity* entity =
289  findObjectEntity(armarx::fromIce(provided.objectID), providerName);
290  if (entity)
291  {
292  const arondto::ObjectInstance data = getLatestInstanceData(*entity);
293 
294  previousPose = objpose::ObjectPose();
295  fromAron(data, *previousPose);
296  }
297 
298  bool discard = false;
299  if (discardUpdatesUntil && timestamp < discardUpdatesUntil.value())
300  {
301  // Dicard updates temporarily (e.g. due to head movement).
302  discard = true;
303  }
304  else if (previousPose)
305  {
306  if (p.discardSnapshotsWhileAttached && previousPose->attachment)
307  {
308  // Discard update due to active attachemnt.
309  discard = true;
310  }
311  else if (timestamp == previousPose->timestamp)
312  {
313  // Discard update as it is not new.
314  discard = true;
315  }
316  }
317 
318  if (discard)
319  {
320  continue;
321  }
322 
323  // Update the entity.
324  stats.numUpdated++;
325 
326  VirtualRobot::RobotPtr robot = robots.get(provided.robotName, provided.providerName);
327  if (not robot)
328  {
329  ARMARX_INFO << deactivateSpam(1) << "Failed to retrieve robot `"
330  << provided.robotName << "`.";
331  }
332 
333  // robot may be null!
334 
335  bool synchronized = false;
336 
337  // Update the robot to obtain correct local -> global transformation
338  if (robot and robotSyncTimestamp != timestamp)
339  {
340  synchronized = robots.reader->synchronizeRobot(*robot, timestamp);
341  if (not synchronized)
342  {
343  ARMARX_INFO << deactivateSpam(5) << "Failed to synchronize robot to timestamp "
344  << timestamp << " of provided object pose (" << provided.objectID
345  << "). This is " << (Clock::Now() - timestamp).toSecondsDouble()
346  << " seconds in the past.";
347  }
348 
349  robotSyncTimestamp = timestamp;
350 
351  // Apply calibration offset after synchronizing the robot.
352  {
353  if (calibration.offset != 0 and robot->hasRobotNode(calibration.robotNode))
354  {
355  VirtualRobot::RobotNodePtr robotNode =
356  robot->getRobotNode(calibration.robotNode);
357 
358  float value = robotNode->getJointValue();
359  float newValue = value + calibration.offset;
360 
361  /*
362  * If newValue is out of the joint's limits, then the calibration would be ignored.
363  * In that case, we expand the joint value limits of the local robot model to allow
364  * for the calibrated value.
365  * As this is just for perception (and not for controlling the robot), this should be fine^TM.
366  */
367  VirtualRobot::RobotNode::JointLimits limits = robotNode->getJointLimits();
368  bool limitsChanged = false;
369  if (newValue < limits.low)
370  {
371  limits.low = newValue;
372  limitsChanged = true;
373  }
374  if (newValue > limits.high)
375  {
376  limits.high = newValue;
377  limitsChanged = true;
378  }
379  if (limitsChanged)
380  {
381  robotNode->setJointLimits(limits.low, limits.high);
382  }
383 
384  robotNode->setJointValue(newValue);
385  }
386  }
387  }
388  else if (robot and timestamp == robotSyncTimestamp)
389  {
390  synchronized = true;
391  }
392 
393  if (not synchronized)
394  {
395  /*
396  * We know nothing about the current robot configuration. So the behvaiour of the
397  * following code is the same as if we have no robot model at all.
398  */
400  << "Robot could not be synchronized; discarding robot";
401  robot = nullptr;
402  }
403 
404  objpose::ObjectPose& newPose = newObjectPoses.emplace_back();
405  if (provided.objectPoseFrame.empty())
406  {
407  objpose::data::ProvidedObjectPose copy = provided;
408  copy.objectPoseFrame = armarx::GlobalFrame;
409  newPose.fromProvidedPose(copy, robot); // robot == nullptr is OK.
410  }
411  else
412  {
413  newPose.fromProvidedPose(provided, robot); // robot == nullptr is OK.
414  }
415 
416  if (previousPose && previousPose->attachment)
417  {
418  // Keep current attachment.
419  ARMARX_CHECK(!p.discardSnapshotsWhileAttached);
420  newPose.attachment = previousPose->attachment;
421  }
422 
423  if (newPose.objectID.dataset().empty())
424  {
425  // Try to find the data set.
426  const std::string dataset =
427  classNameToDatasetCache.get(newPose.objectID.className());
428  if (!dataset.empty())
429  {
430  newPose.objectID = {
431  dataset, newPose.objectID.className(), newPose.objectID.instanceName()};
432  }
433  }
434  if (!provided.localOOBB)
435  {
436  // Try to load oobb from disk.
437  newPose.localOOBB = getObjectOOBB(newPose.objectID);
438  }
439  }
440 
441  commitObjectPoses(newObjectPoses, providerName);
442 
443  return stats;
444  }
445 
446  void
447  Segment::commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName)
448  {
449  Time now = Time::Now();
450 
451  ARMARX_CHECK_NOT_NULL(segmentPtr);
452  const MemoryID coreSegmentID = segmentPtr->id();
453 
454  Commit commit;
455  for (const objpose::ObjectPose& pose : objectPoses)
456  {
457  EntityUpdate& update = commit.updates.emplace_back();
458 
460  providerName.empty() ? pose.providerName : providerName);
461 
462  update.entityID = providerID.withEntityName(pose.objectID.str());
463  update.arrivedTime = now;
464  update.referencedTime = pose.timestamp;
465  update.confidence = pose.confidence;
466 
467  arondto::ObjectInstance dto;
468  toAron(dto, pose);
469  // Search for object class.
470  if (auto instance = findClassInstance(pose.objectID))
471  {
472  toAron(dto.classID, instance->id());
473  }
474  else
475  {
476  toAron(dto.classID, MemoryID());
477  }
478  toAron(dto.sourceID, MemoryID());
479  update.instancesData.push_back(dto.toAron());
480  }
481  // Commit non-locking.
482  iceMemory.commit(commit);
483  }
484 
486  Segment::getObjectPoses(const DateTime& now)
487  {
488  ObjectPoseMap objectPoses = getLatestObjectPoses();
489  updateObjectPoses(objectPoses, now);
490  return filterObjectPoses(objectPoses);
491  }
492 
494  Segment::getObjectPosesByProvider(const std::string& providerName, const DateTime& now)
495  {
496  ARMARX_CHECK_NOT_NULL(segmentPtr);
497  ObjectPoseMap objectPoses =
498  getLatestObjectPoses(segmentPtr->getProviderSegment(providerName));
499  updateObjectPoses(objectPoses, now);
500  return filterObjectPoses(objectPoses);
501  }
502 
503  wm::Entity*
504  Segment::findObjectEntity(const ObjectID& objectID, const std::string& providerName)
505  {
506  ARMARX_CHECK_NOT_NULL(segmentPtr);
507  armem::MemoryID entityID = armem::MemoryID().withEntityName(objectID.str());
508  if (providerName.empty())
509  {
510  wm::Entity* result = nullptr;
511  segmentPtr->forEachProviderSegment(
512  [&result, &entityID](wm::ProviderSegment& prov)
513  {
514  if (prov.hasEntity(entityID.entityName))
515  {
516  result = &prov.getEntity(entityID);
517  return false;
518  }
519  return true;
520  });
521  return result;
522  }
523  else
524  {
525  entityID.providerSegmentName = providerName;
526  if (segmentPtr->hasProviderSegment(providerName))
527  {
528  wm::ProviderSegment& prov = segmentPtr->getProviderSegment(providerName);
529  return prov.hasEntity(entityID.entityName) ? &prov.getEntity(entityID) : nullptr;
530  }
531  else
532  {
533  return nullptr;
534  }
535  }
536  }
537 
538  void
539  Segment::updateObjectPoses(ObjectPoseMap& objectPoses, const DateTime& now)
540  {
541  bool agentSynchronized = false;
542 
543  for (auto& [id, objectPose] : objectPoses)
544  {
545  VirtualRobot::RobotPtr robot =
546  robots.get(objectPose.robotName, objectPose.providerName);
547  updateObjectPose(objectPose, now, robot, agentSynchronized);
548  }
549  }
550 
551  void
552  Segment::updateObjectPoses(ObjectPoseMap& objectPoses,
553  const DateTime& now,
555  bool& agentSynchronized) const
556  {
557  for (auto& [id, objectPose] : objectPoses)
558  {
559  updateObjectPose(objectPose, now, agent, agentSynchronized);
560  }
561  }
562 
563  void
564  Segment::updateObjectPose(ObjectPose& objectPose,
565  const DateTime& now,
567  bool& agentSynchronized) const
568  {
569  updateAttachement(objectPose, agent, agentSynchronized);
570 
571  if (decay.enabled)
572  {
573  decay.updateConfidence(objectPose, now);
574  }
575  }
576 
578  Segment::filterObjectPoses(const ObjectPoseMap& objectPoses) const
579  {
580  ObjectPoseMap result;
581  for (const auto& [id, objectPose] : objectPoses)
582  {
583  if (!(decay.enabled && objectPose.confidence < decay.removeObjectsBelowConfidence))
584  {
585  result[id] = objectPose;
586  }
587  }
588  return result;
589  }
590 
591  void
592  Segment::updateAttachement(ObjectPose& objectPose,
594  bool& synchronized) const
595  {
596  if (not objectPose.attachment.has_value())
597  {
598  // No attachment, nothing to do.
599  return;
600  }
601  ARMARX_CHECK(objectPose.attachment);
602 
603  if (not agent)
604  {
605  // Without a robot model, we cannot update the object pose.
606  return;
607  }
608  ARMARX_CHECK_NOT_NULL(agent);
609 
610  if (not synchronized) // Synchronize only once.
611  {
613 
614  const armarx::DateTime timestamp = armarx::Clock::Now();
615 
616  ARMARX_CHECK(robots.reader->synchronizeRobot(*agent, timestamp));
617  synchronized = true;
618  }
619  objectPose.updateAttached(agent);
620  }
621 
623  Segment::getLatestObjectPoses() const
624  {
625  ARMARX_CHECK_NOT_NULL(segmentPtr);
626  return getLatestObjectPoses(*segmentPtr);
627  }
628 
630  Segment::getLatestObjectPoses(const wm::CoreSegment& coreSeg)
631  {
632  ObjectPoseMap result;
633  getLatestObjectPoses(coreSeg, result);
634  return result;
635  }
636 
638  Segment::getLatestObjectPoses(const wm::ProviderSegment& provSeg)
639  {
640  ObjectPoseMap result;
641  getLatestObjectPoses(provSeg, result);
642  return result;
643  }
644 
646  Segment::getLatestObjectPose(const wm::Entity& entity)
647  {
648  ObjectPose result;
649  getLatestObjectPose(entity, result);
650  return result;
651  }
652 
653  void
654  Segment::getLatestObjectPoses(const wm::CoreSegment& coreSeg, ObjectPoseMap& out)
655  {
656  coreSeg.forEachProviderSegment([&out](const wm::ProviderSegment& provSegment)
657  { getLatestObjectPoses(provSegment, out); });
658  }
659 
660  void
661  Segment::getLatestObjectPoses(const wm::ProviderSegment& provSegment, ObjectPoseMap& out)
662  {
663  provSegment.forEachEntity(
664  [&out](const wm::Entity& entity)
665  {
666  if (!entity.empty())
667  {
668  ObjectPose pose = getLatestObjectPose(entity);
669  // Try to insert. Fails and returns false if an entry already exists.
670  const auto [it, success] = out.insert({pose.objectID, pose});
671  if (!success)
672  {
673  // An entry with that ID already exists. We keep the newest.
674  if (it->second.timestamp < pose.timestamp)
675  {
676  it->second = pose;
677  }
678  }
679  }
680  });
681  }
682 
683  void
684  Segment::getLatestObjectPose(const wm::Entity& entity, ObjectPose& out)
685  {
686  entity.getLatestSnapshot().forEachInstance(
687  [&out](const wm::EntityInstance& instance)
688  {
689  arondto::ObjectInstance dto;
690  dto.fromAron(instance.data());
691 
692  fromAron(dto, out);
693  });
694  }
695 
696  arondto::ObjectInstance
697  Segment::getLatestInstanceData(const wm::Entity& entity)
698  {
699  ARMARX_CHECK_GREATER_EQUAL(entity.size(), 1);
700  const wm::EntitySnapshot& snapshot = entity.getLatestSnapshot();
701 
702  ARMARX_CHECK_EQUAL(snapshot.size(), 1);
703  const wm::EntityInstance& instance = snapshot.getInstance(0);
704 
705  arondto::ObjectInstance data;
706  data.fromAron(instance.data());
707 
708  return data;
709  }
710 
712  Segment::getArticulatedObjects()
713  {
714  objpose::ObjectPoseMap objectPoses = getObjectPoses(Time::Now());
715 
716  ARMARX_INFO << "Found " << objectPoses.size() << " object poses";
717 
719  for (const auto& [objectId, objectPose] : objectPoses)
720  {
722  articulatedObject.config.jointMap = objectPose.objectJointValues;
723  articulatedObject.config.globalPose = objectPose.objectPoseGlobal;
724  articulatedObject.config.timestamp = objectPose.timestamp;
725  articulatedObject.instance = objectPose.objectID.instanceName();
726  articulatedObject.timestamp = objectPose.timestamp;
727 
728  ARMARX_INFO << "Object id is " << objectId.str();
729  ARMARX_INFO << "Object id for objectPose is " << objectPose.objectID.str();
730 
731  // Search for object class.
732  if (auto classInstance = findClassInstance(objectPose.objectID))
733  {
734  arondto::ObjectClass dto;
735 
736  try
737  {
738  dto.fromAron(classInstance->data());
740 
741  fromAron(dto, description);
742  articulatedObject.description = description;
743  }
744  catch (...)
745  {
746  ARMARX_WARNING << "Conversion failed!";
747  continue;
748  }
749  }
750  else
751  {
752  ARMARX_WARNING << "Class instance not found!";
753  continue;
754  }
755 
756  if (not articulatedObject.config.jointMap.empty())
757  {
758  objects.push_back(articulatedObject);
759  }
760  }
761 
762  return objects;
763  }
764 
765  std::map<DateTime, objpose::ObjectPose>
766  Segment::getObjectPosesInRange(const wm::Entity& entity,
767  const DateTime& start,
768  const DateTime& end)
769  {
770  std::map<DateTime, objpose::ObjectPose> result;
771 
773  start,
774  end,
775  [&result](const wm::EntitySnapshot& snapshot)
776  {
777  snapshot.forEachInstance(
778  [&result, &snapshot](const wm::EntityInstance& instance)
779  {
780  arondto::ObjectInstance dto;
781  dto.fromAron(instance.data());
782 
783  ObjectPose pose;
784  fromAron(dto, pose);
785 
786  result.emplace(snapshot.time(), pose);
787  });
788  });
789 
790  return result;
791  }
792 
793  std::optional<simox::OrientedBoxf>
794  Segment::getObjectOOBB(const ObjectID& id)
795  {
796  return oobbCache.get(id);
797  }
798 
799  objpose::ProviderInfo
800  Segment::getProviderInfo(const std::string& providerName)
801  {
802  try
803  {
804  return providers.at(providerName);
805  }
806  catch (const std::out_of_range&)
807  {
808  std::stringstream ss;
809  ss << "No provider with name '" << providerName << "' available.\n";
810  ss << "Available are:\n";
811  for (const auto& [name, _] : providers)
812  {
813  ss << "- '" << name << "'\n";
814  }
815  throw std::out_of_range(ss.str());
816  }
817  }
818 
819  objpose::AttachObjectToRobotNodeOutput
820  Segment::attachObjectToRobotNode(const objpose::AttachObjectToRobotNodeInput& input)
821  {
822  const armem::Time now = armem::Time::Now();
823 
824  objpose::AttachObjectToRobotNodeOutput output;
825  output.success = false; // We are not successful until proven otherwise.
826 
827  ObjectID objectID = armarx::fromIce(input.objectID);
828 
829  VirtualRobot::RobotPtr agent = robots.get(input.agentName);
830  if (not agent)
831  {
832  std::stringstream ss;
833  ss << "Tried to attach object " << objectID << " to unknown agent '" << input.agentName
834  << "'."
835  << "\n(You can leave the agent name empty if there is only one agent.)\n"
836  << "\nKnown agents: ";
837  for (const auto& [name, robot] : robots.loaded)
838  {
839  ss << "\n- '" << name << "'";
840  }
841  ARMARX_WARNING << ss.str();
842  return output;
843  }
844  ARMARX_CHECK_NOT_NULL(agent);
845 
846  if (!agent->hasRobotNode(input.frameName))
847  {
848  ARMARX_WARNING << "Tried to attach object " << objectID << " to unknown node '"
849  << input.frameName << "' of agent '" << agent->getName() << "'.";
850  return output;
851  }
852  std::string frameName = input.frameName;
853 
854 
855  // Find object pose (provider name can be empty).
856  wm::Entity* objectEntity = this->findObjectEntity(objectID, input.providerName);
857  if (!objectEntity || objectEntity->empty())
858  {
859  ARMARX_WARNING << "Tried to attach object " << objectID << " to node '" << frameName
860  << "' of agent '" << agent->getName()
861  << "', but object is currently not provided.";
862  return output;
863  }
864  arondto::ObjectInstance data = getLatestInstanceData(*objectEntity);
865 
867  info.agentName = agent->getName();
868  info.frameName = frameName;
869 
870  if (input.poseInFrame)
871  {
872  info.poseInFrame = PosePtr::dynamicCast(input.poseInFrame)->toEigen();
873  }
874  else
875  {
877 
878  const auto timestamp = armarx::Clock::Now();
879  ARMARX_CHECK(robots.reader->synchronizeRobot(*agent, timestamp));
880 
881  armarx::FramedPose framed(
882  data.pose.objectPoseGlobal, armarx::GlobalFrame, agent->getName());
883  if (frameName == armarx::GlobalFrame)
884  {
885  info.poseInFrame = framed.toGlobalEigen(agent);
886  }
887  else
888  {
889  framed.changeFrame(agent, info.frameName);
890  info.poseInFrame = framed.toEigen();
891  }
892  }
893 
894  // Store attachment in new entity snapshot.
895  {
896  armem::Commit commit;
897  armem::EntityUpdate& update = commit.add();
898  update.entityID = objectEntity->id();
899  update.referencedTime = now;
900  {
901  arondto::ObjectInstance updated = data;
902  toAron(updated.pose.attachment, info);
903  updated.pose.attachmentValid = true;
904  update.instancesData = {updated.toAron()};
905  }
906  iceMemory.commit(commit);
907  }
908 
909  ARMARX_INFO << "Attached object " << objectID << " by provider '" << data.pose.providerName
910  << "' "
911  << "to node '" << info.frameName << "' of agent '" << info.agentName << "'.\n"
912  << "Object pose in frame: \n"
913  << info.poseInFrame;
914 
915  output.success = true;
916  output.attachment = new objpose::data::ObjectAttachmentInfo();
917  output.attachment->frameName = info.frameName;
918  output.attachment->agentName = info.agentName;
919  output.attachment->poseInFrame = new Pose(info.poseInFrame);
920 
921  return output;
922  }
923 
924  objpose::DetachObjectFromRobotNodeOutput
925  Segment::detachObjectFromRobotNode(const objpose::DetachObjectFromRobotNodeInput& input)
926  {
927  const armem::Time now = armem::Time::Now();
928 
929  ObjectID objectID = armarx::fromIce(input.objectID);
930  std::string providerName = input.providerName;
931 
932  std::optional<objpose::arondto::ObjectAttachmentInfo> attachment;
933  {
934  // Remove from latest pose (if it was cached).
935  // Find object pose (provider name can be empty).
936  wm::Entity* entity = this->findObjectEntity(objectID, input.providerName);
937  if (entity)
938  {
939  const arondto::ObjectInstance data = getLatestInstanceData(*entity);
940  if (data.pose.attachmentValid)
941  {
942  attachment = data.pose.attachment;
943 
944  // Store non-attached pose in new snapshot.
945  storeDetachedSnapshot(*entity, data, now, input.commitAttachedPose);
946  }
947  if (providerName.empty())
948  {
949  providerName = data.pose.providerName;
950  }
951  }
952  }
953 
954  objpose::DetachObjectFromRobotNodeOutput output;
955  output.wasAttached = bool(attachment);
956  if (attachment)
957  {
958  ARMARX_INFO << "Detached object " << objectID << " by provider '" << providerName
959  << "' from robot node '" << attachment->frameName << "' of agent '"
960  << attachment->agentName << "'.";
961  }
962  else
963  {
964  ARMARX_INFO << "Tried to detach object " << objectID << " by provider '" << providerName
965  << "' "
966  << "from robot node, but it was not attached.";
967  }
968 
969  return output;
970  }
971 
972  objpose::DetachAllObjectsFromRobotNodesOutput
973  Segment::detachAllObjectsFromRobotNodes(
974  const objpose::DetachAllObjectsFromRobotNodesInput& input)
975  {
976  ARMARX_CHECK_NOT_NULL(segmentPtr);
977 
978  const armem::Time now = armem::Time::Now();
979 
980  objpose::DetachAllObjectsFromRobotNodesOutput output;
981  output.numDetached = 0;
982  segmentPtr->forEachEntity(
983  [this, now, &input, &output](wm::Entity& entity)
984  {
985  const arondto::ObjectInstance data = this->getLatestInstanceData(entity);
986  if (data.pose.attachmentValid)
987  {
988  ++output.numDetached;
989  // Store non-attached pose in new snapshot.
990  this->storeDetachedSnapshot(entity, data, now, input.commitAttachedPose);
991  }
992  });
993 
994  ARMARX_INFO << "Detached all objects (" << output.numDetached << ") from robot nodes.";
995 
996  return output;
997  }
998 
999  void
1000  Segment::storeDetachedSnapshot(wm::Entity& entity,
1001  const arondto::ObjectInstance& data,
1002  Time now,
1003  bool commitAttachedPose)
1004  {
1005  armem::Commit commit;
1006  armem::EntityUpdate& update = commit.add();
1007  update.entityID = entity.id();
1008  update.referencedTime = now;
1009  {
1010  arondto::ObjectInstance updated;
1011  if (commitAttachedPose and data.pose.attachmentValid)
1012  {
1013  ObjectPose objectPose;
1014  fromAron(data, objectPose);
1015 
1016  VirtualRobot::RobotPtr robot =
1017  robots.get(objectPose.robotName, objectPose.providerName);
1018  bool agentSynchronized = false;
1019  updateAttachement(objectPose, robot, agentSynchronized);
1020 
1021  objectPose.attachment = std::nullopt;
1022  toAron(updated, objectPose);
1023  }
1024  else
1025  {
1026  updated = data;
1027  updated.pose.attachmentValid = false;
1028  toAron(updated.pose.attachment, objpose::ObjectAttachmentInfo{});
1029  }
1030 
1031  update.instancesData = {updated.toAron()};
1032  }
1033  iceMemory.commit(commit);
1034  }
1035 
1036  std::optional<wm::EntityInstance>
1037  Segment::findClassInstance(const ObjectID& objectID) const
1038  {
1039  const ObjectID classID = {objectID.dataset(), objectID.className()};
1040  try
1041  {
1042  std::optional<wm::EntityInstance> result;
1043  iceMemory.workingMemory->getCoreSegment("Class").forEachProviderSegment(
1044  [&classID, &result](const wm::ProviderSegment& provSeg)
1045  {
1046  if (provSeg.hasEntity(classID.str()))
1047  {
1048  result =
1049  provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0);
1050  return false;
1051  }
1052  return true;
1053  });
1054 
1055  if (not result.has_value())
1056  {
1057  ARMARX_WARNING << deactivateSpam(120) << "No provider segment for classID "
1058  << classID.str() << " found";
1059  }
1060  return result;
1061  }
1062  catch (const armem::error::ArMemError& e)
1063  {
1064  // Some segment or entity did not exist.
1065  ARMARX_WARNING << e.what();
1066  return std::nullopt;
1067  }
1068  }
1069 
1070  void
1071  Segment::storeScene(const std::string& filename, const armarx::objects::Scene& scene)
1072  {
1073  if (const std::optional<std::filesystem::path> path = resolveSceneFilepath(filename))
1074  {
1075  ARMARX_INFO << "Storing scene snapshot at: \n" << path.value();
1076  try
1077  {
1078  simox::json::write(path.value(), scene, 2);
1079  }
1080  catch (const simox::json::error::JsonError& e)
1081  {
1082  ARMARX_WARNING << "Storing scene snapshot failed: \n" << e.what();
1083  }
1084  }
1085  }
1086 
1087  std::optional<armarx::objects::Scene>
1088  Segment::loadScene(const std::string& filename)
1089  {
1090  if (const std::optional<std::filesystem::path> path = resolveSceneFilepath(filename))
1091  {
1092  return loadScene(path.value());
1093  }
1094  else
1095  {
1096  return std::nullopt;
1097  }
1098  }
1099 
1100  std::optional<armarx::objects::Scene>
1101  Segment::loadScene(const std::filesystem::path& path)
1102  {
1103  try
1104  {
1105  ARMARX_CHECK(std::filesystem::exists(path)) << path;
1106  return simox::json::read<armarx::objects::Scene>(path);
1107  }
1108  catch (const simox::json::error::JsonError& e)
1109  {
1110  ARMARX_WARNING << "Loading scene snapshot failed: \n" << e.what();
1111  return std::nullopt;
1112  }
1113  }
1114 
1115  const std::string Segment::timestampPlaceholder = "%TIMESTAMP";
1116 
1117  std::optional<std::filesystem::path>
1118  Segment::resolveSceneFilepath(const std::string& _filename)
1119  {
1120  std::stringstream log;
1121  std::filesystem::path filepath = _filename;
1122 
1123  filepath = simox::alg::replace_all(
1124  filepath, timestampPlaceholder, Time::Now().toString("%Y-%m-%d_%H-%M-%S"));
1125  if (not simox::alg::ends_with(filepath, ".json"))
1126  {
1127  filepath += ".json";
1128  }
1129 
1130  if (filepath.is_absolute())
1131  {
1132  return filepath;
1133  }
1134 
1135  armarx::PackagePath packagePath = [&filepath, this]()
1136  {
1137  if (filepath.has_parent_path())
1138  {
1139  // Interpret the first component as package name.
1140  std::string packageName = *filepath.begin();
1141  return PackagePath(packageName, std::filesystem::relative(filepath, packageName));
1142  }
1143  else
1144  {
1145  // Only a filename => Interprete it as relative to 'Package/scenes/'.
1146  return PackagePath(p.sceneSnapshotsPackage, p.sceneSnapshotsDirectory / filepath);
1147  }
1148  }();
1149 
1150  try
1151  {
1152  std::filesystem::path systemPath = packagePath.toSystemPath();
1153  return systemPath;
1154  }
1155  catch (const armarx::PackageNotFoundException& e)
1156  {
1157  ARMARX_INFO << "Could not interpret '" << packagePath.serialize().package
1158  << "' as ArmarX package name (" << e.what() << ").";
1159  return std::nullopt;
1160  }
1161  }
1162 
1164  Segment::getSceneSnapshot() const
1165  {
1167 
1168  // We only store the latest version of each objectID.
1169 
1170  struct StampedSceneObject
1171  {
1172  SceneObject object;
1173  Time timestamp;
1174  };
1175 
1176  std::map<ObjectID, StampedSceneObject> objects;
1177  segmentPtr->forEachEntity(
1178  [&objects](wm::Entity& entity)
1179  {
1180  const wm::EntityInstance* entityInstance = entity.findLatestInstance();
1181  if (entityInstance)
1182  {
1183  std::optional<arondto::ObjectInstance> objectInstance =
1184  tryCast<arondto::ObjectInstance>(*entityInstance);
1185  if (objectInstance)
1186  {
1187  const ObjectID objectID =
1188  ObjectID::FromString(objectInstance->classID.entityName);
1189 
1190  auto it = objects.find(objectID);
1191  if (it == objects.end() or
1192  objectInstance->pose.timestamp > it->second.timestamp)
1193  {
1194  StampedSceneObject& stamped = objects[objectID];
1195  stamped.timestamp = objectInstance->pose.timestamp;
1196 
1197  SceneObject& object = stamped.object;
1198  object.className = objectID.getClassID().str();
1199  object.instanceName = objectID.instanceName();
1200  object.collection = "";
1201 
1202  object.position =
1203  simox::math::position(objectInstance->pose.objectPoseGlobal);
1204  object.orientation =
1205  simox::math::orientation(objectInstance->pose.objectPoseGlobal);
1206 
1207  object.isStatic = objectInstance->pose.isStatic;
1208  object.jointValues = objectInstance->pose.objectJointValues;
1209  }
1210  }
1211  }
1212  });
1213 
1214  armarx::objects::Scene scene;
1215  for (const auto& [id, stamped] : objects)
1216  {
1217  scene.objects.emplace_back(std::move(stamped.object));
1218  }
1219  return scene;
1220  }
1221 
1222  void
1223  Segment::commitSceneSnapshot(const armarx::objects::Scene& scene, const std::string& sceneName)
1224  {
1225  const Time now = Time::Now();
1226  std::map<ObjectID, int> idCounters;
1227 
1228  objpose::ObjectPoseSeq objectPoses;
1229 
1230  for (const auto& object : scene.objects)
1231  {
1232  if (simox::alg::starts_with(object.className, "#"))
1233  {
1234  // marked to be ignored
1235  continue;
1236  }
1237 
1238  const ObjectID classID = object.getClassID(objectFinder);
1239 
1240  objpose::ObjectPose& pose = objectPoses.emplace_back();
1241 
1242  pose.providerName = sceneName;
1243  pose.objectType = objpose::ObjectType::KnownObject;
1244  // If not specified, assume loaded objects are static.
1245  pose.isStatic = object.isStatic.has_value() ? object.isStatic.value() : true;
1246  pose.objectID = classID.withInstanceName(object.instanceName.empty()
1247  ? std::to_string(idCounters[classID]++)
1248  : object.instanceName);
1249 
1250  pose.objectPoseGlobal = simox::math::pose(object.position, object.orientation);
1251  pose.objectPoseRobot = pose.objectPoseGlobal;
1252  pose.objectPoseOriginal = pose.objectPoseGlobal;
1253  pose.objectPoseOriginalFrame = armarx::GlobalFrame;
1254 
1255  pose.objectJointValues = object.jointValues;
1256 
1257  pose.robotConfig = {};
1258  pose.robotPose = Eigen::Matrix4f::Identity();
1259  pose.robotName = "";
1260 
1261  pose.confidence = 1.0;
1262  pose.localOOBB = getObjectOOBB(classID);
1263  pose.timestamp = now;
1264  }
1265 
1266  commitObjectPoses(objectPoses);
1267  }
1268 
1269  void
1270  Segment::commitSceneSnapshotFromFilename(const std::string& filename, bool lockMemory)
1271  {
1272  std::stringstream ss;
1273  ss << "Loading scene '" << filename << "' ...";
1274  if (std::optional<std::filesystem::path> path = resolveSceneFilepath(filename))
1275  {
1276  ARMARX_INFO << ss.str() << "\nfrom " << path.value();
1277 
1278  if (const auto snapshot = loadScene(path.value()))
1279  {
1280  auto makeSceneName = [](const std::filesystem::path& path)
1281  {
1282  std::filesystem::path filename = path.filename();
1283  filename.replace_extension(); // Removes extension
1284  return filename.string();
1285  };
1286  std::string sceneName = makeSceneName(path.value());
1287 
1288  // The check seems useless?
1289  if (lockMemory)
1290  {
1291  segmentPtr->doLocked([this, &snapshot, &sceneName]()
1292  { commitSceneSnapshot(snapshot.value(), sceneName); });
1293  }
1294  else
1295  {
1296  commitSceneSnapshot(snapshot.value(), sceneName);
1297  }
1298  }
1299  }
1300  else
1301  {
1302  ARMARX_INFO << ss.str() << " failed: Could not resolve scene name or path.";
1303  }
1304  }
1305 
1306  void
1307  Segment::RemoteGui::setup(const Segment& data)
1308  {
1309  using namespace armarx::RemoteGui::Client;
1310 
1311  maxHistorySize.setValue(std::max(1, int(data.properties.maxHistorySize)));
1312  maxHistorySize.setRange(1, 1e6);
1313  infiniteHistory.setValue(data.properties.maxHistorySize == -1);
1314  discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
1315 
1316  const std::string storeLoadPath = [&data]()
1317  {
1318  const std::vector<std::string> scenes = data.p.getSceneSnapshotsToLoad();
1319  if (scenes.empty())
1320  {
1321  std::string storeLoadFilename = "Scene_" + timestampPlaceholder;
1322  return data.p.sceneSnapshotsPackage + "/" + data.p.sceneSnapshotsToLoad;
1323  }
1324  else
1325  {
1326  return scenes.front();
1327  }
1328  }();
1329 
1330  storeLoadLine.setValue(storeLoadPath);
1331  loadButton.setLabel("Load Scene");
1332  storeButton.setLabel("Store Scene");
1333 
1334  HBoxLayout storeLoadLineLayout({storeLoadLine, Label(".json")});
1335  HBoxLayout storeLoadButtonsLayout({loadButton, storeButton});
1336 
1337  detachAllObjectsButton.setLabel("Detach All Objects");
1338  detachAllObjectsCommitAttachedPoseCheckBox.setValue(true);
1339  HBoxLayout detachAllObjectsCommitAttachedPoseLayout(
1340  {Label("Commit Attached Pose"), detachAllObjectsCommitAttachedPoseCheckBox});
1341 
1342 
1343  GridLayout grid;
1344  int row = 0;
1345 
1346  grid.add(storeLoadLineLayout, {row, 0}, {1, 2});
1347  row++;
1348  grid.add(storeLoadButtonsLayout, {row, 0}, {1, 2});
1349  row++;
1350 
1351  grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
1352  row++;
1353  grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
1354  row++;
1355  grid.add(Label("Discard Snapshots while Attached"), {row, 0})
1356  .add(discardSnapshotsWhileAttached, {row, 1});
1357  row++;
1358 
1359  grid.add(detachAllObjectsButton, {row, 0})
1360  .add(detachAllObjectsCommitAttachedPoseLayout, {row, 1});
1361 
1362  group.setLabel("Data");
1363  group.addChild(grid);
1364  }
1365 
1366  void
1368  {
1369  if (loadButton.wasClicked())
1370  {
1371  bool lockMemory = true;
1372  segment.commitSceneSnapshotFromFilename(storeLoadLine.getValue(), lockMemory);
1373  }
1374 
1375  if (storeButton.wasClicked())
1376  {
1377  armarx::objects::Scene scene;
1378  segment.doLocked([&scene, &segment]() { scene = segment.getSceneSnapshot(); });
1379  segment.storeScene(storeLoadLine.getValue(), scene);
1380  }
1381 
1382  if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() ||
1383  discardSnapshotsWhileAttached.hasValueChanged())
1384  {
1385  segment.doLocked(
1386  [this, &segment]()
1387  {
1388  if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
1389  {
1390  segment.properties.maxHistorySize =
1391  infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
1392  if (segment.segmentPtr)
1393  {
1394  segment.segmentPtr->setMaxHistorySize(
1395  long(segment.properties.maxHistorySize));
1396  }
1397  }
1398 
1399  segment.p.discardSnapshotsWhileAttached =
1400  discardSnapshotsWhileAttached.getValue();
1401  });
1402  }
1403 
1404  if (detachAllObjectsButton.wasClicked())
1405  {
1406  objpose::DetachAllObjectsFromRobotNodesInput input;
1407  input.commitAttachedPose = detachAllObjectsCommitAttachedPoseCheckBox.getValue();
1408 
1409  objpose::DetachAllObjectsFromRobotNodesOutput output = segment.doLocked(
1410  [&segment, &input]() { return segment.detachAllObjectsFromRobotNodes(input); });
1411  (void)output;
1412  }
1413  }
1414 
1416  Segment::RobotsCache::get(const std::string& _robotName, const std::string& providerName)
1417  {
1418  std::string robotName = _robotName;
1419 
1420  if (robotName.empty())
1421  {
1422  auto antiSpam = deactivateSpam(10 * 60); // 10 minutes.
1423 
1424  std::stringstream ss;
1425  if (providerName.empty())
1426  {
1427  ss << "The provided object pose";
1428  }
1429  else
1430  {
1431  ss << "The object pose provided by '" << providerName << "'";
1432  }
1433  ss << " does not specify a robot name";
1434 
1435  if (fallbackName.empty())
1436  {
1437  ss << ", and no fallback robot name was configured (e.g. via the properties).\n"
1438  << "For these object poses, the object instance segment is not able "
1439  << "to provide transformed object poses (global and in robot root frame).";
1440  ARMARX_INFO << antiSpam << ss.str();
1441 
1442  return nullptr;
1443  }
1444  else
1445  {
1446  ss << ". The object instance segment is falling back to '" << fallbackName << "'.";
1447  ARMARX_INFO << antiSpam << ss.str();
1448 
1449  robotName = fallbackName;
1450  }
1451  }
1452  ARMARX_CHECK_NOT_EMPTY(robotName);
1453 
1454  // Lookup in cache.
1455  if (auto it = loaded.find(robotName); it != loaded.end())
1456  {
1457  ARMARX_CHECK_NOT_NULL(it->second);
1458  return it->second;
1459  }
1460  else
1461  {
1462  // Try to fetch the robot.
1463  ARMARX_CHECK_NOT_NULL(reader);
1464  VirtualRobot::RobotPtr robot = reader->getRobot(
1465  robotName, Clock::Now(), VirtualRobot::RobotIO::RobotDescription::eStructure);
1466 
1467  if (robot)
1468  {
1469  bool synchronized = reader->synchronizeRobot(*robot, Clock::Now());
1470  if (not synchronized)
1471  {
1472  ARMARX_INFO << "The robot '" << robotName << "' could be loaded, but not"
1473  << " synchronized successfully (e.g., the global localization "
1474  "could be missing). "
1475  << "Make sure to synchronize it before use if necessary.";
1476  }
1477  // Store robot if valid.
1478  loaded.emplace(robotName, robot);
1479  }
1480  return robot; // valid or nullptr
1481  }
1482  }
1483 
1484 
1485 } // namespace armarx::armem::server::obj::instance
memory_ids.h
armarx::SimpleRunningTask
Usage:
Definition: TaskUtil.h:70
RemoteRobot.h
armarx::armem::base::detail::MemoryContainerBase::empty
bool empty() const
Definition: MemoryContainerBase.h:44
armarx::navigation::graph::coreSegmentID
const armem::MemoryID coreSegmentID
Definition: constants.h:30
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::armem::base::EntitySnapshotBase::getInstance
EntityInstanceT & getInstance(int index)
Get the given instance.
Definition: EntitySnapshotBase.h:114
armarx::armem::server::wm::EntityInstance
armem::wm::EntityInstance EntityInstance
Definition: forward_declarations.h:64
ice_conversions.h
armarx::ObjectID
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition: ObjectID.h:11
armarx::armem::robot_state::description::RobotDescription
Definition: types.h:44
Writer.h
armarx::objpose::ObjectPoseSeq
std::vector< ObjectPose > ObjectPoseSeq
Definition: forward_declarations.h:20
armarx::ObjectID::FromString
static ObjectID FromString(const std::string &idString)
Construct from a string produced by str(), e.g. ("mydataset/myobject", "mydataset/myclass/myinstance"...
Definition: ObjectID.cpp:31
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::armem::Commit
A bundle of updates to be sent to the memory.
Definition: Commit.h:89
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::armem::robot_state::Robot
Definition: types.h:126
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::FramedPose
The FramedPose class.
Definition: FramedPose.h:258
robots
std::vector< VirtualRobot::RobotPtr > robots
Definition: VisualizationRobot.cpp:85
armarx::armem::server::MemoryToIceAdapter
Helps connecting a Memory server to the Ice interface.
Definition: MemoryToIceAdapter.h:19
armarx::objects::Scene::objects
std::vector< SceneObject > objects
Definition: Scene.h:58
armarx::armem::attachment::ObjectID
armem::MemoryID ObjectID
Definition: types.h:79
armarx::armem::base::detail::GetLatestSnapshotMixin::getLatestSnapshot
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
Definition: lookup_mixins.h:199
armarx::armem::base::EntitySnapshotBase::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: EntitySnapshotBase.h:178
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:55
armarx::armem::server::segment::SpecializedCoreSegment::SpecializedCoreSegment
SpecializedCoreSegment(MemoryToIceAdapter &iceMemory, const std::string &defaultCoreSegmentName="", aron::type::ObjectPtr coreSegmentAronType=nullptr, int defaultMaxHistorySize=10, const std::vector< PredictionEngine > &predictionEngines={})
Definition: SpecializedCoreSegment.cpp:13
DateTime.h
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::RemoteGui::Client::GridLayout::add
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition: Widgets.cpp:412
armarx::armem::objects::instaceSegmentID
const MemoryID instaceSegmentID
Definition: memory_ids.cpp:33
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:62
armarx::armem::toAron
void toAron(arondto::MemoryID &dto, const MemoryID &bo)
Definition: aron_conversions.cpp:19
Segment.h
armarx::armem::server::obj::instance::Segment::Calibration::offset
float offset
Definition: Segment.h:51
armarx::armem::server::obj::instance::Segment::objectFinder
ObjectFinder objectFinder
Definition: Segment.h:183
armarx::PackageNotFoundException
Definition: PackagePath.h:42
armarx::objpose::ObjectAttachmentInfo::agentName
std::string agentName
Definition: ObjectPose.h:28
query_fns.h
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
ice_conversions.h
armarx::armem::robot_state::RobotState::jointMap
JointMap jointMap
Definition: types.h:121
armarx::armem::robot_state::RobotState::timestamp
DateTime timestamp
Definition: types.h:118
armarx::objpose::ObjectAttachmentInfo::frameName
std::string frameName
Definition: ObjectPose.h:27
armarx::armem::server::obj::instance::Segment::Calibration::robotName
std::string robotName
Definition: Segment.h:49
armarx::starts_with
bool starts_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:43
Scene.h
armarx::objects::SceneObject
Definition: Scene.h:38
armarx::armem::server::wm::Entity
Definition: memory_definitions.h:30
armarx::armem::server::obj::instance::Segment::Calibration::robotNode
std::string robotNode
Definition: Segment.h:50
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
Clock.h
armarx::armem::Commit::updates
std::vector< EntityUpdate > updates
The entity updates.
Definition: Commit.h:97
armarx::armem::server::obj::instance
Definition: ArticulatedObjectVisu.cpp:16
armarx::PackagePath::serialize
data::PackagePath serialize() const
Definition: PackagePath.cpp:76
armarx::armem::base::detail::MemoryContainerBase::size
std::size_t size() const
Definition: MemoryContainerBase.h:48
armarx::armem::robot_state::Robot::timestamp
DateTime timestamp
Definition: types.h:133
visionx::voxelgrid::Label
uint32_t Label
Type of an object label.
Definition: types.h:7
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
armarx::RemoteGui::Client::GridLayout
Definition: Widgets.h:186
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::armem::MemoryID::withProviderSegmentName
MemoryID withProviderSegmentName(const std::string &name) const
Definition: MemoryID.cpp:412
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::FramedPose::toGlobalEigen
Eigen::Matrix4f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
Definition: FramedPose.cpp:517
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
json_conversions.h
copy
Use of this software is granted under one of the following two to be chosen freely by the user Boost Software License Version Marcin Kalicinski Permission is hereby free of to any person or organization obtaining a copy of the software and accompanying documentation covered by this and transmit the and to prepare derivative works of the and to permit third parties to whom the Software is furnished to do all subject to the including the above license this restriction and the following must be included in all copies of the in whole or in and all derivative works of the unless such copies or derivative works are solely in the form of machine executable object code generated by a source language processor THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF FITNESS FOR A PARTICULAR TITLE AND NON INFRINGEMENT IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN TORT OR ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE The MIT Marcin Kalicinski Permission is hereby free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to copy
Definition: license.txt:39
armarx::objpose::ObjectAttachmentInfo::poseInFrame
Eigen::Matrix4f poseInFrame
Definition: ObjectPose.h:29
FramedPose.h
armarx::PackagePath::toSystemPath
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
Definition: PackagePath.cpp:54
armarx::armem::base::ProviderSegmentBase::hasEntity
bool hasEntity(const std::string &name) const
Definition: ProviderSegmentBase.h:108
armarx::armem::robot_state::Robot::config
RobotState config
Definition: types.h:131
armarx::armem::server::obj::instance::Segment::ObjectPoseMap
std::map< ObjectID, ObjectPose > ObjectPoseMap
Definition: Segment.h:45
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::armem::server::segment::SpecializedCoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: SpecializedCoreSegment.h:39
armarx::aron::input
ReaderT::InputType & input
Definition: rw.h:19
armarx::armem::base::CoreSegmentBase::forEachProviderSegment
bool forEachProviderSegment(ProviderSegmentFunctionT &&func)
Definition: CoreSegmentBase.h:217
error.h
armarx::read
void read(auto &eigen, auto *table)
Definition: FTSensorCalibrationGuiWidgetController.cpp:462
armarx::Pose::toEigen
virtual Eigen::Matrix4f toEigen() const
Definition: Pose.cpp:334
armarx::armem::EntityUpdate
An update of an entity for a specific point in time.
Definition: Commit.h:27
aron_conversions.h
armarx::armem::server::obj::instance::Segment::Calibration::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="calibration.")
Definition: Segment.cpp:52
filename
std::string filename
Definition: VisualizationRobot.cpp:83
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::armem::server::obj::instance::Segment::Segment
Segment(server::MemoryToIceAdapter &iceMemory)
Definition: Segment.cpp:62
armarx::armem::robot_state::RobotState::globalPose
Pose globalPose
Definition: types.h:120
armarx::armem::wm::EntitySnapshot
Client-side working memory entity snapshot.
Definition: memory_definitions.h:80
TaskUtil.h
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:27
armarx::armem::server::obj::instance::Segment::CommitStats
Definition: Segment.h:38
ARMARX_CHECK_GREATER_EQUAL
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
Definition: ExpressionException.h:123
armarx::armem::server::wm::ProviderSegment
Definition: memory_definitions.h:60
armarx::armem::robot_state::Robot::instance
std::string instance
Definition: types.h:129
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::armem::MemoryID::entityName
std::string entityName
Definition: MemoryID.h:53
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:67
aron_conversions.h
MemoryToIceAdapter.h
armarx::objpose::ProvidedObjectPoseSeq
std::vector< ProvidedObjectPose > ProvidedObjectPoseSeq
Definition: forward_declarations.h:25
armarx::fromIce
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
Definition: ice_conversions_boost_templates.h:26
armarx::objects::Scene
Definition: Scene.h:56
aron_conversions.h
armarx::RemoteGui::Client::HBoxLayout
Definition: Widgets.h:160
armarx::armem::server::wm::CoreSegment
base::CoreSegmentBase
Definition: memory_definitions.h:86
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::armem::fromAron
void fromAron(const arondto::MemoryID &dto, MemoryID &bo)
Definition: aron_conversions.cpp:8
CMakePackageFinder.h
armarx::objpose::ObjectPose::updateAttached
void updateAttached(VirtualRobot::RobotPtr agent)
Update an the object pose and robot state of an attached object pose according to the given agent sta...
Definition: ObjectPose.cpp:248
aron_conversions.h
armarx::armem::ObjectInstance
Definition: types.h:39
armarx::armem::articulated_object::ArticulatedObjects
armarx::armem::robot_state::Robots ArticulatedObjects
Definition: types.h:141
armarx::armem::MemoryID::withEntityName
MemoryID withEntityName(const std::string &name) const
Definition: MemoryID.cpp:420
armarx::armem::base::EntitySnapshotBase::time
Time & time()
Definition: EntitySnapshotBase.h:59
armarx::armem::Commit::add
EntityUpdate & add()
Definition: Commit.cpp:81
armarx::armem::base::EntityBase::forEachSnapshotInTimeRange
void forEachSnapshotInTimeRange(const Time &min, const Time &max, FunctionT &&func) const
Return all snapshots between, including, min and max.
Definition: EntityBase.h:477
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::armem::base::ProviderSegmentBase::forEachEntity
bool forEachEntity(EntityFunctionT &&func)
Definition: ProviderSegmentBase.h:189
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::ends_with
bool ends_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:50
armarx::ObjectFinder::findObject
std::optional< ObjectInfo > findObject(const std::string &dataset, const std::string &name) const
Definition: ObjectFinder.cpp:65
armarx::viz::toString
const char * toString(InteractionFeedbackType type)
Definition: Interaction.h:27
armarx::objpose::ObjectPose::attachment
std::optional< ObjectAttachmentInfo > attachment
Attachment information.
Definition: ObjectPose.h:95
Builder.h
armarx::Logging::tag
LogTag tag
Definition: Logging.h:271
armarx::aron::write
requires data::isWriter< WriterT > void write(WriterT &aron_w, const Eigen::Matrix< EigenT, rows, cols, options > &input, typename WriterT::ReturnType &ret, const armarx::aron::Path &aron_p=armarx::aron::Path())
Definition: eigen.h:134
armarx::armem::server::obj::instance::Segment::ObjectPoseSeq
objpose::ObjectPoseSeq ObjectPoseSeq
Definition: Segment.h:44
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:97
ice_conversions_templates.h
util.h
armarx::armem::server::obj::instance::Segment
Definition: Segment.h:35
Logging.h
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
aron_conversions.h
armarx::armem::base::ProviderSegmentBase::getEntity
EntityT & getEntity(const std::string &name)
Definition: ProviderSegmentBase.h:135
armarx::armem::base::EntityInstanceBase::data
const DataT & data() const
Definition: EntityInstanceBase.h:129
armarx::viz::Client
Definition: Client.h:109
armarx::objpose::ObjectAttachmentInfo
Definition: ObjectPose.h:25
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
armarx::PackagePath
Definition: PackagePath.h:55
aron_conversions.h
armarx::armem::server::obj::instance::Segment::CommitStats::numUpdated
int numUpdated
Definition: Segment.h:40
armarx::core::time::DateTime::Invalid
static DateTime Invalid()
Definition: DateTime.cpp:60
armarx::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:36
armarx::status::success
@ success
armarx::FramedPose::changeFrame
void changeFrame(const SharedRobotInterfacePrx &referenceRobot, const std::string &newFrame)
Definition: FramedPose.cpp:406
armarx::ObjectID::str
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
Definition: ObjectID.cpp:55
armarx::armem::robot_state::Robot::description
description::RobotDescription description
Definition: types.h:128
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18
ObjectFinder.h
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
armarx::objpose::ObjectPoseMap
std::map< ObjectID, ObjectPose > ObjectPoseMap
Definition: forward_declarations.h:21
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:29