38 #include <Ice/Current.h>
40 #include <SimoxUtility/algorithm/string/string_tools.h>
51 #include <ArmarXCore/interface/core/PackagePath.h>
67 #include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
72 #include <armarx/navigation/algorithms/aron/Costmap.aron.generated.h>
73 #include <armarx/navigation/algorithms/aron/Room.aron.generated.h>
75 #include <armarx/navigation/core/aron/Graph.aron.generated.h>
76 #include <armarx/navigation/core/aron/Trajectory.aron.generated.h>
78 #include <armarx/navigation/human/aron/Human.aron.generated.h>
80 #include <armarx/navigation/memory/aron/LaserScannerFeatures.aron.generated.h>
85 #include <nlohmann/json_fwd.hpp>
108 def->optional(properties.snapshotToLoad,
110 "Snapshot to load at start up \n"
111 "(e.g. 'R003' to load 'PriorKnowledgeData/navigation-graphs/R003').");
113 def->optional(properties.packageToLoad,
115 "Package to load snapshot at start up \n"
116 "(e.g. 'PriorKnowledgeData').");
118 def->optional(properties.locationGraph.visuLocations,
119 "p.locationGraph.visuLocation",
120 "Enable visualization of locations.");
123 properties.locationGraph.visuRelativeLocations,
124 "p.locationGraph.visuRelativeLocation",
125 "Enable visualization of relative locations (currently supported: robots, objects).");
127 def->optional(properties.locationGraph.visuGraphEdges,
128 "p.locationGraph.visuGraphEdges",
129 "Enable visualization of navigation graph edges.");
132 properties.visuCostmaps,
"p.visuCostmaps",
"Enable visualization of costmaps.");
133 def->optional(properties.zOffsetCostmap,
135 "Adjust the height of the visualized costmap.");
137 def->optional(properties.visuHumans,
"p.visuHumans",
"Enable visualization of humans.");
139 def->optional(properties.visuTransparent,
141 "Enable visualization of humans a bit transparent.");
143 def->optional(properties.visuHumanMaxAgeMs,
144 "p.visuHumanMaxAgeMs",
145 "The maximum age of humans to be drawn in ms.");
147 def->optional(properties.visuRooms,
"p.visuRooms",
"Enable visualization of rooms.");
149 def->optional(properties.visuFrequency,
151 "Visualization frequeny of locations and graph edges [Hz].");
156 properties.coreSeg.parameterization.maxHistorySize,
157 "p.coreSeg.parameterization.maxHistorySize",
158 "Max history size of the " +
162 def->optional(properties.coreSeg.costmap.maxHistorySize,
163 "p.coreSeg.costmap.maxHistorySize",
164 "Max history size of the " +
169 properties.coreSeg.resultsGlobalPlanner.maxHistorySize,
170 "p.coreSeg.resultsGlobalPlanner.maxHistorySize",
171 "Max history size of the " +
175 def->optional(properties.coreSeg.resultsLocalPlanner.maxHistorySize,
176 "p.coreSeg.resultsLocalPlanner.maxHistorySize",
177 "Max history size of the " +
181 def->optional(properties.coreSeg.events.maxHistorySize,
182 "p.coreSeg.events.maxHistorySize",
183 "Max history size of the " +
187 def->optional(properties.coreSeg.exceptions.maxHistorySize,
188 "p.coreSeg.exceptions.maxHistorySize",
189 "Max history size of the " +
193 def->optional(properties.coreSeg.location.maxHistorySize,
194 "p.coreSeg.location.maxHistorySize",
195 "Max history size of the " +
199 def->optional(properties.coreSeg.graph.maxHistorySize,
200 "p.coreSeg.graph.maxHistorySize",
201 "Max history size of the " +
205 def->optional(properties.coreSeg.human.maxHistorySize,
206 "p.coreSeg.human.maxHistorySize",
207 "Max history size of the " +
212 properties.coreSeg.laserScannerFeatures.maxHistorySize,
213 "p.coreSeg.laserScannerFeatures.maxHistorySize",
214 "Max history size of the " +
218 def->optional(properties.coreSeg.rooms.maxHistorySize,
219 "p.coreSeg.rooms.maxHistorySize",
220 "Max history size of the " +
244 .setMaxHistorySize(properties.coreSeg.parameterization.maxHistorySize);
248 algorithms::arondto::Costmap::ToAronType())
249 .setMaxHistorySize(properties.coreSeg.costmap.maxHistorySize);
253 navigation::core::arondto::GlobalTrajectory::ToAronType())
254 .setMaxHistorySize(properties.coreSeg.resultsGlobalPlanner.maxHistorySize);
258 navigation::core::arondto::LocalTrajectory::ToAronType())
259 .setMaxHistorySize(properties.coreSeg.resultsLocalPlanner.maxHistorySize);
267 .setMaxHistorySize(properties.coreSeg.events
272 .setMaxHistorySize(properties.coreSeg.exceptions
277 navigation::location::arondto::Location::ToAronType())
278 .setMaxHistorySize(properties.coreSeg.location.maxHistorySize);
281 navigation::core::arondto::Graph::ToAronType())
282 .setMaxHistorySize(properties.coreSeg.graph.maxHistorySize);
286 navigation::human::arondto::Human::ToAronType())
287 .setMaxHistorySize(properties.coreSeg.human.maxHistorySize);
291 navigation::memory::arondto::LaserScannerFeatures::ToAronType())
292 .setMaxHistorySize(properties.coreSeg.laserScannerFeatures.maxHistorySize);
298 navigation::algorithms::arondto::Room::ToAronType())
299 .setMaxHistorySize(properties.coreSeg.rooms.maxHistorySize);
308 if (properties.locationGraph.visuRelativeLocations)
320 tasks.visuTask->start();
342 return "navigation_memory";
352 tab.locationGraph.setup(*
this);
362 tab.locationGraph.update(*
this);
386 grid.
add(
Label(
"Visualize Locations"), {.row = row, .column = 0})
390 grid.
add(
Label(
"Visualize Graph Edges"), {.row = row, .column = 0})
402 if (reloadSnapshot.wasClicked())
404 owner.loadSnapshot();
406 if (visuLocations.hasValueChanged() or visuGraphEdges.hasValueChanged())
408 std::scoped_lock lock(owner.propertiesMutex);
409 owner.properties.locationGraph.visuLocations = visuLocations.getValue();
410 owner.properties.locationGraph.visuGraphEdges = visuGraphEdges.getValue();
427 std::scoped_lock lock(propertiesMutex);
428 pp = properties.locationGraph;
433 while (tasks.visuTask and not tasks.visuTask->isStopped())
438 std::scoped_lock lock(propertiesMutex);
439 pp = properties.locationGraph;
442 std::vector<viz::Layer> layers;
445 if (properties.locationGraph.visuRelativeLocations)
457 if (properties.locationGraph.visuRelativeLocations)
470 visu.drawCostmaps(layers, p.visuCostmaps, p.zOffsetCostmap);
474 visu.drawHumans(layers,
480 visu.drawRooms(layers, p.visuRooms);
484 metronome.waitForNextTick();
489 Component::loadSnapshot()
491 if (properties.snapshotToLoad.empty())
494 <<
"Not loading any predefined locations or graphs as the params was empty ...";
498 const std::vector<std::string> snapshotsToLoad =
501 for (
const auto& snapshotToLoad : snapshotsToLoad)
504 ARMARX_INFO <<
"Loading snapshots from snapshot '" << snapshotToLoad <<
"' in package '"
505 << properties.packageToLoad <<
"' ...";
508 properties.packageToLoad,
512 if (
auto graph = f.find(snapshotToLoad); graph.has_value())
514 const std::string graphId = graph->getID();
515 ARMARX_DEBUG <<
"Found graph " << graphId <<
" with path: " << graph->getFullPath();
523 std::filesystem::path locationsFilePath =
524 graph->getFullPath() /
"locations.json";
525 if (not std::filesystem::is_regular_file(locationsFilePath))
527 ARMARX_WARNING <<
"Found no locations file for graph '" << graphId <<
"'.";
541 std::ifstream ifs(locationsFilePath);
542 const std::string content((std::istreambuf_iterator<char>(ifs)),
543 (std::istreambuf_iterator<char>()));
546 nlohmann::json js = nlohmann::json::parse(content);
552 for (
const auto& location : locations)
555 if (location->type !=
559 <<
"Navigation memory received location '" + location->id.name +
560 "' which is not of type "
561 "'armarx::priorknowledge::util::LocationType:"
562 ":FRAMED_LOCATION' (e.g. you specified a "
563 "FRAMED_BOXED_LOCATION?). Only FramedLocations (i.e. "
564 "poses in 3D space) are navigatable. Ignoring this "
566 "but please check the location.json file.";
570 auto& framedLocation =
574 navigation::location::arondto::Location loc;
577 loc.framedPose.header.
frame = framedLocation.frame;
578 loc.framedPose.header.agent = framedLocation.agent;
579 loc.framedPose.pose = framedLocation.pose;
580 toAron(loc.names, framedLocation.names);
585 up.referencedTime = now;
587 up.arrivedTime = now;
589 up.instancesData = {loc.toAron()};
601 std::filesystem::path graphFilesPath = graph->getFullPath() /
"Graph";
603 if (not std::filesystem::is_directory(graphFilesPath))
605 ARMARX_INFO <<
"Found no `Graph/` folder for graph '" << graphId <<
"'.";
619 up.referencedTime = now;
620 up.arrivedTime = now;
623 up.instancesData = {g.toAron()};
625 ARMARX_DEBUG <<
"Sending empty graph `" << snapshotToLoad <<
"` to memory.";
630 ARMARX_DEBUG <<
"Loading graphs from " << graphFilesPath;
639 for (
const auto& graphFile : std::filesystem::directory_iterator(
642 if (std::filesystem::is_regular_file(graphFile.path()) and
646 const std::string graphName = graphFile.path().stem();
649 ARMARX_DEBUG <<
"Loading graph `" << graphName <<
" `from file `"
650 << graphFile.path() <<
"`.";
654 std::ifstream ifs(graphFile.path());
655 const std::string content((std::istreambuf_iterator<char>(ifs)),
656 (std::istreambuf_iterator<char>()));
658 const nlohmann::json j = nlohmann::json::parse(content);
660 const auto& jEdges = j.at(
"edges");
661 const auto& jVertices = j.at(
"vertices");
663 for (
const auto& jVertex : jVertices)
666 jVertex.at(
"locationID"));
668 armarx::navigation::core::arondto::Vertex
v;
669 v.vertexID = jVertex.at(
"vertexID");
670 toAron(
v.locationID, vertexLocationMemoryId);
672 v.locationID.instanceIndex = 0;
674 g.vertices.push_back(
v);
677 for (
const auto& jEdge : jEdges)
679 std::pair<std::int64_t, std::int64_t> edgeSourceTargetPair;
680 jEdge.get_to(edgeSourceTargetPair);
682 armarx::navigation::core::arondto::Edge e;
683 e.sourceVertexID = edgeSourceTargetPair.first;
684 e.targetVertexID = edgeSourceTargetPair.second;
685 g.edges.push_back(e);
690 up.referencedTime = now;
691 up.arrivedTime = now;
694 up.instancesData = {g.toAron()};
705 std::filesystem::path roomsFilePath = graph->getFullPath() /
"rooms.json";
706 if (not std::filesystem::is_regular_file(roomsFilePath))
708 ARMARX_INFO <<
"Found no rooms file for graph '" << graphId <<
"'.";
723 std::ifstream ifs(roomsFilePath);
724 const std::string content((std::istreambuf_iterator<char>(ifs)),
725 (std::istreambuf_iterator<char>()));
728 const nlohmann::json js = nlohmann::json::parse(content);
731 js.at(
"rooms").get<std::map<std::string, nlohmann::json>>();
732 ARMARX_INFO <<
"Found " << rooms.size() <<
" rooms.";
733 for (
const auto& [roomId, j] : rooms)
735 auto roomMemoryId = providerID;
738 const std::string roomMemoryIdStr = roomMemoryId.str();
740 if (j.find(
"polygon") == j.end())
743 <<
"' has no 'polygon' member. Skipping "
748 if (j.find(
"height") == j.end())
751 <<
"' has no 'height' member. "
752 "Skipping this entity.";
756 navigation::algorithms::arondto::Room room;
757 j.at(
"polygon").get_to(room.polygon);
758 j.at(
"height").get_to(room.height);
762 for (
auto& point : room.polygon)
770 up.referencedTime = now;
772 up.arrivedTime = now;
774 up.instancesData = {room.toAron()};
781 ARMARX_INFO <<
"Loaded NavigationMemory '" << snapshotToLoad <<
"' --> graph: '"
786 ARMARX_WARNING <<
"Could not load NavigationMemory '" << snapshotToLoad
787 <<
"'. Continue with empty memory.";
797 store(
const std::map<armem::MemoryID, core::Graph>& graphs,
798 const std::filesystem::path& baseDirectory)
800 ARMARX_INFO <<
"Creating export directory `" << baseDirectory <<
"`.";
801 std::filesystem::create_directories(baseDirectory);
803 for (
const auto& [memoryId, graph] : graphs)
805 const std::filesystem::path nestedSubDir =
806 std::filesystem::path(memoryId.providerSegmentName) / memoryId.coreSegmentName;
807 const std::filesystem::path dir = baseDirectory / nestedSubDir;
809 std::filesystem::create_directories(dir);
814 std::vector<std::pair<std::size_t, std::size_t>> outgoingEdges;
817 std::back_inserter(outgoingEdges),
819 { return std::make_pair(edge.m_source, edge.m_target); });
821 j[
"edges"] = outgoingEdges;
824 for (
const auto& vertex : graph.m_vertices)
828 fromAron(vertex.m_property.aron.locationID, locationId);
830 nlohmann::json jVertex;
832 jVertex[
"vertexID"] = vertex.m_property.aron.vertexID;
834 j[
"vertices"].push_back(jVertex);
838 const std::filesystem::path
filename = dir / (memoryId.entityName +
".json");
841 ofs << std::setw(4) << j;
848 store(
const std::map<armem::MemoryID, location::arondto::Location>& locations,
849 const std::filesystem::path& baseDirectory)
851 ARMARX_INFO <<
"Creating export directory `" << baseDirectory <<
"`.";
852 std::filesystem::create_directories(baseDirectory);
855 std::map<std::string, nlohmann::json> js;
857 for (
const auto& [memoryId, location] : locations)
859 auto& j = js[memoryId.providerSegmentName];
861 if (j.count(
"locations") == 0)
867 nlohmann::json framedPose;
869 framedPose[
"agent"] = location.framedPose.header.agent;
870 framedPose[
"frame"] = location.framedPose.header.frame;
873 std::vector<std::vector<float>> poseAsVec;
875 framedPose[
"pose"] = poseAsVec;
877 jLoc[
"framedPose"] = framedPose;
879 auto entityId = memoryId.getEntityID();
880 j[
"locations"][entityId.entityName] = jLoc;
884 for (
const auto& [providerId, j] : js)
886 const std::filesystem::path subDir = std::filesystem::path(providerId);
887 const std::filesystem::path dir = baseDirectory / subDir;
889 if (not std::filesystem::exists(dir))
891 std::filesystem::create_directories(dir);
894 const std::filesystem::path
filename = dir /
"locations.json";
897 ofs << std::setw(4) << j;
908 const Ice::Current& )
917 const std::map<armem::MemoryID, location::arondto::Location> locations =
918 [&locationCoreSegment]()
920 std::map<armem::MemoryID, location::arondto::Location> locations;
930 locations[entity.id()].fromAron(instance->data());
942 const auto graphs = [&graphCoreSegment]()
944 std::map<armem::MemoryID, core::Graph> graphs;
956 aron.fromAron(instance->data());
972 store(locations, baseDirectory);