6 #include <sys/inotify.h>
9 #include <Eigen/Geometry>
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>
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>
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.");
69 [
this](
const ObjectID&
id) -> std::optional<simox::OrientedBoxf>
76 objectInfo->setLogError(false);
77 return objectInfo->loadOOBB();
79 catch (
const std::ios_base::failure& e)
93 classNameToDatasetCache.setFetchFn(
94 [
this](
const std::string& className)
96 std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className);
97 return objectInfo ? objectInfo->dataset() :
"";
108 SpecializedCoreSegment::defineProperties(defs, prefix);
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.");
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.");
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.");
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' "
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'",
141 defs->optional(p.sceneSnapshotsToLoad,
142 prefix +
"scene.12_SnapshotToLoad",
143 simox::alg::join(sceneSnapshotToLoadDescription,
" \n"));
145 defs->optional(p.autoReloadSceneSnapshotsOnFileChange,
146 prefix +
"scene.13_autoReloadSceneSnapshotsOnFileChange");
148 decay.defineProperties(defs, prefix +
"decay.");
151 std::vector<std::string>
152 Segment::Properties::getSceneSnapshotsToLoad()
const
154 if (sceneSnapshotsToLoad.empty())
165 SpecializedCoreSegment::init();
167 const std::vector<std::string> scenes = p.getSceneSnapshotsToLoad();
168 for (
const std::string& scene : scenes)
170 const bool lockMemory =
false;
171 commitSceneSnapshotFromFilename(scene, lockMemory);
176 if (p.autoReloadSceneSnapshotsOnFileChange)
184 inotifyFd = inotify_init();
191 std::map<int, std::string> wds;
194 for (
const auto& scene : scenes)
196 if (std::optional<std::filesystem::path> path = resolveSceneFilepath(scene))
198 auto wd = inotify_add_watch(inotifyFd, path.value().c_str(), IN_MODIFY);
201 ARMARX_WARNING <<
"inotify_add_watch for scene: " << scene <<
"` failed.";
204 ARMARX_INFO <<
"inotify_add_watch for scene: " << scene <<
"` added.";
205 wds.emplace(wd, scene);
209 ARMARX_WARNING <<
"Faild to add file watcher for scene: `" << scene <<
"`.";
216 [
this, inotifyFd, wds]()
218 constexpr std::size_t BUF_LEN = (10 * (
sizeof(inotify_event) + NAME_MAX + 1));
226 numRead =
read(inotifyFd, buf, BUF_LEN);
239 for (
char* p = buf; p < buf + numRead;)
241 auto*
event =
reinterpret_cast<inotify_event*
>(p);
243 const auto& scene = wds.at(event->wd);
246 p +=
sizeof(
struct inotify_event) + event->len;
248 const bool lockMemory =
true;
249 commitSceneSnapshotFromFilename(scene, lockMemory);
254 fileWatcherTask->start();
268 Segment::commitObjectPoses(
const std::string& providerName,
270 const Calibration& calibration,
271 std::optional<armem::Time> discardUpdatesUntil)
282 for (
const objpose::data::ProvidedObjectPose& provided : providedPoses)
284 const Time timestamp = armarx::fromIce<Time>(provided.timestamp);
287 std::optional<objpose::ObjectPose> previousPose;
292 const arondto::ObjectInstance
data = getLatestInstanceData(*entity);
298 bool discard =
false;
299 if (discardUpdatesUntil && timestamp < discardUpdatesUntil.value())
304 else if (previousPose)
306 if (p.discardSnapshotsWhileAttached && previousPose->attachment)
311 else if (timestamp == previousPose->timestamp)
330 << provided.robotName <<
"`.";
335 bool synchronized =
false;
338 if (robot and robotSyncTimestamp != timestamp)
340 synchronized =
robots.reader->synchronizeRobot(*robot, timestamp);
341 if (not
synchronized)
344 << timestamp <<
" of provided object pose (" << provided.objectID
345 <<
"). This is " << (
Clock::Now() - timestamp).toSecondsDouble()
346 <<
" seconds in the past.";
349 robotSyncTimestamp = timestamp;
353 if (calibration.offset != 0 and robot->hasRobotNode(calibration.robotNode))
355 VirtualRobot::RobotNodePtr robotNode =
356 robot->getRobotNode(calibration.robotNode);
358 float value = robotNode->getJointValue();
359 float newValue =
value + calibration.offset;
367 VirtualRobot::RobotNode::JointLimits limits = robotNode->getJointLimits();
368 bool limitsChanged =
false;
369 if (newValue < limits.low)
371 limits.low = newValue;
372 limitsChanged =
true;
374 if (newValue > limits.high)
376 limits.high = newValue;
377 limitsChanged =
true;
381 robotNode->setJointLimits(limits.low, limits.high);
384 robotNode->setJointValue(newValue);
388 else if (robot and timestamp == robotSyncTimestamp)
393 if (not
synchronized)
400 <<
"Robot could not be synchronized; discarding robot";
404 objpose::ObjectPose& newPose = newObjectPoses.emplace_back();
405 if (provided.objectPoseFrame.empty())
407 objpose::data::ProvidedObjectPose
copy = provided;
409 newPose.fromProvidedPose(
copy, robot);
413 newPose.fromProvidedPose(provided, robot);
416 if (previousPose && previousPose->attachment)
420 newPose.attachment = previousPose->attachment;
423 if (newPose.objectID.dataset().empty())
426 const std::string dataset =
427 classNameToDatasetCache.get(newPose.objectID.className());
428 if (!dataset.empty())
431 dataset, newPose.objectID.className(), newPose.objectID.instanceName()};
434 if (!provided.localOOBB)
437 newPose.localOOBB = getObjectOOBB(newPose.objectID);
441 commitObjectPoses(newObjectPoses, providerName);
447 Segment::commitObjectPoses(
const ObjectPoseSeq& objectPoses,
const std::string& providerName)
460 providerName.empty() ? pose.providerName : providerName);
464 update.referencedTime = pose.timestamp;
465 update.confidence = pose.confidence;
467 arondto::ObjectInstance dto;
470 if (
auto instance = findClassInstance(pose.objectID))
472 toAron(dto.classID, instance->id());
479 update.instancesData.push_back(dto.toAron());
482 iceMemory.commit(commit);
489 updateObjectPoses(objectPoses, now);
490 return filterObjectPoses(objectPoses);
494 Segment::getObjectPosesByProvider(
const std::string& providerName,
const DateTime& now)
498 getLatestObjectPoses(segmentPtr->getProviderSegment(providerName));
499 updateObjectPoses(objectPoses, now);
500 return filterObjectPoses(objectPoses);
504 Segment::findObjectEntity(
const ObjectID& objectID,
const std::string& providerName)
508 if (providerName.empty())
511 segmentPtr->forEachProviderSegment(
516 result = &prov.getEntity(entityID);
526 if (segmentPtr->hasProviderSegment(providerName))
541 bool agentSynchronized =
false;
543 for (
auto& [
id, objectPose] : objectPoses)
546 robots.get(objectPose.robotName, objectPose.providerName);
547 updateObjectPose(objectPose, now, robot, agentSynchronized);
555 bool& agentSynchronized)
const
557 for (
auto& [
id, objectPose] : objectPoses)
559 updateObjectPose(objectPose, now, agent, agentSynchronized);
564 Segment::updateObjectPose(ObjectPose& objectPose,
567 bool& agentSynchronized)
const
569 updateAttachement(objectPose, agent, agentSynchronized);
573 decay.updateConfidence(objectPose, now);
578 Segment::filterObjectPoses(
const ObjectPoseMap& objectPoses)
const
581 for (
const auto& [
id, objectPose] : objectPoses)
583 if (!(decay.enabled && objectPose.confidence < decay.removeObjectsBelowConfidence))
585 result[id] = objectPose;
594 bool&
synchronized)
const
610 if (not
synchronized)
623 Segment::getLatestObjectPoses()
const
626 return getLatestObjectPoses(*segmentPtr);
633 getLatestObjectPoses(coreSeg, result);
641 getLatestObjectPoses(provSeg, result);
649 getLatestObjectPose(entity, result);
657 { getLatestObjectPoses(provSegment, out); });
668 ObjectPose pose = getLatestObjectPose(entity);
670 const auto [it, success] = out.insert({pose.objectID, pose});
674 if (it->second.timestamp < pose.timestamp)
689 arondto::ObjectInstance dto;
690 dto.fromAron(instance.
data());
696 arondto::ObjectInstance
705 arondto::ObjectInstance
data;
712 Segment::getArticulatedObjects()
716 ARMARX_INFO <<
"Found " << objectPoses.size() <<
" object poses";
719 for (
const auto& [objectId, objectPose] : objectPoses)
725 articulatedObject.
instance = objectPose.objectID.instanceName();
726 articulatedObject.
timestamp = objectPose.timestamp;
729 ARMARX_INFO <<
"Object id for objectPose is " << objectPose.objectID.str();
732 if (
auto classInstance = findClassInstance(objectPose.objectID))
734 arondto::ObjectClass dto;
738 dto.fromAron(classInstance->data());
758 objects.push_back(articulatedObject);
765 std::map<DateTime, objpose::ObjectPose>
770 std::map<DateTime, objpose::ObjectPose> result;
780 arondto::ObjectInstance dto;
781 dto.fromAron(instance.
data());
786 result.emplace(snapshot.
time(), pose);
793 std::optional<simox::OrientedBoxf>
796 return oobbCache.get(
id);
799 objpose::ProviderInfo
800 Segment::getProviderInfo(
const std::string& providerName)
804 return providers.at(providerName);
806 catch (
const std::out_of_range&)
808 std::stringstream ss;
809 ss <<
"No provider with name '" << providerName <<
"' available.\n";
810 ss <<
"Available are:\n";
811 for (
const auto& [name, _] : providers)
813 ss <<
"- '" << name <<
"'\n";
815 throw std::out_of_range(ss.str());
819 objpose::AttachObjectToRobotNodeOutput
820 Segment::attachObjectToRobotNode(
const objpose::AttachObjectToRobotNodeInput&
input)
824 objpose::AttachObjectToRobotNodeOutput output;
825 output.success =
false;
832 std::stringstream ss;
833 ss <<
"Tried to attach object " << objectID <<
" to unknown agent '" <<
input.agentName
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)
839 ss <<
"\n- '" << name <<
"'";
846 if (!agent->hasRobotNode(
input.frameName))
848 ARMARX_WARNING <<
"Tried to attach object " << objectID <<
" to unknown node '"
849 <<
input.frameName <<
"' of agent '" << agent->getName() <<
"'.";
852 std::string frameName =
input.frameName;
856 wm::Entity* objectEntity = this->findObjectEntity(objectID,
input.providerName);
857 if (!objectEntity || objectEntity->
empty())
859 ARMARX_WARNING <<
"Tried to attach object " << objectID <<
" to node '" << frameName
860 <<
"' of agent '" << agent->getName()
861 <<
"', but object is currently not provided.";
864 arondto::ObjectInstance
data = getLatestInstanceData(*objectEntity);
870 if (
input.poseInFrame)
898 update.entityID = objectEntity->
id();
899 update.referencedTime = now;
901 arondto::ObjectInstance updated =
data;
902 toAron(updated.pose.attachment, info);
903 updated.pose.attachmentValid =
true;
904 update.instancesData = {updated.toAron()};
906 iceMemory.commit(commit);
909 ARMARX_INFO <<
"Attached object " << objectID <<
" by provider '" <<
data.pose.providerName
912 <<
"Object pose in frame: \n"
915 output.success =
true;
916 output.attachment =
new objpose::data::ObjectAttachmentInfo();
917 output.attachment->frameName = info.
frameName;
918 output.attachment->agentName = info.
agentName;
924 objpose::DetachObjectFromRobotNodeOutput
925 Segment::detachObjectFromRobotNode(
const objpose::DetachObjectFromRobotNodeInput&
input)
930 std::string providerName =
input.providerName;
932 std::optional<objpose::arondto::ObjectAttachmentInfo> attachment;
936 wm::Entity* entity = this->findObjectEntity(objectID,
input.providerName);
939 const arondto::ObjectInstance
data = getLatestInstanceData(*entity);
940 if (
data.pose.attachmentValid)
942 attachment =
data.pose.attachment;
945 storeDetachedSnapshot(*entity,
data, now,
input.commitAttachedPose);
947 if (providerName.empty())
949 providerName =
data.pose.providerName;
954 objpose::DetachObjectFromRobotNodeOutput output;
955 output.wasAttached = bool(attachment);
958 ARMARX_INFO <<
"Detached object " << objectID <<
" by provider '" << providerName
959 <<
"' from robot node '" << attachment->frameName <<
"' of agent '"
960 << attachment->agentName <<
"'.";
964 ARMARX_INFO <<
"Tried to detach object " << objectID <<
" by provider '" << providerName
966 <<
"from robot node, but it was not attached.";
972 objpose::DetachAllObjectsFromRobotNodesOutput
973 Segment::detachAllObjectsFromRobotNodes(
974 const objpose::DetachAllObjectsFromRobotNodesInput&
input)
980 objpose::DetachAllObjectsFromRobotNodesOutput output;
981 output.numDetached = 0;
982 segmentPtr->forEachEntity(
985 const arondto::ObjectInstance
data = this->getLatestInstanceData(entity);
986 if (
data.pose.attachmentValid)
988 ++output.numDetached;
990 this->storeDetachedSnapshot(entity,
data, now,
input.commitAttachedPose);
994 ARMARX_INFO <<
"Detached all objects (" << output.numDetached <<
") from robot nodes.";
1000 Segment::storeDetachedSnapshot(
wm::Entity& entity,
1001 const arondto::ObjectInstance&
data,
1003 bool commitAttachedPose)
1008 update.referencedTime = now;
1010 arondto::ObjectInstance updated;
1011 if (commitAttachedPose and
data.pose.attachmentValid)
1013 ObjectPose objectPose;
1017 robots.get(objectPose.robotName, objectPose.providerName);
1018 bool agentSynchronized =
false;
1019 updateAttachement(objectPose, robot, agentSynchronized);
1021 objectPose.attachment = std::nullopt;
1022 toAron(updated, objectPose);
1027 updated.pose.attachmentValid =
false;
1031 update.instancesData = {updated.toAron()};
1033 iceMemory.commit(commit);
1036 std::optional<wm::EntityInstance>
1037 Segment::findClassInstance(
const ObjectID& objectID)
const
1039 const ObjectID classID = {objectID.dataset(), objectID.className()};
1042 std::optional<wm::EntityInstance> result;
1043 iceMemory.workingMemory->getCoreSegment(
"Class").forEachProviderSegment(
1044 [&classID, &result](
const wm::ProviderSegment& provSeg)
1046 if (provSeg.hasEntity(classID.str()))
1049 provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0);
1055 if (not result.has_value())
1058 << classID.str() <<
" found";
1062 catch (
const armem::error::ArMemError& e)
1066 return std::nullopt;
1073 if (
const std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
1075 ARMARX_INFO <<
"Storing scene snapshot at: \n" << path.value();
1080 catch (
const simox::json::error::JsonError& e)
1082 ARMARX_WARNING <<
"Storing scene snapshot failed: \n" << e.what();
1087 std::optional<armarx::objects::Scene>
1088 Segment::loadScene(
const std::string&
filename)
1090 if (
const std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
1092 return loadScene(path.value());
1096 return std::nullopt;
1100 std::optional<armarx::objects::Scene>
1101 Segment::loadScene(
const std::filesystem::path& path)
1106 return simox::json::read<armarx::objects::Scene>(path);
1108 catch (
const simox::json::error::JsonError& e)
1110 ARMARX_WARNING <<
"Loading scene snapshot failed: \n" << e.what();
1111 return std::nullopt;
1115 const std::string Segment::timestampPlaceholder =
"%TIMESTAMP";
1117 std::optional<std::filesystem::path>
1118 Segment::resolveSceneFilepath(
const std::string& _filename)
1120 std::stringstream log;
1121 std::filesystem::path filepath = _filename;
1123 filepath = simox::alg::replace_all(
1127 filepath +=
".json";
1130 if (filepath.is_absolute())
1137 if (filepath.has_parent_path())
1140 std::string packageName = *filepath.begin();
1141 return PackagePath(packageName, std::filesystem::relative(filepath, packageName));
1146 return PackagePath(p.sceneSnapshotsPackage, p.sceneSnapshotsDirectory / filepath);
1152 std::filesystem::path systemPath = packagePath.
toSystemPath();
1158 <<
"' as ArmarX package name (" << e.what() <<
").";
1159 return std::nullopt;
1164 Segment::getSceneSnapshot()
const
1170 struct StampedSceneObject
1176 std::map<ObjectID, StampedSceneObject> objects;
1177 segmentPtr->forEachEntity(
1178 [&objects](wm::Entity& entity)
1183 std::optional<arondto::ObjectInstance> objectInstance =
1184 tryCast<arondto::ObjectInstance>(*entityInstance);
1190 auto it = objects.find(objectID);
1191 if (it == objects.end() or
1192 objectInstance->pose.timestamp > it->second.timestamp)
1194 StampedSceneObject& stamped = objects[objectID];
1195 stamped.timestamp = objectInstance->pose.timestamp;
1197 SceneObject&
object = stamped.object;
1198 object.className = objectID.getClassID().str();
1199 object.instanceName = objectID.instanceName();
1200 object.collection =
"";
1203 simox::math::position(objectInstance->pose.objectPoseGlobal);
1204 object.orientation =
1205 simox::math::orientation(objectInstance->pose.objectPoseGlobal);
1207 object.isStatic = objectInstance->pose.isStatic;
1208 object.jointValues = objectInstance->pose.objectJointValues;
1215 for (
const auto& [
id, stamped] : objects)
1217 scene.
objects.emplace_back(std::move(stamped.object));
1226 std::map<ObjectID, int> idCounters;
1230 for (
const auto&
object : scene.
objects)
1238 const ObjectID classID =
object.getClassID(objectFinder);
1240 objpose::ObjectPose& pose = objectPoses.emplace_back();
1242 pose.providerName = sceneName;
1243 pose.objectType = objpose::ObjectType::KnownObject;
1245 pose.isStatic =
object.isStatic.has_value() ?
object.isStatic.value() :
true;
1246 pose.objectID = classID.withInstanceName(
object.instanceName.empty()
1248 :
object.instanceName);
1250 pose.objectPoseGlobal = simox::math::pose(
object.position,
object.orientation);
1251 pose.objectPoseRobot = pose.objectPoseGlobal;
1252 pose.objectPoseOriginal = pose.objectPoseGlobal;
1255 pose.objectJointValues =
object.jointValues;
1257 pose.robotConfig = {};
1259 pose.robotName =
"";
1261 pose.confidence = 1.0;
1262 pose.localOOBB = getObjectOOBB(classID);
1263 pose.timestamp = now;
1266 commitObjectPoses(objectPoses);
1270 Segment::commitSceneSnapshotFromFilename(
const std::string&
filename,
bool lockMemory)
1272 std::stringstream ss;
1273 ss <<
"Loading scene '" <<
filename <<
"' ...";
1274 if (std::optional<std::filesystem::path> path = resolveSceneFilepath(
filename))
1276 ARMARX_INFO << ss.str() <<
"\nfrom " << path.value();
1278 if (
const auto snapshot = loadScene(path.value()))
1280 auto makeSceneName = [](
const std::filesystem::path& path)
1282 std::filesystem::path
filename = path.filename();
1286 std::string sceneName = makeSceneName(path.value());
1291 segmentPtr->doLocked([
this, &snapshot, &sceneName]()
1292 { commitSceneSnapshot(snapshot.value(), sceneName); });
1296 commitSceneSnapshot(snapshot.value(), sceneName);
1302 ARMARX_INFO << ss.str() <<
" failed: Could not resolve scene name or path.";
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);
1316 const std::string storeLoadPath = [&
data]()
1318 const std::vector<std::string> scenes =
data.p.getSceneSnapshotsToLoad();
1321 std::string storeLoadFilename =
"Scene_" + timestampPlaceholder;
1322 return data.p.sceneSnapshotsPackage +
"/" +
data.p.sceneSnapshotsToLoad;
1326 return scenes.front();
1330 storeLoadLine.setValue(storeLoadPath);
1331 loadButton.setLabel(
"Load Scene");
1332 storeButton.setLabel(
"Store Scene");
1335 HBoxLayout storeLoadButtonsLayout({loadButton, storeButton});
1337 detachAllObjectsButton.setLabel(
"Detach All Objects");
1338 detachAllObjectsCommitAttachedPoseCheckBox.setValue(
true);
1339 HBoxLayout detachAllObjectsCommitAttachedPoseLayout(
1340 {
Label(
"Commit Attached Pose"), detachAllObjectsCommitAttachedPoseCheckBox});
1346 grid.
add(storeLoadLineLayout, {row, 0}, {1, 2});
1348 grid.
add(storeLoadButtonsLayout, {row, 0}, {1, 2});
1351 grid.
add(
Label(
"Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
1353 grid.
add(
Label(
"Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
1355 grid.
add(
Label(
"Discard Snapshots while Attached"), {row, 0})
1356 .add(discardSnapshotsWhileAttached, {row, 1});
1359 grid.
add(detachAllObjectsButton, {row, 0})
1360 .add(detachAllObjectsCommitAttachedPoseLayout, {row, 1});
1362 group.setLabel(
"Data");
1363 group.addChild(grid);
1369 if (loadButton.wasClicked())
1371 bool lockMemory =
true;
1372 segment.commitSceneSnapshotFromFilename(storeLoadLine.getValue(), lockMemory);
1375 if (storeButton.wasClicked())
1378 segment.
doLocked([&scene, &segment]() { scene = segment.getSceneSnapshot(); });
1379 segment.storeScene(storeLoadLine.getValue(), scene);
1382 if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() ||
1383 discardSnapshotsWhileAttached.hasValueChanged())
1388 if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
1390 segment.properties.maxHistorySize =
1391 infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
1392 if (segment.segmentPtr)
1394 segment.segmentPtr->setMaxHistorySize(
1395 long(segment.properties.maxHistorySize));
1399 segment.p.discardSnapshotsWhileAttached =
1400 discardSnapshotsWhileAttached.getValue();
1404 if (detachAllObjectsButton.wasClicked())
1406 objpose::DetachAllObjectsFromRobotNodesInput
input;
1407 input.commitAttachedPose = detachAllObjectsCommitAttachedPoseCheckBox.getValue();
1409 objpose::DetachAllObjectsFromRobotNodesOutput output = segment.doLocked(
1410 [&segment, &
input]() {
return segment.detachAllObjectsFromRobotNodes(
input); });
1416 Segment::RobotsCache::get(
const std::string& _robotName,
const std::string& providerName)
1418 std::string robotName = _robotName;
1420 if (robotName.empty())
1424 std::stringstream ss;
1425 if (providerName.empty())
1427 ss <<
"The provided object pose";
1431 ss <<
"The object pose provided by '" << providerName <<
"'";
1433 ss <<
" does not specify a robot name";
1435 if (fallbackName.empty())
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).";
1446 ss <<
". The object instance segment is falling back to '" << fallbackName <<
"'.";
1449 robotName = fallbackName;
1455 if (
auto it = loaded.find(robotName); it != loaded.end())
1465 robotName,
Clock::Now(), VirtualRobot::RobotIO::RobotDescription::eStructure);
1469 bool synchronized = reader->synchronizeRobot(*robot,
Clock::Now());
1470 if (not
synchronized)
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.";
1478 loaded.emplace(robotName, robot);