6 #include <SimoxUtility/math/convert/mat3f_to_rpy.h>
44 def->topic(reportTopic);
45 def->topic(globalRobotPoseTopic);
46 def->topic(gobalRobotPoseCorrectionTopic);
49 def->optional(properties.updateWorkingMemory,
50 "working_memory.update",
51 "If enabled, updates the global pose in the working memory");
52 def->optional(properties.workingMemoryUpdateFrequency,
"working_memory.update_frequency");
55 def->optional(properties.longtermMemoryName,
57 "Which legacy long-term memory to use if longterm_memory.update"
58 "or longterm_memory.retrieve_initial_pose are set");
59 def->optional(properties.updateLongTermMemory,
60 "longterm_memory.update",
61 "If enabled, updates the global pose in the longterm memory");
62 def->optional(properties.longtermMemoryUpdateFrequency,
"longterm_memory.update_frequency");
63 def->optional(properties.initialPoseFromLTM,
"longterm_memory.retrieve_initial_pose");
67 def->optional(properties.updateArMem,
"armem.update",
"If enabled, updates ArMem");
68 def->optional(properties.armMemUpdateFrequency,
"armem.update_frequency");
71 def->component(robotStateComponent,
72 "RobotStateComponent",
73 "robot_state_component",
74 "The name of the RobotStateComponent. Used to get local transformation of "
79 const std::string fullTypeName =
80 ::IceProxy::armarx::LocalizationUnitInterface::ice_staticId();
81 properties.localizationUnitName =
85 def->optional(properties.useLocalizationUnit,
86 "localizationUnit.use",
87 "If enabled, connects to the localization unit");
88 def->optional(properties.localizationUnitName,
89 "localizationUnit.proxyName",
90 "If enabled, connects to the localization unit");
100 if (not connected.load())
103 <<
"Will not publish self localization as some dependencies are not available.";
108 publishSelfLocalizationOnTopic(map_T_robot);
111 publishSelfLocalizationToArMem(map_T_robot);
114 ARMARX_DEBUG <<
"publishSelfLocalizationToWorkingMemory";
115 publishSelfLocalizationToWorkingMemory(map_T_robot);
117 ARMARX_DEBUG <<
"publishSelfLocalizationToLongtermMemory";
118 publishSelfLocalizationToLongtermMemory(map_T_robot);
125 if (properties.updateWorkingMemory)
129 if (properties.updateLongTermMemory or properties.initialPoseFromLTM)
134 if (properties.useLocalizationUnit)
144 connected.store(
false);
148 SelfLocalization::publishSelfLocalizationOnTopic(
const PoseStamped& map_T_robot)
152 const Eigen::Isometry3f globalPose = global_T_map * map_T_robot.
pose;
154 const float yaw = simox::math::mat3f_to_rpy(globalPose.linear()).z();
165 globalRobotPoseTopic->reportGlobalRobotPose(toTransformStamped(globalPoseStamped));
169 const armem::robot_state::client::localization::TransformQuery odomQuery{
171 .frame = robotRootFrame,
178 const auto odomLookupResult = transformReaderPlugin->get().lookupTransform(odomQuery);
180 if (odomLookupResult.status ==
183 const Eigen::Isometry3f robot_T_odom =
184 odomLookupResult.transform.transform.inverse();
185 const Eigen::Isometry3f map_T_odom = map_T_robot.
pose * robot_T_odom;
186 const Eigen::Isometry3f global_T_odom = global_T_map * map_T_odom;
187 const PoseStamped globalOdomPoseStamped{.pose = global_T_odom,
190 gobalRobotPoseCorrectionTopic->reportGlobalRobotPoseCorrection(
191 toTransformStamped(globalOdomPoseStamped));
193 if (properties.useLocalizationUnit)
196 localizationUnitPrx->reportGlobalRobotPoseCorrection(
197 toTransformStamped(globalOdomPoseStamped));
208 <<
"Failed to publish global pose on topics as the following "
209 "exception occured: "
220 SelfLocalization::publishSelfLocalizationToWorkingMemory(
const PoseStamped& map_T_robot)
224 if (not properties.updateWorkingMemory or not workingMemory)
234 properties.workingMemoryUpdateFrequency))
239 const Eigen::Affine3f globalPose = global_T_map * map_T_robot.pose;
249 wmAgentInstance->setPose(reportPose);
250 const std::string robotAgentId =
251 wmAgentsMemory->upsertEntityByName(wmAgentInstance->getName(), wmAgentInstance);
252 wmAgentInstance->setId(robotAgentId);
254 catch (IceUtil::Exception
const& ex)
256 ARMARX_WARNING <<
"Caught exception while updating the working memory:\n" << ex;
261 SelfLocalization::publishSelfLocalizationToLongtermMemory(
const PoseStamped& map_T_robot)
265 if (not properties.updateLongTermMemory or not longtermMemory)
271 <<
"Self localisation memory segment is not set";
275 properties.longtermMemoryUpdateFrequency))
280 if (not ltmPoseEntityId)
285 const Eigen::Affine3f globalPose = global_T_map * map_T_robot.pose;
293 poseEntity->setName(agentName);
294 poseEntity->putAttribute(
"pose", reportPose);
295 poseEntity->setId(*ltmPoseEntityId);
297 ltmSelfLocalisationSegment->upsertEntity(*ltmPoseEntityId, poseEntity);
299 catch (IceUtil::Exception
const& ex)
301 ARMARX_WARNING <<
"Caught exception while updating the longterm memory:\n" << ex;
305 armem::robot_state::localization::Transform
306 SelfLocalization::toTransform(
const PoseStamped& poseStamped)
308 return {.header{.parentFrame =
MapFrame,
311 .timestamp = poseStamped.timestamp},
312 .transform = poseStamped.pose};
316 SelfLocalization::publishSelfLocalizationToArMem(
const PoseStamped& map_T_robot)
320 if (not properties.updateArMem)
326 if (not skipper.
checkFrequency(
"armMemUpdateFrequency", properties.armMemUpdateFrequency))
331 const armem::robot_state::client::localization::TransformQuery odomQuery{
333 .frame = robotRootFrame,
335 .timestamp = map_T_robot.timestamp}};
337 const auto odomLookupResult = transformReaderPlugin->get().lookupTransform(odomQuery);
339 if (odomLookupResult.status !=
346 const Eigen::Isometry3f robot_T_odom = odomLookupResult.transform.transform.inverse();
347 const Eigen::Isometry3f map_T_odom = map_T_robot.pose * robot_T_odom;
349 const armem::robot_state::localization::Transform mapToOdomTransform{
353 .timestamp = map_T_robot.timestamp},
354 .transform = map_T_odom};
356 const auto status = transformWriterPlugin->get().commitTransform(mapToOdomTransform);
365 SelfLocalization::toTransformStamped(
const PoseStamped& poseStamped)
369 header.frame = robotRootFrame;
370 header.agent = agentName;
371 header.timestampInMicroSeconds = poseStamped.timestamp.toMicroSecondsSinceEpoch();
375 transform.transform = poseStamped.pose.matrix();
381 SelfLocalization::setupArMem()
385 if (not properties.updateArMem)
395 ARMARX_INFO <<
"Publishing world to map transform";
402 .transform = global_T_map,
408 <<
"Something went wrong during setupArMem. Updating ArMem will be deactivated";
409 properties.updateArMem =
false;
414 SelfLocalization::setupWorkingMemory()
418 if (not properties.updateWorkingMemory or not workingMemory)
425 wmAgentsMemory = workingMemory->getAgentInstancesSegment();
428 wmAgentInstance->setSharedRobot(robotStateComponent->getSynchronizedRobot());
429 wmAgentInstance->setAgentFilePath(robotStateComponent->getRobotFilename());
430 wmAgentInstance->setName(agentName);
434 SelfLocalization::setupLongTermMemory()
438 if (not longtermMemory)
444 ltmSelfLocalisationSegment = longtermMemory->getSelfLocalisationSegment();
446 if (not properties.updateLongTermMemory)
453 const auto getOrCreatePoseEntityID = [&]() -> std::string
455 const memoryx::EntityBasePtr existingPoseEntity =
456 ltmSelfLocalisationSegment->getEntityByName(agentName);
458 if (existingPoseEntity)
460 return existingPoseEntity->getId();
464 ARMARX_WARNING <<
"No pose in longterm memory found for agent: " << agentName;
471 poseEntity->setName(agentName);
472 poseEntity->putAttribute(
"pose", pose);
474 return ltmSelfLocalisationSegment->addEntity(poseEntity);
479 ltmPoseEntityId = getOrCreatePoseEntityID();
485 <<
"Could not setup LongTermMemory. Updating LongTermMemory will be deactivated.";
486 properties.updateLongTermMemory =
false;
496 if (properties.useLocalizationUnit)
498 getProxy(localizationUnitPrx, properties.localizationUnitName);
514 agentName = robotStateComponent->getRobotName();
521 if (properties.updateWorkingMemory)
523 getProxy(workingMemory,
"WorkingMemory");
525 <<
"but working memory is not available.";
526 setupWorkingMemory();
528 if (properties.updateLongTermMemory or properties.initialPoseFromLTM)
530 getProxy(longtermMemory, properties.longtermMemoryName);
532 <<
"Long-term memory updates or pose retrieval are enabled, "
533 <<
"but long-term memory is not available.";
535 setupLongTermMemory();
540 connected.store(
true);
541 onConnectCalled =
true;
550 ARMARX_INFO <<
"SelfLocalization::onReconnectComponent";
554 setupWorkingMemory();
555 setupLongTermMemory();
557 connected.store(
true);
562 std::optional<Eigen::Affine3f>
567 if (not properties.initialPoseFromLTM or not longtermMemory)
572 ARMARX_INFO <<
"Querying initial pose from long term memory";
574 if (not ltmSelfLocalisationSegment)
576 ARMARX_FATAL <<
"Could not retrieve global pose from long-term memory."
577 <<
"Reason: Self-localization segment not available.";
586 const memoryx::EntityBasePtr poseEntity =
587 ltmSelfLocalisationSegment->getEntityByName(agentName);
590 ARMARX_FATAL <<
"Could not retrieve global pose from long-term memory."
591 <<
"Reason: Pose entity not available.";
595 const auto poseEntityId = poseEntity->getId();
596 ARMARX_DEBUG <<
"Using pose entity from LTM with ID: " << poseEntityId;
597 const memoryx::EntityAttributeBasePtr poseAttribute = poseEntity->getAttribute(
"pose");
599 if (not poseAttribute)
601 ARMARX_FATAL <<
"Could not retrieve global pose from long-term memory."
602 <<
"Reason: Pose attribute not available.";
608 armarx::VariantPtr::dynamicCast(poseAttribute->getValueAt(0))
613 ARMARX_FATAL <<
"Could not retrieve global pose from long-term memory."
614 <<
"Reason: Casting to framed pose failed.";
618 const Eigen::Affine3f pose(framedPose->toGlobalEigen(robot));
619 ARMARX_INFO <<
"Long-term memory global pose prior: " << pose.matrix();
625 ARMARX_FATAL <<
"Could not retrieve global pose from long-term memory."
626 <<
"Reason: unknown.";
641 return robotRootFrame;
653 return transformWriterPlugin->get();
659 return transformReaderPlugin->get();