29 #include <SimoxUtility/algorithm/string/string_tools.h>
51 #include <armarx/navigation/algorithms/aron/Costmap.aron.generated.h>
53 #include <armarx/navigation/core/aron/Graph.aron.generated.h>
54 #include <armarx/navigation/core/aron/Location.aron.generated.h>
55 #include <armarx/navigation/core/aron/Trajectory.aron.generated.h>
56 #include <armarx/navigation/core/aron/Twist.aron.generated.h>
58 #include <armarx/navigation/human/aron/Human.aron.generated.h>
60 #include <armarx/navigation/memory/aron/LaserScannerFeatures.aron.generated.h>
62 #include <armarx/navigation/rooms/aron/Room.aron.generated.h>
88 def->optional(properties.snapshotToLoad,
90 "Snapshot to load at start up \n"
91 "(e.g. 'R003' to load 'PriorKnowledgeData/navigation-graphs/R003').");
93 def->optional(properties.packageToLoad,
95 "Package to load snapshot at start up \n"
96 "(e.g. 'PriorKnowledgeData').");
98 def->optional(properties.locationGraph.visuLocations,
99 "p.locationGraph.visuLocation",
100 "Enable visualization of locations.");
103 properties.locationGraph.visuRelativeLocations,
104 "p.locationGraph.visuRelativeLocation",
105 "Enable visualization of relative locations (currently supported: robots, objects).");
107 def->optional(properties.locationGraph.visuGraphEdges,
108 "p.locationGraph.visuGraphEdges",
109 "Enable visualization of navigation graph edges.");
112 properties.visuCostmaps,
"p.visuCostmaps",
"Enable visualization of costmaps.");
113 def->optional(properties.zOffsetCostmap,
115 "Adjust the height of the visualized costmap.");
117 def->optional(properties.visuHumans,
"p.visuHumans",
"Enable visualization of humans.");
119 def->optional(properties.visuTransparent,
121 "Enable visualization of humans a bit transparent.");
123 def->optional(properties.visuHumanMaxAgeMs,
124 "p.visuHumanMaxAgeMs",
125 "The maximum age of humans to be drawn in ms.");
127 def->optional(properties.visuRooms,
"p.visuRooms",
"Enable visualization of rooms.");
129 def->optional(properties.visuFrequency,
131 "Visualization frequeny of locations and graph edges [Hz].");
154 algorithms::arondto::Costmap::ToAronType());
157 navigation::core::arondto::GlobalTrajectory::ToAronType());
159 navigation::core::arondto::LocalTrajectory::ToAronType());
171 navigation::location::arondto::Location::ToAronType());
173 navigation::core::arondto::Graph::ToAronType());
176 navigation::human::arondto::Human::ToAronType());
180 navigation::memory::arondto::LaserScannerFeatures::ToAronType())
181 .setMaxHistorySize(properties.laserScannerFeaturesMaxHistorySize);
186 navigation::rooms::arondto::Room::ToAronType());
195 if (properties.locationGraph.visuRelativeLocations)
207 tasks.visuTask->start();
229 return "navigation_memory";
238 tab.locationGraph.setup(*
this);
248 tab.locationGraph.update(*
this);
258 reloadSnapshot =
Button();
259 reloadSnapshot.setLabel(
"Reload from Snapshot '" + owner.properties.snapshotToLoad +
262 visuLocations.setValue(owner.properties.locationGraph.visuLocations);
263 visuGraphEdges.setValue(owner.properties.locationGraph.visuLocations);
265 grid.
add(reloadSnapshot, {row, 0}, {1, 2});
268 grid.
add(
Label(
"Visualize Locations"), {row, 0}).add(visuLocations, {row, 1});
271 grid.
add(
Label(
"Visualize Graph Edges"), {row, 0}).add(visuGraphEdges, {row, 1});
282 if (reloadSnapshot.wasClicked())
284 owner.loadSnapshot();
286 if (visuLocations.hasValueChanged() or visuGraphEdges.hasValueChanged())
288 std::scoped_lock lock(owner.propertiesMutex);
289 owner.properties.locationGraph.visuLocations = visuLocations.getValue();
290 owner.properties.locationGraph.visuGraphEdges = visuGraphEdges.getValue();
307 std::scoped_lock lock(propertiesMutex);
308 pp = properties.locationGraph;
313 while (tasks.visuTask and not tasks.visuTask->isStopped())
318 std::scoped_lock lock(propertiesMutex);
319 pp = properties.locationGraph;
322 std::vector<viz::Layer> layers;
326 if (properties.locationGraph.visuRelativeLocations)
338 if (properties.locationGraph.visuRelativeLocations)
351 visu.drawCostmaps(layers, p.visuCostmaps, p.zOffsetCostmap);
355 visu.drawHumans(layers,
361 visu.drawRooms(layers, p.visuRooms);
365 metronome.waitForNextTick();
370 Component::loadSnapshot()
372 if (properties.snapshotToLoad.empty())
375 <<
"Not loading any predefined locations or graphs as the params was empty ...";
379 const std::vector<std::string> snapshotsToLoad =
382 for (
const auto& snapshotToLoad : snapshotsToLoad)
385 ARMARX_INFO <<
"Loading snapshots from snapshot '" << snapshotToLoad
386 <<
"' in package '" << properties.packageToLoad <<
"' ...";
389 properties.packageToLoad,
393 if (
auto graph = f.find(snapshotToLoad); graph.has_value())
395 const std::string graphId = graph->getID();
396 ARMARX_DEBUG <<
"Found graph " << graphId <<
" with path: " << graph->getFullPath();
404 std::filesystem::path locationsFilePath =
405 graph->getFullPath() /
"locations.json";
406 if (not std::filesystem::is_regular_file(locationsFilePath))
408 ARMARX_WARNING <<
"Found no locations file for graph '" << graphId <<
"'.";
422 std::ifstream ifs(locationsFilePath);
423 const std::string content((std::istreambuf_iterator<char>(ifs)),
424 (std::istreambuf_iterator<char>()));
427 nlohmann::json js = nlohmann::json::parse(content);
433 for (
const auto& location : locations)
436 if (location->type !=
440 <<
"Navigation memory received location '" + location->id.name +
441 "' which is not of type "
442 "'armarx::priorknowledge::util::LocationType:"
443 ":FRAMED_LOCATION' (e.g. you specified a "
444 "FRAMED_BOXED_LOCATION?). Only FramedLocations (i.e. "
445 "poses in 3D space) are navigatable. Ignoring this "
447 "but please check the location.json file.";
451 auto& framedLocation =
455 navigation::location::arondto::Location loc;
458 loc.framedPose.header.
frame = framedLocation.frame;
459 loc.framedPose.header.agent = framedLocation.agent;
460 loc.framedPose.pose = framedLocation.pose;
461 toAron(loc.names, framedLocation.names);
466 up.referencedTime = now;
468 up.arrivedTime = now;
470 up.instancesData = {loc.toAron()};
482 std::filesystem::path graphFilesPath = graph->getFullPath() /
"Graph";
484 if (not std::filesystem::is_directory(graphFilesPath))
486 ARMARX_INFO <<
"Found no `Graph/` folder for graph '" << graphId <<
"'.";
500 up.referencedTime = now;
501 up.arrivedTime = now;
504 up.instancesData = {g.toAron()};
506 ARMARX_DEBUG <<
"Sending empty graph `" << snapshotToLoad
512 ARMARX_DEBUG <<
"Loading graphs from " << graphFilesPath;
521 for (
const auto& graphFile : std::filesystem::directory_iterator(
524 if (std::filesystem::is_regular_file(graphFile.path()) and
528 const std::string graphName = graphFile.path().stem();
531 ARMARX_DEBUG <<
"Loading graph `" << graphName <<
" `from file `"
532 << graphFile.path() <<
"`.";
536 std::ifstream ifs(graphFile.path());
537 const std::string content((std::istreambuf_iterator<char>(ifs)),
538 (std::istreambuf_iterator<char>()));
541 const nlohmann::json j = nlohmann::json::parse(content);
543 const auto& jEdges = j.at(
"edges");
544 const auto& jVertices = j.at(
"vertices");
546 for (
const auto& jVertex : jVertices)
549 jVertex.at(
"locationID"));
551 armarx::navigation::core::arondto::Vertex
v;
552 v.vertexID = jVertex.at(
"vertexID");
553 toAron(
v.locationID, vertexLocationMemoryId);
555 v.locationID.instanceIndex = 0;
557 g.vertices.push_back(
v);
560 for (
const auto& jEdge : jEdges)
562 std::pair<std::int64_t, std::int64_t> edgeSourceTargetPair;
563 jEdge.get_to(edgeSourceTargetPair);
565 armarx::navigation::core::arondto::Edge e;
566 e.sourceVertexID = edgeSourceTargetPair.first;
567 e.targetVertexID = edgeSourceTargetPair.second;
568 g.edges.push_back(e);
573 up.referencedTime = now;
574 up.arrivedTime = now;
577 up.instancesData = {g.toAron()};
588 std::filesystem::path roomsFilePath = graph->getFullPath() /
"rooms.json";
589 if (not std::filesystem::is_regular_file(roomsFilePath))
591 ARMARX_INFO <<
"Found no rooms file for graph '" << graphId <<
"'.";
606 std::ifstream ifs(roomsFilePath);
607 const std::string content((std::istreambuf_iterator<char>(ifs)),
608 (std::istreambuf_iterator<char>()));
611 const nlohmann::json js = nlohmann::json::parse(content);
614 js.at(
"rooms").get<std::map<std::string, nlohmann::json>>();
615 ARMARX_INFO <<
"Found " << rooms.size() <<
" rooms.";
616 for (
const auto& [roomId, j] : rooms)
618 auto roomMemoryId = providerID;
621 const std::string roomMemoryIdStr = roomMemoryId.str();
623 if (j.find(
"polygon") == j.end())
626 <<
"' has no 'polygon' member. Skipping "
631 if (j.find(
"height") == j.end())
634 <<
"' has no 'height' member. "
635 "Skipping this entity.";
639 navigation::rooms::arondto::Room room;
640 j.at(
"polygon").get_to(room.polygon);
641 j.at(
"height").get_to(room.height);
645 for (
auto& point : room.polygon)
653 up.referencedTime = now;
655 up.arrivedTime = now;
657 up.instancesData = {room.toAron()};
664 ARMARX_INFO <<
"Loaded NavigationMemory '" << snapshotToLoad
665 <<
"' --> graph: '" << graphId <<
"'";
669 ARMARX_WARNING <<
"Could not load NavigationMemory '" << snapshotToLoad
670 <<
"'. Continue with empty memory.";
676 store(
const std::map<armem::MemoryID, core::Graph>& graphs,
677 const std::filesystem::path& baseDirectory)
679 ARMARX_INFO <<
"Creating export directory `" << baseDirectory <<
"`.";
680 std::filesystem::create_directories(baseDirectory);
682 for (
const auto& [memoryId, graph] : graphs)
684 const std::filesystem::path nestedSubDir =
685 std::filesystem::path(memoryId.providerSegmentName) / memoryId.coreSegmentName;
686 const std::filesystem::path dir = baseDirectory / nestedSubDir;
688 std::filesystem::create_directories(dir);
693 std::vector<std::pair<std::size_t, std::size_t>> outgoingEdges;
696 std::back_inserter(outgoingEdges),
698 { return std::make_pair(edge.m_source, edge.m_target); });
700 j[
"edges"] = outgoingEdges;
703 for (
const auto& vertex : graph.m_vertices)
707 fromAron(vertex.m_property.aron.locationID, locationId);
709 nlohmann::json jVertex;
711 jVertex[
"vertexID"] = vertex.m_property.aron.vertexID;
713 j[
"vertices"].push_back(jVertex);
717 const std::filesystem::path
filename = dir / (memoryId.entityName +
".json");
720 ofs << std::setw(4) << j;
727 store(
const std::map<armem::MemoryID, location::arondto::Location>& locations,
728 const std::filesystem::path& baseDirectory)
730 ARMARX_INFO <<
"Creating export directory `" << baseDirectory <<
"`.";
731 std::filesystem::create_directories(baseDirectory);
734 std::map<std::string, nlohmann::json> js;
736 for (
const auto& [memoryId, location] : locations)
738 auto& j = js[memoryId.providerSegmentName];
740 if (j.count(
"locations") == 0)
746 nlohmann::json framedPose;
748 framedPose[
"agent"] = location.framedPose.header.agent;
749 framedPose[
"frame"] = location.framedPose.header.frame;
752 std::vector<std::vector<float>> poseAsVec;
754 framedPose[
"pose"] = poseAsVec;
756 jLoc[
"framedPose"] = framedPose;
758 auto entityId = memoryId.getEntityID();
759 j[
"locations"][entityId.entityName] = jLoc;
763 for (
const auto& [providerId, j] : js)
765 const std::filesystem::path subDir = std::filesystem::path(providerId);
766 const std::filesystem::path dir = baseDirectory / subDir;
768 if (not std::filesystem::exists(dir))
770 std::filesystem::create_directories(dir);
773 const std::filesystem::path
filename = dir /
"locations.json";
776 ofs << std::setw(4) << j;
785 const Ice::Current& current)
794 const std::map<armem::MemoryID, location::arondto::Location> locations =
795 [&locationCoreSegment]()
797 std::map<armem::MemoryID, location::arondto::Location> locations;
807 locations[entity.id()].fromAron(instance->data());
819 const auto graphs = [&graphCoreSegment]()
821 std::map<armem::MemoryID, core::Graph> graphs;
833 aron.fromAron(instance->data());
849 store(locations, baseDirectory);