117 def->optional(properties.snapshotToLoad,
119 "Snapshot to load at start up \n"
120 "(e.g. 'R003' to load 'PriorKnowledgeData/navigation-graphs/R003').");
122 def->optional(properties.packageToLoad,
124 "Package to load snapshot at start up \n"
125 "(e.g. 'PriorKnowledgeData').");
127 def->optional(properties.locationGraph.visuLocations,
128 "p.locationGraph.visuLocation",
129 "Enable visualization of locations.");
132 properties.locationGraph.visuRelativeLocations,
133 "p.locationGraph.visuRelativeLocation",
134 "Enable visualization of relative locations (currently supported: robots, objects).");
136 def->optional(properties.locationGraph.visuGraphEdges,
137 "p.locationGraph.visuGraphEdges",
138 "Enable visualization of navigation graph edges.");
140 def->optional(properties.visuCostmaps,
142 "Enable visualization of costmaps.");
143 def->optional(properties.zOffsetCostmap,
145 "Adjust the height of the visualized costmap.");
147 def->optional(properties.visuHumans,
"p.visuHumans",
"Enable visualization of humans.");
149 def->optional(properties.visuTransparent,
151 "Enable visualization of humans a bit transparent.");
153 def->optional(properties.visuHumanMaxAgeMs,
154 "p.visuHumanMaxAgeMs",
155 "The maximum age of humans to be drawn in ms.");
157 def->optional(properties.visuRooms,
"p.visuRooms",
"Enable visualization of rooms.");
159 def->optional(properties.visuLaserScannerFeatures,
160 "p.visuLaserScannerFeatures",
161 "Enable visualization of laser scanner features (global frame only).");
163 def->optional(properties.visuFrequency,
165 "Visualization frequeny of locations and graph edges [Hz].");
170 properties.coreSeg.parameterization.maxHistorySize,
171 "p.coreSeg.parameterization.maxHistorySize",
172 "Max history size of the " +
176 def->optional(properties.coreSeg.costmap.maxHistorySize,
177 "p.coreSeg.costmap.maxHistorySize",
178 "Max history size of the " +
182 def->optional(properties.coreSeg.costmap3d.maxHistorySize,
183 "p.coreSeg.costmap3d.maxHistorySize",
184 "Max history size of the " +
189 properties.coreSeg.resultsGlobalPlanner.maxHistorySize,
190 "p.coreSeg.resultsGlobalPlanner.maxHistorySize",
191 "Max history size of the " +
195 def->optional(properties.coreSeg.resultsLocalPlanner.maxHistorySize,
196 "p.coreSeg.resultsLocalPlanner.maxHistorySize",
197 "Max history size of the " +
201 def->optional(properties.coreSeg.events.maxHistorySize,
202 "p.coreSeg.events.maxHistorySize",
203 "Max history size of the " +
207 def->optional(properties.coreSeg.exceptions.maxHistorySize,
208 "p.coreSeg.exceptions.maxHistorySize",
209 "Max history size of the " +
213 def->optional(properties.coreSeg.location.maxHistorySize,
214 "p.coreSeg.location.maxHistorySize",
215 "Max history size of the " +
219 def->optional(properties.coreSeg.graph.maxHistorySize,
220 "p.coreSeg.graph.maxHistorySize",
221 "Max history size of the " +
225 def->optional(properties.coreSeg.human.maxHistorySize,
226 "p.coreSeg.human.maxHistorySize",
227 "Max history size of the " +
232 properties.coreSeg.laserScannerFeatures.maxHistorySize,
233 "p.coreSeg.laserScannerFeatures.maxHistorySize",
234 "Max history size of the " +
238 def->optional(properties.coreSeg.rooms.maxHistorySize,
239 "p.coreSeg.rooms.maxHistorySize",
240 "Max history size of the " +
270 algorithms::arondto::Costmap::ToAronType())
275 algorithms::orientation_aware::arondto::Costmap3D::ToAronType())
280 navigation::core::arondto::GlobalTrajectory::ToAronType())
285 navigation::core::arondto::LocalTrajectory::ToAronType())
304 navigation::location::arondto::Location::ToAronType())
308 navigation::core::arondto::Graph::ToAronType())
313 navigation::human::arondto::Human::ToAronType())
318 navigation::memory::arondto::LaserScannerFeatures::ToAronType())
325 navigation::algorithms::arondto::Room::ToAronType())
348 tasks.visuTask->start();
357 tasks.visuTask->stop();
358 tasks.visuTask =
nullptr;
376 return "navigation_memory";
386 tab.locationGraph.setup(*
this);
396 tab.locationGraph.update(*
this);
411 reloadSnapshot.setLabel(
"Reload from Snapshot '" + owner.properties.snapshotToLoad +
420 grid.
add(
Label(
"Visualize Locations"), {.row = row, .column = 0})
424 grid.
add(
Label(
"Visualize Graph Edges"), {.row = row, .column = 0})
430 group.setLabel(
"Locations");
438 owner.loadSnapshot();
442 std::scoped_lock lock(owner.propertiesMutex);
464 std::scoped_lock lock(propertiesMutex);
465 pp = properties.locationGraph;
470 while (tasks.visuTask and not tasks.visuTask->isStopped())
475 std::scoped_lock lock(propertiesMutex);
476 pp = properties.locationGraph;
479 std::vector<viz::Layer> layers;
485 if (properties.locationGraph.visuRelativeLocations)
487 visu.drawLocations(objClient, layers);
491 visu.drawLocations(layers);
499 if (properties.locationGraph.visuRelativeLocations)
501 visu.drawGraphs(objClient, layers);
505 visu.drawGraphs(layers);
513 visu.drawCostmaps(layers, p.zOffsetCostmap);
527 visu.drawRooms(layers);
531 if (p.visuLaserScannerFeatures)
534 visu.drawLaserScannerFeatures(layers);
539 metronome.waitForNextTick();
544 Component::loadSnapshot()
546 if (properties.snapshotToLoad.empty())
549 <<
"Not loading any predefined locations or graphs as the params was empty ...";
553 const std::vector<std::string> snapshotsToLoad =
554 simox::alg::split(properties.snapshotToLoad,
";",
true);
556 for (
const auto& snapshotToLoad : snapshotsToLoad)
560 <<
" in package '" << properties.packageToLoad <<
"' ...";
562 armarx::priorknowledge::navigation_graphs::NavigationGraphFinder f(
563 properties.packageToLoad,
564 armarx::priorknowledge::navigation_graphs::NavigationGraphFinder::
567 if (
auto graph = f.find(snapshotToLoad); graph.has_value())
569 const std::string graphId = graph->getID();
570 ARMARX_DEBUG <<
"Found graph " << graphId <<
" with path: " << graph->getFullPath();
578 std::filesystem::path locationsFilePath =
579 graph->getFullPath() /
"locations.json";
580 if (not std::filesystem::is_regular_file(locationsFilePath))
597 std::ifstream ifs(locationsFilePath);
598 const std::string content((std::istreambuf_iterator<char>(ifs)),
599 (std::istreambuf_iterator<char>()));
602 nlohmann::json js = nlohmann::json::parse(content);
608 for (
const auto& location : locations)
611 if (location->type !=
615 <<
"Navigation memory received location '" + location->id.name +
616 "' which is not of type "
617 "'armarx::priorknowledge::util::LocationType:"
618 ":FRAMED_LOCATION' (e.g. you specified a "
619 "FRAMED_BOXED_LOCATION?). Only FramedLocations (i.e. "
620 "poses in 3D space) are navigatable. Ignoring this "
622 "but please check the location.json file.";
626 auto& framedLocation =
627 dynamic_cast<armarx::priorknowledge::util::FramedLocation&
>(
630 navigation::location::arondto::Location loc;
633 loc.framedPose.header.frame = framedLocation.frame;
634 loc.framedPose.header.agent = framedLocation.agent;
635 loc.framedPose.pose = framedLocation.pose;
636 toAron(loc.names, framedLocation.names);
641 up.referencedTime = now;
643 up.arrivedTime = now;
645 up.instancesData = {loc.toAron()};
657 std::filesystem::path graphFilesPath = graph->getFullPath() /
"Graph";
659 if (not std::filesystem::is_directory(graphFilesPath))
672 navigation::core::arondto::Graph g;
676 up.referencedTime = now;
677 up.arrivedTime = now;
680 up.instancesData = {g.toAron()};
688 ARMARX_DEBUG <<
"Loading graphs from " << graphFilesPath;
697 for (
const auto& graphFile : std::filesystem::directory_iterator(
700 if (std::filesystem::is_regular_file(graphFile.path()) and
701 simox::alg::ends_with(graphFile.path().filename(),
704 const std::string graphName = graphFile.path().stem();
707 ARMARX_DEBUG <<
"Loading graph `" << graphName <<
" `from file `"
708 << graphFile.path() <<
"`.";
710 navigation::core::arondto::Graph g;
712 std::ifstream ifs(graphFile.path());
713 const std::string content((std::istreambuf_iterator<char>(ifs)),
714 (std::istreambuf_iterator<char>()));
716 const nlohmann::json j = nlohmann::json::parse(content);
718 const auto& jEdges = j.at(
"edges");
719 const auto& jVertices = j.at(
"vertices");
721 for (
const auto& jVertex : jVertices)
723 const armarx::armem::MemoryID vertexLocationMemoryId(
724 jVertex.at(
"locationID"));
726 armarx::navigation::core::arondto::Vertex
v;
727 v.vertexID = jVertex.at(
"vertexID");
728 toAron(
v.locationID, vertexLocationMemoryId);
730 v.locationID.instanceIndex = 0;
732 g.vertices.push_back(v);
735 for (
const auto& jEdge : jEdges)
737 std::pair<std::int64_t, std::int64_t> edgeSourceTargetPair;
738 jEdge.get_to(edgeSourceTargetPair);
740 armarx::navigation::core::arondto::Edge e;
741 e.sourceVertexID = edgeSourceTargetPair.first;
742 e.targetVertexID = edgeSourceTargetPair.second;
743 g.edges.push_back(e);
748 up.referencedTime = now;
749 up.arrivedTime = now;
752 up.instancesData = {g.toAron()};
763 std::filesystem::path roomsFilePath = graph->getFullPath() /
"rooms.json";
764 if (not std::filesystem::is_regular_file(roomsFilePath))
781 std::ifstream ifs(roomsFilePath);
782 const std::string content((std::istreambuf_iterator<char>(ifs)),
783 (std::istreambuf_iterator<char>()));
786 const nlohmann::json js = nlohmann::json::parse(content);
789 js.at(
"rooms").get<std::map<std::string, nlohmann::json>>();
790 ARMARX_INFO <<
"Found " << rooms.size() <<
" rooms.";
791 for (
const auto& [roomId, j] : rooms)
793 auto roomMemoryId = providerID;
796 const std::string roomMemoryIdStr = roomMemoryId.str();
798 if (j.find(
"polygon") == j.end())
801 <<
"' has no 'polygon' member. Skipping "
806 if (j.find(
"height") == j.end())
809 <<
"' has no 'height' member. "
810 "Skipping this entity.";
814 navigation::algorithms::arondto::Room room;
815 j.at(
"polygon").get_to(room.polygon);
816 j.at(
"height").get_to(room.height);
820 for (
auto& point : room.polygon)
828 up.referencedTime = now;
830 up.arrivedTime = now;
831 up.entityID = armarx::armem::MemoryID(roomMemoryIdStr);
832 up.instancesData = {room.toAron()};
840 <<
" --> graph: '" << graphId <<
"'";
844 ARMARX_WARNING <<
"Could not load NavigationMemory '" << snapshotToLoad
845 <<
"'. Continue with empty memory.";
855 store(
const std::map<armem::MemoryID, core::Graph>& graphs,
856 const std::filesystem::path& baseDirectory)
859 std::filesystem::create_directories(baseDirectory);
861 for (
const auto& [memoryId, graph] : graphs)
863 const std::filesystem::path nestedSubDir =
864 std::filesystem::path(memoryId.providerSegmentName) / memoryId.coreSegmentName;
865 const std::filesystem::path dir = baseDirectory / nestedSubDir;
867 std::filesystem::create_directories(dir);
872 std::vector<std::pair<std::size_t, std::size_t>> outgoingEdges;
873 std::transform(graph.m_edges.begin(),
875 std::back_inserter(outgoingEdges),
877 { return std::make_pair(edge.m_source, edge.m_target); });
879 j[
"edges"] = outgoingEdges;
882 for (
const auto& vertex : graph.m_vertices)
885 armarx::armem::MemoryID locationId;
886 fromAron(vertex.m_property.aron.locationID, locationId);
888 nlohmann::json jVertex;
890 jVertex[
"vertexID"] = vertex.m_property.aron.vertexID;
892 j[
"vertices"].push_back(jVertex);
896 const std::filesystem::path filename = dir / (memoryId.entityName +
".json");
898 std::ofstream ofs(filename);
899 ofs << std::setw(4) << j;
906 store(
const std::map<armem::MemoryID, location::arondto::Location>& locations,
907 const std::filesystem::path& baseDirectory)
910 std::filesystem::create_directories(baseDirectory);
913 std::map<std::string, nlohmann::json> js;
915 for (
const auto& [memoryId, location] : locations)
917 auto& j = js[memoryId.providerSegmentName];
919 if (j.count(
"locations") == 0)
923 j[
"locations"] = std::map<std::string, nlohmann::json>{};
927 nlohmann::json framedPose;
929 framedPose[
"agent"] = location.framedPose.header.agent;
930 framedPose[
"frame"] = location.framedPose.header.frame;
933 std::vector<std::vector<float>> poseAsVec;
935 framedPose[
"pose"] = poseAsVec;
937 jLoc[
"framedPose"] = framedPose;
939 auto entityId = memoryId.getEntityID();
940 j[
"locations"][entityId.entityName] = jLoc;
944 for (
const auto& [providerId, j] : js)
946 const std::filesystem::path subDir = std::filesystem::path(providerId);
947 const std::filesystem::path dir = baseDirectory / subDir;
949 if (not std::filesystem::exists(dir))
951 std::filesystem::create_directories(dir);
954 const std::filesystem::path filename = dir /
"locations.json";
956 std::ofstream ofs(filename);
957 ofs << std::setw(4) << j;
968 const Ice::Current& )
977 const std::map<armem::MemoryID, location::arondto::Location> locations =
978 [&locationCoreSegment]()
980 std::map<armem::MemoryID, location::arondto::Location> locations;
990 locations[entity.
id()].fromAron(instance->data());
1002 const auto graphs = [&graphCoreSegment]()
1004 std::map<armem::MemoryID, core::Graph> graphs;
1015 navigation::core::arondto::Graph
aron;
1016 aron.fromAron(instance->data());
1032 store(locations, baseDirectory);
1041 Component::loadSpecialRooms()
1047 const auto objectFinder = objClient.getObjectFinder();
1048 const auto objectPoseMap = objClient.fetchObjectPosesAsMap();
1050 for (
const auto& [providerName, objectPose] : objectPoseMap)
1052 const auto objectInfoOpt = objectFinder.findObject(objectPose.objectID);
1053 if (not objectInfoOpt)
1055 ARMARX_WARNING <<
"Could not find object with id '" << objectPose.objectID
1060 const auto& objectInfo = *objectInfoOpt;
1066 const auto articulatedModelPathOpt = objectInfo.getArticulatedModel();
1067 if (not articulatedModelPathOpt)
1070 <<
"' is not an articulated model.";
1074 const auto& articulatedModelPath = *articulatedModelPathOpt;
1075 if (not std::filesystem::is_regular_file(articulatedModelPath.absolutePath))
1078 <<
"' has no articulated model.";
1084 VirtualRobot::RobotIO::loadRobot(articulatedModelPath.absolutePath.string(),
1085 VirtualRobot::RobotIO::eStructure);
1087 <<
QUOTED(articulatedModelPath.absolutePath.string());
1090 articulatedObject->setJointValues(objectPose.objectJointValues);
1091 articulatedObject->setGlobalPose(objectPose.objectPoseGlobal);
1094 const auto affordances = articulatedObject->getAffordances();
1095 for (
const auto& affordanceLocation : affordances)
1097 for (
const auto& affordance : affordanceLocation.affordances)
1099 if (simox::alg::to_lower(affordance.type) ==
"containable")
1104 for (
const std::shared_ptr<VirtualRobot::Primitive::Primitive>&
1105 primitive : affordance.primitiveRepresentation)
1107 if (primitive->type == VirtualRobot::Primitive::Box::TYPE)
1109 VirtualRobot::Primitive::Box* box =
1110 std::dynamic_pointer_cast<VirtualRobot::Primitive::Box>(
1116 const Eigen::Isometry3f& root_T_prim =
1117 affordanceLocation.pose.pose;
1118 const Eigen::Isometry3f global_T_prim =
1119 Eigen::Isometry3f{articulatedObject->getGlobalPose()} *
1122 const Eigen::Isometry3f prim_T_affordance{
1123 primitive->transform};
1124 const Eigen::Isometry3f global_T_affordance =
1125 global_T_prim * prim_T_affordance;
1127 const Eigen::Vector3f boxSize{box->width,
1134 const Eigen::Vector3f corner1 =
1135 Eigen::Vector3f{boxSize.x() / 2,
1138 const Eigen::Vector3f corner2 =
1139 Eigen::Vector3f{-boxSize.x() / 2,
1142 const Eigen::Vector3f corner3 =
1143 Eigen::Vector3f{-boxSize.x() / 2,
1146 const Eigen::Vector3f corner4 =
1147 Eigen::Vector3f{boxSize.x() / 2,
1153 std::vector<Eigen::Vector3f> polygon;
1155 polygon.emplace_back(global_T_affordance * corner1);
1156 polygon.emplace_back(global_T_affordance * corner2);
1157 polygon.emplace_back(global_T_affordance * corner3);
1158 polygon.emplace_back(global_T_affordance * corner4);
1161 navigation::algorithms::arondto::Room room;
1162 room.name =
"inside";
1163 room.polygon = polygon;
1164 room.height = boxSize.z();
1171 objectPose.objectID.dataset() +
1172 "::" + objectPose.objectID.className();
1177 up.confidence = 1.0;
1178 up.referencedTime = now;
1180 up.arrivedTime = now;
1182 up.instancesData = {room.toAron()};
1197 const auto areas = objectInfo.file(
".json",
"_areas",
true);
1198 ARMARX_VERBOSE <<
"Checking for areas.json file at " << areas.absolutePath;
1199 if (std::filesystem::exists(areas.absolutePath))
1201 ARMARX_INFO <<
"Found areas.json file for object '" << objectPose.objectID
1205 std::ifstream ifs(areas.absolutePath);
1206 const auto json = nlohmann::json::parse(ifs);
1208 const std::map<std::string, nlohmann::json> jAreas = json.at(
"areas");
1209 ARMARX_INFO <<
"Found " << jAreas.size() <<
" areas.";
1211 for (
const auto& [areaName, jArea] : jAreas)
1213 const std::vector<Eigen::Vector2f> polygon =
1214 jArea.at(
"polygon").get<std::vector<Eigen::Vector2f>>();
1215 const float height = jArea.at(
"height").get<
float>();
1221 providerID.providerSegmentName =
1222 objectPose.objectID.dataset() +
"::" + objectPose.objectID.className();
1227 navigation::algorithms::arondto::Room room;
1229 objectPose.objectID.getClassID().withInstanceName(areaName).str();
1231 room.height = height;
1234 const Eigen::Isometry3f global_T_object{objectPose.objectPoseGlobal};
1235 for (
auto& point : room.polygon)
1238 point = global_T_object * point;
1252 up.confidence = 1.0;
1253 up.referencedTime = now;
1255 up.arrivedTime = now;
1256 up.entityID = providerID.withEntityName(areaName);
1257 up.instancesData = {room.toAron()};
1263 if (
c.updates.empty())
1269 ARMARX_INFO <<
"Sending " <<
c.updates.size() <<
" special rooms to memory";