6 #include <Eigen/Geometry>
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>
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>
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.");
64 [
this](
const ObjectID&
id) -> std::optional<simox::OrientedBoxf>
71 objectInfo->setLogError(false);
72 return objectInfo->loadOOBB();
74 catch (
const std::ios_base::failure& e)
88 classNameToDatasetCache.setFetchFn(
89 [
this](
const std::string& className)
91 std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className);
92 return objectInfo ? objectInfo->dataset() :
"";
103 SpecializedCoreSegment::defineProperties(defs, prefix);
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.");
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.");
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.");
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' "
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'",
136 defs->optional(p.sceneSnapshotsToLoad,
137 prefix +
"scene.12_SnapshotToLoad",
138 simox::alg::join(sceneSnapshotToLoadDescription,
" \n"));
140 decay.defineProperties(defs, prefix +
"decay.");
143 std::vector<std::string>
144 Segment::Properties::getSceneSnapshotsToLoad()
const
146 if (sceneSnapshotsToLoad.empty())
157 SpecializedCoreSegment::init();
159 const std::vector<std::string> scenes = p.getSceneSnapshotsToLoad();
160 for (
const std::string& scene : scenes)
162 const bool lockMemory =
false;
163 commitSceneSnapshotFromFilename(scene, lockMemory);
179 Segment::commitObjectPoses(
const std::string& providerName,
181 const Calibration& calibration,
182 std::optional<armem::Time> discardUpdatesUntil)
193 for (
const objpose::data::ProvidedObjectPose& provided : providedPoses)
195 const Time timestamp = armarx::fromIce<Time>(provided.timestamp);
198 std::optional<objpose::ObjectPose> previousPose;
203 const arondto::ObjectInstance
data = getLatestInstanceData(*entity);
209 bool discard =
false;
210 if (discardUpdatesUntil && timestamp < discardUpdatesUntil.value())
215 else if (previousPose)
217 if (p.discardSnapshotsWhileAttached && previousPose->attachment)
222 else if (timestamp == previousPose->timestamp)
241 << provided.robotName <<
"`.";
246 bool synchronized =
false;
249 if (robot and robotSyncTimestamp != timestamp)
251 synchronized =
robots.reader->synchronizeRobot(*robot, timestamp);
252 if (not
synchronized)
255 << timestamp <<
" of provided object pose (" << provided.objectID
256 <<
"). This is " << (
Clock::Now() - timestamp).toSecondsDouble()
257 <<
" seconds in the past.";
260 robotSyncTimestamp = timestamp;
264 if (calibration.offset != 0 and robot->hasRobotNode(calibration.robotNode))
266 VirtualRobot::RobotNodePtr robotNode =
267 robot->getRobotNode(calibration.robotNode);
269 float value = robotNode->getJointValue();
270 float newValue =
value + calibration.offset;
278 VirtualRobot::RobotNode::JointLimits limits = robotNode->getJointLimits();
279 bool limitsChanged =
false;
280 if (newValue < limits.low)
282 limits.low = newValue;
283 limitsChanged =
true;
285 if (newValue > limits.high)
287 limits.high = newValue;
288 limitsChanged =
true;
292 robotNode->setJointLimits(limits.low, limits.high);
295 robotNode->setJointValue(newValue);
299 else if (robot and timestamp == robotSyncTimestamp)
304 if (not
synchronized)
311 <<
"Robot could not be synchronized; discarding robot";
315 objpose::ObjectPose& newPose = newObjectPoses.emplace_back();
316 if (provided.objectPoseFrame.empty())
318 objpose::data::ProvidedObjectPose
copy = provided;
320 newPose.fromProvidedPose(
copy, robot);
324 newPose.fromProvidedPose(provided, robot);
327 if (previousPose && previousPose->attachment)
331 newPose.attachment = previousPose->attachment;
334 if (newPose.objectID.dataset().empty())
337 const std::string dataset =
338 classNameToDatasetCache.get(newPose.objectID.className());
339 if (!dataset.empty())
342 dataset, newPose.objectID.className(), newPose.objectID.instanceName()};
345 if (!provided.localOOBB)
348 newPose.localOOBB = getObjectOOBB(newPose.objectID);
352 commitObjectPoses(newObjectPoses, providerName);
358 Segment::commitObjectPoses(
const ObjectPoseSeq& objectPoses,
const std::string& providerName)
371 providerName.empty() ? pose.providerName : providerName);
375 update.referencedTime = pose.timestamp;
376 update.confidence = pose.confidence;
378 arondto::ObjectInstance dto;
381 if (
auto instance = findClassInstance(pose.objectID))
383 toAron(dto.classID, instance->id());
390 update.instancesData.push_back(dto.toAron());
393 iceMemory.commit(commit);
400 updateObjectPoses(objectPoses, now);
401 return filterObjectPoses(objectPoses);
405 Segment::getObjectPosesByProvider(
const std::string& providerName,
const DateTime& now)
409 getLatestObjectPoses(segmentPtr->getProviderSegment(providerName));
410 updateObjectPoses(objectPoses, now);
411 return filterObjectPoses(objectPoses);
415 Segment::findObjectEntity(
const ObjectID& objectID,
const std::string& providerName)
419 if (providerName.empty())
422 segmentPtr->forEachProviderSegment(
427 result = &prov.getEntity(entityID);
437 if (segmentPtr->hasProviderSegment(providerName))
452 bool agentSynchronized =
false;
454 for (
auto& [
id, objectPose] : objectPoses)
457 robots.get(objectPose.robotName, objectPose.providerName);
458 updateObjectPose(objectPose, now, robot, agentSynchronized);
466 bool& agentSynchronized)
const
468 for (
auto& [
id, objectPose] : objectPoses)
470 updateObjectPose(objectPose, now, agent, agentSynchronized);
475 Segment::updateObjectPose(ObjectPose& objectPose,
478 bool& agentSynchronized)
const
480 updateAttachement(objectPose, agent, agentSynchronized);
484 decay.updateConfidence(objectPose, now);
489 Segment::filterObjectPoses(
const ObjectPoseMap& objectPoses)
const
492 for (
const auto& [
id, objectPose] : objectPoses)
494 if (!(decay.enabled && objectPose.confidence < decay.removeObjectsBelowConfidence))
496 result[id] = objectPose;
505 bool&
synchronized)
const
521 if (not
synchronized)
534 Segment::getLatestObjectPoses()
const
537 return getLatestObjectPoses(*segmentPtr);
544 getLatestObjectPoses(coreSeg, result);
552 getLatestObjectPoses(provSeg, result);
560 getLatestObjectPose(entity, result);
568 { getLatestObjectPoses(provSegment, out); });
579 ObjectPose pose = getLatestObjectPose(entity);
581 const auto [it, success] = out.insert({pose.objectID, pose});
585 if (it->second.timestamp < pose.timestamp)
600 arondto::ObjectInstance dto;
601 dto.fromAron(instance.
data());
607 arondto::ObjectInstance
616 arondto::ObjectInstance
data;
623 Segment::getArticulatedObjects()
627 ARMARX_INFO <<
"Found " << objectPoses.size() <<
" object poses";
630 for (
const auto& [objectId, objectPose] : objectPoses)
636 articulatedObject.
instance = objectPose.objectID.instanceName();
637 articulatedObject.
timestamp = objectPose.timestamp;
640 ARMARX_INFO <<
"Object id for objectPose is " << objectPose.objectID.str();
643 if (
auto classInstance = findClassInstance(objectPose.objectID))
645 arondto::ObjectClass dto;
649 dto.fromAron(classInstance->data());
669 objects.push_back(articulatedObject);
676 std::map<DateTime, objpose::ObjectPose>
681 std::map<DateTime, objpose::ObjectPose> result;
691 arondto::ObjectInstance dto;
692 dto.fromAron(instance.
data());
697 result.emplace(snapshot.
time(), pose);
704 std::optional<simox::OrientedBoxf>
707 return oobbCache.get(
id);
710 objpose::ProviderInfo
711 Segment::getProviderInfo(
const std::string& providerName)
715 return providers.at(providerName);
717 catch (
const std::out_of_range&)
719 std::stringstream ss;
720 ss <<
"No provider with name '" << providerName <<
"' available.\n";
721 ss <<
"Available are:\n";
722 for (
const auto& [name, _] : providers)
724 ss <<
"- '" << name <<
"'\n";
726 throw std::out_of_range(ss.str());
730 objpose::AttachObjectToRobotNodeOutput
731 Segment::attachObjectToRobotNode(
const objpose::AttachObjectToRobotNodeInput&
input)
735 objpose::AttachObjectToRobotNodeOutput output;
736 output.success =
false;
743 std::stringstream ss;
744 ss <<
"Tried to attach object " << objectID <<
" to unknown agent '" <<
input.agentName
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)
750 ss <<
"\n- '" << name <<
"'";
757 if (!agent->hasRobotNode(
input.frameName))
759 ARMARX_WARNING <<
"Tried to attach object " << objectID <<
" to unknown node '"
760 <<
input.frameName <<
"' of agent '" << agent->getName() <<
"'.";
763 std::string frameName =
input.frameName;
767 wm::Entity* objectEntity = this->findObjectEntity(objectID,
input.providerName);
768 if (!objectEntity || objectEntity->
empty())
770 ARMARX_WARNING <<
"Tried to attach object " << objectID <<
" to node '" << frameName
771 <<
"' of agent '" << agent->getName()
772 <<
"', but object is currently not provided.";
775 arondto::ObjectInstance
data = getLatestInstanceData(*objectEntity);
781 if (
input.poseInFrame)
809 update.entityID = objectEntity->
id();
810 update.referencedTime = now;
812 arondto::ObjectInstance updated =
data;
813 toAron(updated.pose.attachment, info);
814 updated.pose.attachmentValid =
true;
815 update.instancesData = {updated.toAron()};
817 iceMemory.commit(commit);
820 ARMARX_INFO <<
"Attached object " << objectID <<
" by provider '" <<
data.pose.providerName
823 <<
"Object pose in frame: \n"
826 output.success =
true;
827 output.attachment =
new objpose::data::ObjectAttachmentInfo();
828 output.attachment->frameName = info.
frameName;
829 output.attachment->agentName = info.
agentName;
835 objpose::DetachObjectFromRobotNodeOutput
836 Segment::detachObjectFromRobotNode(
const objpose::DetachObjectFromRobotNodeInput&
input)
841 std::string providerName =
input.providerName;
843 std::optional<objpose::arondto::ObjectAttachmentInfo> attachment;
847 wm::Entity* entity = this->findObjectEntity(objectID,
input.providerName);
850 const arondto::ObjectInstance
data = getLatestInstanceData(*entity);
851 if (
data.pose.attachmentValid)
853 attachment =
data.pose.attachment;
856 storeDetachedSnapshot(*entity,
data, now,
input.commitAttachedPose);
858 if (providerName.empty())
860 providerName =
data.pose.providerName;
865 objpose::DetachObjectFromRobotNodeOutput output;
866 output.wasAttached = bool(attachment);
869 ARMARX_INFO <<
"Detached object " << objectID <<
" by provider '" << providerName
870 <<
"' from robot node '" << attachment->frameName <<
"' of agent '"
871 << attachment->agentName <<
"'.";
875 ARMARX_INFO <<
"Tried to detach object " << objectID <<
" by provider '" << providerName
877 <<
"from robot node, but it was not attached.";
883 objpose::DetachAllObjectsFromRobotNodesOutput
884 Segment::detachAllObjectsFromRobotNodes(
885 const objpose::DetachAllObjectsFromRobotNodesInput&
input)
891 objpose::DetachAllObjectsFromRobotNodesOutput output;
892 output.numDetached = 0;
893 segmentPtr->forEachEntity(
896 const arondto::ObjectInstance
data = this->getLatestInstanceData(entity);
897 if (
data.pose.attachmentValid)
899 ++output.numDetached;
901 this->storeDetachedSnapshot(entity,
data, now,
input.commitAttachedPose);
905 ARMARX_INFO <<
"Detached all objects (" << output.numDetached <<
") from robot nodes.";
911 Segment::storeDetachedSnapshot(
wm::Entity& entity,
912 const arondto::ObjectInstance&
data,
914 bool commitAttachedPose)
919 update.referencedTime = now;
921 arondto::ObjectInstance updated;
922 if (commitAttachedPose and
data.pose.attachmentValid)
924 ObjectPose objectPose;
928 robots.get(objectPose.robotName, objectPose.providerName);
929 bool agentSynchronized =
false;
930 updateAttachement(objectPose, robot, agentSynchronized);
932 objectPose.attachment = std::nullopt;
933 toAron(updated, objectPose);
938 updated.pose.attachmentValid =
false;
942 update.instancesData = {updated.toAron()};
944 iceMemory.commit(commit);
947 std::optional<wm::EntityInstance>
948 Segment::findClassInstance(
const ObjectID& objectID)
const
950 const ObjectID classID = {objectID.dataset(), objectID.className()};
953 std::optional<wm::EntityInstance> result;
954 iceMemory.workingMemory->getCoreSegment(
"Class").forEachProviderSegment(
955 [&classID, &result](
const wm::ProviderSegment& provSeg)
957 if (provSeg.hasEntity(classID.str()))
960 provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0);
966 if (not result.has_value())
969 << classID.str() <<
" found";
973 catch (
const armem::error::ArMemError& e)
984 if (
const std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
986 ARMARX_INFO <<
"Storing scene snapshot at: \n" << path.value();
991 catch (
const simox::json::error::JsonError& e)
993 ARMARX_WARNING <<
"Storing scene snapshot failed: \n" << e.what();
998 std::optional<armarx::objects::Scene>
999 Segment::loadScene(
const std::string&
filename)
1001 if (
const std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
1003 return loadScene(path.value());
1007 return std::nullopt;
1011 std::optional<armarx::objects::Scene>
1012 Segment::loadScene(
const std::filesystem::path& path)
1016 return simox::json::read<armarx::objects::Scene>(path);
1018 catch (
const simox::json::error::JsonError& e)
1020 ARMARX_WARNING <<
"Loading scene snapshot failed: \n" << e.what();
1021 return std::nullopt;
1025 const std::string Segment::timestampPlaceholder =
"%TIMESTAMP";
1027 std::optional<std::filesystem::path>
1028 Segment::resolveSceneFilepath(
const std::string& _filename)
1030 std::stringstream log;
1031 std::filesystem::path filepath = _filename;
1033 filepath = simox::alg::replace_all(
1037 filepath +=
".json";
1040 if (filepath.is_absolute())
1047 if (filepath.has_parent_path())
1050 std::string packageName = *filepath.begin();
1051 return PackagePath(packageName, std::filesystem::relative(filepath, packageName));
1056 return PackagePath(p.sceneSnapshotsPackage, p.sceneSnapshotsDirectory / filepath);
1062 std::filesystem::path systemPath = packagePath.
toSystemPath();
1068 <<
"' as ArmarX package name (" << e.what() <<
").";
1069 return std::nullopt;
1074 Segment::getSceneSnapshot()
const
1080 struct StampedSceneObject
1086 std::map<ObjectID, StampedSceneObject> objects;
1087 segmentPtr->forEachEntity(
1088 [&objects](wm::Entity& entity)
1093 std::optional<arondto::ObjectInstance> objectInstance =
1094 tryCast<arondto::ObjectInstance>(*entityInstance);
1100 auto it = objects.find(objectID);
1101 if (it == objects.end() or
1102 objectInstance->pose.timestamp > it->second.timestamp)
1104 StampedSceneObject& stamped = objects[objectID];
1105 stamped.timestamp = objectInstance->pose.timestamp;
1107 SceneObject&
object = stamped.object;
1108 object.className = objectID.getClassID().str();
1109 object.instanceName = objectID.instanceName();
1110 object.collection =
"";
1113 simox::math::position(objectInstance->pose.objectPoseGlobal);
1114 object.orientation =
1115 simox::math::orientation(objectInstance->pose.objectPoseGlobal);
1117 object.isStatic = objectInstance->pose.isStatic;
1118 object.jointValues = objectInstance->pose.objectJointValues;
1125 for (
const auto& [
id, stamped] : objects)
1127 scene.
objects.emplace_back(std::move(stamped.object));
1136 std::map<ObjectID, int> idCounters;
1140 for (
const auto&
object : scene.
objects)
1148 const ObjectID classID =
object.getClassID(objectFinder);
1150 objpose::ObjectPose& pose = objectPoses.emplace_back();
1152 pose.providerName = sceneName;
1153 pose.objectType = objpose::ObjectType::KnownObject;
1155 pose.isStatic =
object.isStatic.has_value() ?
object.isStatic.value() :
true;
1156 pose.objectID = classID.withInstanceName(
object.instanceName.empty()
1158 :
object.instanceName);
1160 pose.objectPoseGlobal = simox::math::pose(
object.position,
object.orientation);
1161 pose.objectPoseRobot = pose.objectPoseGlobal;
1162 pose.objectPoseOriginal = pose.objectPoseGlobal;
1165 pose.objectJointValues =
object.jointValues;
1167 pose.robotConfig = {};
1169 pose.robotName =
"";
1171 pose.confidence = 1.0;
1172 pose.localOOBB = getObjectOOBB(classID);
1173 pose.timestamp = now;
1176 commitObjectPoses(objectPoses);
1180 Segment::commitSceneSnapshotFromFilename(
const std::string&
filename,
bool lockMemory)
1182 std::stringstream ss;
1183 ss <<
"Loading scene '" <<
filename <<
"' ...";
1184 if (std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
1186 ARMARX_INFO << ss.str() <<
"\nfrom " << path.value();
1188 if (
const auto snapshot = loadScene(path.value()))
1190 auto makeSceneName = [](
const std::filesystem::path& path)
1192 std::filesystem::path
filename = path.filename();
1196 std::string sceneName = makeSceneName(path.value());
1201 segmentPtr->doLocked([
this, &snapshot, &sceneName]()
1202 { commitSceneSnapshot(snapshot.value(), sceneName); });
1206 commitSceneSnapshot(snapshot.value(), sceneName);
1212 ARMARX_INFO << ss.str() <<
" failed: Could not resolve scene name or path.";
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);
1226 const std::string storeLoadPath = [&
data]()
1228 const std::vector<std::string> scenes =
data.p.getSceneSnapshotsToLoad();
1231 std::string storeLoadFilename =
"Scene_" + timestampPlaceholder;
1232 return data.p.sceneSnapshotsPackage +
"/" +
data.p.sceneSnapshotsToLoad;
1236 return scenes.front();
1240 storeLoadLine.setValue(storeLoadPath);
1241 loadButton.setLabel(
"Load Scene");
1242 storeButton.setLabel(
"Store Scene");
1245 HBoxLayout storeLoadButtonsLayout({loadButton, storeButton});
1247 detachAllObjectsButton.setLabel(
"Detach All Objects");
1248 detachAllObjectsCommitAttachedPoseCheckBox.setValue(
true);
1249 HBoxLayout detachAllObjectsCommitAttachedPoseLayout(
1250 {
Label(
"Commit Attached Pose"), detachAllObjectsCommitAttachedPoseCheckBox});
1256 grid.
add(storeLoadLineLayout, {row, 0}, {1, 2});
1258 grid.
add(storeLoadButtonsLayout, {row, 0}, {1, 2});
1261 grid.
add(
Label(
"Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
1263 grid.
add(
Label(
"Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
1265 grid.
add(
Label(
"Discard Snapshots while Attached"), {row, 0})
1266 .add(discardSnapshotsWhileAttached, {row, 1});
1269 grid.
add(detachAllObjectsButton, {row, 0})
1270 .add(detachAllObjectsCommitAttachedPoseLayout, {row, 1});
1272 group.setLabel(
"Data");
1273 group.addChild(grid);
1279 if (loadButton.wasClicked())
1281 bool lockMemory =
true;
1282 segment.commitSceneSnapshotFromFilename(storeLoadLine.getValue(), lockMemory);
1285 if (storeButton.wasClicked())
1288 segment.
doLocked([&scene, &segment]() { scene = segment.getSceneSnapshot(); });
1289 segment.storeScene(storeLoadLine.getValue(), scene);
1292 if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() ||
1293 discardSnapshotsWhileAttached.hasValueChanged())
1298 if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
1300 segment.properties.maxHistorySize =
1301 infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
1302 if (segment.segmentPtr)
1304 segment.segmentPtr->setMaxHistorySize(
1305 long(segment.properties.maxHistorySize));
1309 segment.p.discardSnapshotsWhileAttached =
1310 discardSnapshotsWhileAttached.getValue();
1314 if (detachAllObjectsButton.wasClicked())
1316 objpose::DetachAllObjectsFromRobotNodesInput
input;
1317 input.commitAttachedPose = detachAllObjectsCommitAttachedPoseCheckBox.getValue();
1319 objpose::DetachAllObjectsFromRobotNodesOutput output = segment.doLocked(
1320 [&segment, &
input]() {
return segment.detachAllObjectsFromRobotNodes(
input); });
1326 Segment::RobotsCache::get(
const std::string& _robotName,
const std::string& providerName)
1328 std::string robotName = _robotName;
1330 if (robotName.empty())
1334 std::stringstream ss;
1335 if (providerName.empty())
1337 ss <<
"The provided object pose";
1341 ss <<
"The object pose provided by '" << providerName <<
"'";
1343 ss <<
" does not specify a robot name";
1345 if (fallbackName.empty())
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).";
1356 ss <<
". The object instance segment is falling back to '" << fallbackName <<
"'.";
1359 robotName = fallbackName;
1365 if (
auto it = loaded.find(robotName); it != loaded.end())
1375 robotName,
Clock::Now(), VirtualRobot::RobotIO::RobotDescription::eStructure);
1379 bool synchronized = reader->synchronizeRobot(*robot,
Clock::Now());
1380 if (not
synchronized)
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.";
1388 loaded.emplace(robotName, robot);