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