Component.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package Navigation::ArmarXObjects::NavigationMemory
17  * @author Fabian Reister ( fabian dot reister at kit dot edu )
18  * @date 2021
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "Component.h"
24 
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstdint>
28 #include <filesystem>
29 #include <fstream>
30 #include <iomanip>
31 #include <iterator>
32 #include <map>
33 #include <mutex>
34 #include <string>
35 #include <utility>
36 #include <vector>
37 
38 #include <Ice/Current.h>
39 
40 #include <SimoxUtility/algorithm/string/string_tools.h>
41 
51 #include <ArmarXCore/interface/core/PackagePath.h>
54 
56 
67 #include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
68 #include <RobotAPI/libraries/aron/common/aron_conversions.h> // IWYU pragma: keep
69 #include <RobotAPI/libraries/aron/common/aron_conversions/names.h> // IWYU pragma: keep
71 
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>
83 
84 #include "Visu.h"
85 #include <nlohmann/json_fwd.hpp>
86 
88 {
89 
91 
94  {
97 
98  // Publish to a topic (passing the TopicListenerPrx).
99  // def->topic(myTopicListener);
100 
101  // Subscribe to a topic (passing the topic name).
102  // def->topic<PlatformUnitListener>("MyTopic");
103 
104  // Use (and depend on) another component (passing the ComponentInterfacePrx).
105  // def->component(myComponentProxy)
106 
107 
108  def->optional(properties.snapshotToLoad,
109  "p.snapshotToLoad",
110  "Snapshot to load at start up \n"
111  "(e.g. 'R003' to load 'PriorKnowledgeData/navigation-graphs/R003').");
112 
113  def->optional(properties.packageToLoad,
114  "p.packageToLoad",
115  "Package to load snapshot at start up \n"
116  "(e.g. 'PriorKnowledgeData').");
117 
118  def->optional(properties.locationGraph.visuLocations,
119  "p.locationGraph.visuLocation",
120  "Enable visualization of locations.");
121 
122  def->optional(
123  properties.locationGraph.visuRelativeLocations,
124  "p.locationGraph.visuRelativeLocation",
125  "Enable visualization of relative locations (currently supported: robots, objects).");
126 
127  def->optional(properties.locationGraph.visuGraphEdges,
128  "p.locationGraph.visuGraphEdges",
129  "Enable visualization of navigation graph edges.");
130 
131  def->optional(
132  properties.visuCostmaps, "p.visuCostmaps", "Enable visualization of costmaps.");
133  def->optional(properties.zOffsetCostmap,
134  "p.zOffsetCostmap",
135  "Adjust the height of the visualized costmap.");
136 
137  def->optional(properties.visuHumans, "p.visuHumans", "Enable visualization of humans.");
138 
139  def->optional(properties.visuTransparent,
140  "p.visuTransparent",
141  "Enable visualization of humans a bit transparent.");
142 
143  def->optional(properties.visuHumanMaxAgeMs,
144  "p.visuHumanMaxAgeMs",
145  "The maximum age of humans to be drawn in ms.");
146 
147  def->optional(properties.visuRooms, "p.visuRooms", "Enable visualization of rooms.");
148 
149  def->optional(properties.visuFrequency,
150  "p.visuFrequency",
151  "Visualization frequeny of locations and graph edges [Hz].");
152 
153  // Core segments (max history size)
154  {
155  def->optional(
156  properties.coreSeg.parameterization.maxHistorySize,
157  "p.coreSeg.parameterization.maxHistorySize",
158  "Max history size of the " +
160  " core segment.");
161 
162  def->optional(properties.coreSeg.costmap.maxHistorySize,
163  "p.coreSeg.costmap.maxHistorySize",
164  "Max history size of the " +
166  " core segment.");
167 
168  def->optional(
169  properties.coreSeg.resultsGlobalPlanner.maxHistorySize,
170  "p.coreSeg.resultsGlobalPlanner.maxHistorySize",
171  "Max history size of the " +
173  " core segment.");
174 
175  def->optional(properties.coreSeg.resultsLocalPlanner.maxHistorySize,
176  "p.coreSeg.resultsLocalPlanner.maxHistorySize",
177  "Max history size of the " +
179  " core segment.");
180 
181  def->optional(properties.coreSeg.events.maxHistorySize,
182  "p.coreSeg.events.maxHistorySize",
183  "Max history size of the " +
185  " core segment.");
186 
187  def->optional(properties.coreSeg.exceptions.maxHistorySize,
188  "p.coreSeg.exceptions.maxHistorySize",
189  "Max history size of the " +
191  " core segment.");
192 
193  def->optional(properties.coreSeg.location.maxHistorySize,
194  "p.coreSeg.location.maxHistorySize",
195  "Max history size of the " +
197  " core segment.");
198 
199  def->optional(properties.coreSeg.graph.maxHistorySize,
200  "p.coreSeg.graph.maxHistorySize",
201  "Max history size of the " +
202  QUOTED(navigation::graph::coreSegmentID.coreSegmentName) +
203  " core segment.");
204 
205  def->optional(properties.coreSeg.human.maxHistorySize,
206  "p.coreSeg.human.maxHistorySize",
207  "Max history size of the " +
209  " core segment.");
210 
211  def->optional(
212  properties.coreSeg.laserScannerFeatures.maxHistorySize,
213  "p.coreSeg.laserScannerFeatures.maxHistorySize",
214  "Max history size of the " +
216  " core segment.");
217 
218  def->optional(properties.coreSeg.rooms.maxHistorySize,
219  "p.coreSeg.rooms.maxHistorySize",
220  "Max history size of the " +
221  QUOTED(navigation::rooms::coreSegmentID.coreSegmentName) +
222  " core segment.");
223  }
224 
225  return def;
226  }
227 
229  {
230  workingMemory().setName("Navigation");
231  }
232 
233  void
235  {
236  // Topics and properties defined above are automagically registered.
237 
238  // Keep debug observer data until calling `sendDebugObserverBatch()`.
239  // (Requies the armarx::DebugObserverComponentPluginUser.)
240  // setDebugObserverBatchModeEnabled(true);
241 
242  workingMemory()
244  .setMaxHistorySize(properties.coreSeg.parameterization.maxHistorySize);
245 
246  workingMemory()
248  algorithms::arondto::Costmap::ToAronType())
249  .setMaxHistorySize(properties.coreSeg.costmap.maxHistorySize);
250 
251  workingMemory()
253  navigation::core::arondto::GlobalTrajectory::ToAronType())
254  .setMaxHistorySize(properties.coreSeg.resultsGlobalPlanner.maxHistorySize);
255 
256  workingMemory()
258  navigation::core::arondto::LocalTrajectory::ToAronType())
259  .setMaxHistorySize(properties.coreSeg.resultsLocalPlanner.maxHistorySize);
260  // workingMemory().addCoreSegment("Results_TrajectoryController",
261  // navigation::core::arondto::Twist::ToAronType());
262  // workingMemory().addCoreSegment("Results_SafetyGuard",
263  // navigation::core::arondto::Twist::ToAronType());
264 
265  workingMemory()
267  .setMaxHistorySize(properties.coreSeg.events
268  .maxHistorySize); //, armem::example::ExampleData::ToAronType());
269 
270  workingMemory()
272  .setMaxHistorySize(properties.coreSeg.exceptions
273  .maxHistorySize); //, armem::example::ExampleData::ToAronType());
274 
275  workingMemory()
277  navigation::location::arondto::Location::ToAronType())
278  .setMaxHistorySize(properties.coreSeg.location.maxHistorySize);
279  workingMemory()
281  navigation::core::arondto::Graph::ToAronType())
282  .setMaxHistorySize(properties.coreSeg.graph.maxHistorySize);
283 
284  workingMemory()
286  navigation::human::arondto::Human::ToAronType())
287  .setMaxHistorySize(properties.coreSeg.human.maxHistorySize);
288 
289  workingMemory()
291  navigation::memory::arondto::LaserScannerFeatures::ToAronType())
292  .setMaxHistorySize(properties.coreSeg.laserScannerFeatures.maxHistorySize);
293 
294  // workingMemory().addCoreSegment(memory::constants::HumanGroupCoreSegmentName,
295  // navigation::human::arondto::Human::ToAronType());
296  workingMemory()
298  navigation::algorithms::arondto::Room::ToAronType())
299  .setMaxHistorySize(properties.coreSeg.rooms.maxHistorySize);
300 
301  loadSnapshot();
302  }
303 
304  void
306  {
307  // connect readers if enabled
308  if (properties.locationGraph.visuRelativeLocations)
309  {
311  }
312 
313  // Setup the remote GUI.
314  {
317  }
318 
319  tasks.visuTask = new SimpleRunningTask<>([this]() { this->visuRun(); }, "Visualization");
320  tasks.visuTask->start();
321  }
322 
323  void
325  {
326  }
327 
328  void
330  {
331  }
332 
333  std::string
335  {
336  return GetDefaultName();
337  }
338 
339  std::string
341  {
342  return "navigation_memory";
343  }
344 
345  void
347  {
350 
351  // Setup the widgets.
352  tab.locationGraph.setup(*this);
353 
354  // Setup the layout.
355  VBoxLayout root = {tab.locationGraph.group, VSpacer()};
356  RemoteGui_createTab(getName(), root, &tab);
357  }
358 
359  void
361  {
362  tab.locationGraph.update(*this);
363  }
364 
365  void
367  {
372 
373  GridLayout grid;
374  int row = 0;
375  {
377  reloadSnapshot.setLabel("Reload from Snapshot '" + owner.properties.snapshotToLoad +
378  "'");
379 
380  visuLocations.setValue(owner.properties.locationGraph.visuLocations);
381  visuGraphEdges.setValue(owner.properties.locationGraph.visuLocations);
382 
383  grid.add(reloadSnapshot, {.row = row, .column = 0}, {.rows = 1, .columns = 2});
384  ++row;
385 
386  grid.add(Label("Visualize Locations"), {.row = row, .column = 0})
387  .add(visuLocations, {.row = row, .column = 1});
388  ++row;
389 
390  grid.add(Label("Visualize Graph Edges"), {.row = row, .column = 0})
391  .add(visuGraphEdges, {.row = row, .column = 1});
392  ++row;
393  }
394 
395  group = GroupBox({grid});
396  group.setLabel("Locations");
397  }
398 
399  void
401  {
402  if (reloadSnapshot.wasClicked())
403  {
404  owner.loadSnapshot();
405  }
406  if (visuLocations.hasValueChanged() or visuGraphEdges.hasValueChanged())
407  {
408  std::scoped_lock lock(owner.propertiesMutex);
409  owner.properties.locationGraph.visuLocations = visuLocations.getValue();
410  owner.properties.locationGraph.visuGraphEdges = visuGraphEdges.getValue();
411  }
412  }
413 
414  void
415  Component::visuRun()
416  {
417  memory::Visu visu{arviz,
423 
425  Properties p;
426  {
427  std::scoped_lock lock(propertiesMutex);
428  pp = properties.locationGraph;
429  p = properties;
430  }
431 
432  Metronome metronome(Frequency::HertzDouble(p.visuFrequency));
433  while (tasks.visuTask and not tasks.visuTask->isStopped())
434  {
435  ARMARX_TRACE;
436 
437  {
438  std::scoped_lock lock(propertiesMutex);
439  pp = properties.locationGraph;
440  }
441 
442  std::vector<viz::Layer> layers;
443 
444  // Locations
445  if (properties.locationGraph.visuRelativeLocations)
446  {
447  ARMARX_TRACE;
448  visu.drawLocations(objClient, layers, pp.visuLocations);
449  }
450  else
451  {
452  ARMARX_TRACE;
453  visu.drawLocations(layers, pp.visuLocations);
454  }
455 
456  // Graph Edges
457  if (properties.locationGraph.visuRelativeLocations)
458  {
459  ARMARX_TRACE;
460  visu.drawGraphs(objClient, layers, pp.visuGraphEdges);
461  }
462  else
463  {
464  ARMARX_TRACE;
465  visu.drawGraphs(layers, pp.visuGraphEdges);
466  }
467 
468  // Costmaps
469  ARMARX_TRACE;
470  visu.drawCostmaps(layers, p.visuCostmaps, p.zOffsetCostmap);
471 
472  // Humans
473  ARMARX_TRACE;
474  visu.drawHumans(layers,
475  p.visuHumans,
476  p.visuTransparent,
477  Duration::MilliSeconds(p.visuHumanMaxAgeMs));
478  // Rooms
479  ARMARX_TRACE;
480  visu.drawRooms(layers, p.visuRooms);
481 
482  arviz.commit(layers);
483 
484  metronome.waitForNextTick();
485  }
486  }
487 
488  void
489  Component::loadSnapshot()
490  {
491  if (properties.snapshotToLoad.empty())
492  {
494  << "Not loading any predefined locations or graphs as the params was empty ...";
495  return;
496  }
497 
498  const std::vector<std::string> snapshotsToLoad =
499  simox::alg::split(properties.snapshotToLoad, ";", true);
500 
501  for (const auto& snapshotToLoad : snapshotsToLoad)
502  {
503 
504  ARMARX_INFO << "Loading snapshots from snapshot '" << snapshotToLoad << "' in package '"
505  << properties.packageToLoad << "' ...";
506 
508  properties.packageToLoad,
510  DEFAULT_DIR_TO_IDS);
511 
512  if (auto graph = f.find(snapshotToLoad); graph.has_value())
513  {
514  const std::string graphId = graph->getID();
515  ARMARX_DEBUG << "Found graph " << graphId << " with path: " << graph->getFullPath();
516 
517  // Sometimes, we use the date before the snapshotname.
518  // In this case a symlink to the real data should be used (e.g. R003 and 2022-03-01_R003)
519 
520  // This loads the location. All locations are stored in a single locations.json file
521  // The file contains json with the framed poses (frame, agent, 4x4 matrix)
522  {
523  std::filesystem::path locationsFilePath =
524  graph->getFullPath() / "locations.json";
525  if (not std::filesystem::is_regular_file(locationsFilePath))
526  {
527  ARMARX_WARNING << "Found no locations file for graph '" << graphId << "'.";
528  }
529  else
530  {
531 
532  ARMARX_DEBUG << "Found the locations file";
534  armem::MemoryID providerID = workingMemory().id();
535  providerID.coreSegmentName = "Location";
536  providerID.providerSegmentName = graphId;
537 
538  const auto now = armem::Time::Now();
539  ARMARX_DEBUG << "Loading " << locationsFilePath;
540 
541  std::ifstream ifs(locationsFilePath);
542  const std::string content((std::istreambuf_iterator<char>(ifs)),
543  (std::istreambuf_iterator<char>()));
544 
545  // parse location as json. All files in Location folder must be valid json objects!
546  nlohmann::json js = nlohmann::json::parse(content);
547 
548  auto locations =
550  js);
551 
552  for (const auto& location : locations)
553  {
554  // we assert that only framedLocations are allowed. Everything else will be rejected!
555  if (location->type !=
557  {
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 "
565  "location "
566  "but please check the location.json file.";
567  continue;
568  }
569 
570  auto& framedLocation =
572  *location);
573 
574  navigation::location::arondto::Location loc;
575 
576  // set members of 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);
581 
582  // send commit to memory
583  auto& up = c.add();
584  up.confidence = 1.0;
585  up.referencedTime = now;
586  up.sentTime = now;
587  up.arrivedTime = now;
588  up.entityID = providerID.withEntityName(framedLocation.id.name);
589  up.instancesData = {loc.toAron()};
590  }
591 
592  ARMARX_DEBUG << "Sending locations to memory";
594  }
595  }
596 
597  {
598  // Next we load the graphs. The graph folder may contain several graphs, represented by different json files.
599  // Each of those graphs contains a list of files representing the vertices. The filename is the vertice id (ideally starting at 0).
600  // The file contains a json with the corresponding location name (as path) and the adjacent vertives (representing the directed outgoing edges).
601  std::filesystem::path graphFilesPath = graph->getFullPath() / "Graph";
602 
603  if (not std::filesystem::is_directory(graphFilesPath))
604  {
605  ARMARX_INFO << "Found no `Graph/` folder for graph '" << graphId << "'.";
606  ARMARX_INFO << "Creating empty graph.";
607 
609  armem::MemoryID providerID = workingMemory().id();
611  providerID.providerSegmentName = graphId;
612 
613  const auto now = armem::Time::Now();
614 
616 
617  auto& up = c.add();
618  up.confidence = 1.0;
619  up.referencedTime = now;
620  up.arrivedTime = now;
621  up.sentTime = now;
622  up.entityID = providerID.withEntityName(snapshotToLoad);
623  up.instancesData = {g.toAron()};
624 
625  ARMARX_DEBUG << "Sending empty graph `" << snapshotToLoad << "` to memory.";
626  iceAdapter().commit(c);
627  }
628  else
629  {
630  ARMARX_DEBUG << "Loading graphs from " << graphFilesPath;
631 
633  armem::MemoryID providerID = workingMemory().id();
635  providerID.providerSegmentName = graphId;
636 
637  const auto now = armem::Time::Now();
638 
639  for (const auto& graphFile : std::filesystem::directory_iterator(
640  graphFilesPath)) // iterate over the different graphs (json files)
641  {
642  if (std::filesystem::is_regular_file(graphFile.path()) and
643  simox::alg::ends_with(graphFile.path().filename(),
644  ".json")) // assure that its a json file
645  {
646  const std::string graphName = graphFile.path().stem();
647 
648 
649  ARMARX_DEBUG << "Loading graph `" << graphName << " `from file `"
650  << graphFile.path() << "`.";
651 
653 
654  std::ifstream ifs(graphFile.path());
655  const std::string content((std::istreambuf_iterator<char>(ifs)),
656  (std::istreambuf_iterator<char>()));
657 
658  const nlohmann::json j = nlohmann::json::parse(content);
659 
660  const auto& jEdges = j.at("edges");
661  const auto& jVertices = j.at("vertices");
662 
663  for (const auto& jVertex : jVertices)
664  {
665  const armarx::armem::MemoryID vertexLocationMemoryId(
666  jVertex.at("locationID"));
667 
668  armarx::navigation::core::arondto::Vertex v;
669  v.vertexID = jVertex.at("vertexID");
670  toAron(v.locationID, vertexLocationMemoryId);
671  toAron(v.locationID.timestamp, armem::Time::Invalid());
672  v.locationID.instanceIndex = 0;
673 
674  g.vertices.push_back(v);
675  }
676 
677  for (const auto& jEdge : jEdges)
678  {
679  std::pair<std::int64_t, std::int64_t> edgeSourceTargetPair;
680  jEdge.get_to(edgeSourceTargetPair);
681 
682  armarx::navigation::core::arondto::Edge e;
683  e.sourceVertexID = edgeSourceTargetPair.first;
684  e.targetVertexID = edgeSourceTargetPair.second;
685  g.edges.push_back(e);
686  }
687 
688  auto& up = c.add();
689  up.confidence = 1.0;
690  up.referencedTime = now;
691  up.arrivedTime = now;
692  up.sentTime = now;
693  up.entityID = providerID.withEntityName(graphName);
694  up.instancesData = {g.toAron()};
695  }
696  }
697 
698  ARMARX_DEBUG << "Sending graphs to memory";
699  iceAdapter().commit(c);
700  }
701  }
702 
703  {
704  // Next we load the rooms.
705  std::filesystem::path roomsFilePath = graph->getFullPath() / "rooms.json";
706  if (not std::filesystem::is_regular_file(roomsFilePath))
707  {
708  ARMARX_INFO << "Found no rooms file for graph '" << graphId << "'.";
709  }
710  else
711  {
712  ARMARX_DEBUG << "Found the rooms file";
713 
715  armem::MemoryID providerID = workingMemory().id();
716  providerID.coreSegmentName =
718  providerID.providerSegmentName = graphId;
719 
720  const auto now = armem::Time::Now();
721  ARMARX_VERBOSE << "Loading " << roomsFilePath;
722 
723  std::ifstream ifs(roomsFilePath);
724  const std::string content((std::istreambuf_iterator<char>(ifs)),
725  (std::istreambuf_iterator<char>()));
726 
727  // parse room. TODO: Move into PriorKnowledge similar to locations
728  const nlohmann::json js = nlohmann::json::parse(content);
729 
730  const auto rooms =
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)
734  {
735  auto roomMemoryId = providerID;
736  roomMemoryId.entityName = roomId;
737 
738  const std::string roomMemoryIdStr = roomMemoryId.str();
739 
740  if (j.find("polygon") == j.end())
741  {
742  ARMARX_WARNING << "The element '" << roomMemoryIdStr
743  << "' has no 'polygon' member. Skipping "
744  "this entity.";
745  continue;
746  }
747 
748  if (j.find("height") == j.end())
749  {
750  ARMARX_WARNING << "The element '" << roomMemoryIdStr
751  << "' has no 'height' member. "
752  "Skipping this entity.";
753  continue;
754  }
755 
756  navigation::algorithms::arondto::Room room;
757  j.at("polygon").get_to(room.polygon);
758  j.at("height").get_to(room.height);
759  room.name = roomId;
760 
761  // set the polygon to z=0
762  for (auto& point : room.polygon)
763  {
764  point.z() = 0;
765  }
766 
767  // send commit to memory
768  auto& up = c.add();
769  up.confidence = 1.0;
770  up.referencedTime = now;
771  up.sentTime = now;
772  up.arrivedTime = now;
773  up.entityID = armarx::armem::MemoryID(roomMemoryIdStr);
774  up.instancesData = {room.toAron()};
775  }
776 
777  ARMARX_DEBUG << "Sending rooms to memory";
778  iceAdapter().commit(c);
779  }
780  }
781  ARMARX_INFO << "Loaded NavigationMemory '" << snapshotToLoad << "' --> graph: '"
782  << graphId << "'";
783  }
784  else
785  {
786  ARMARX_WARNING << "Could not load NavigationMemory '" << snapshotToLoad
787  << "'. Continue with empty memory.";
788  }
789  }
790  }
791 
792  namespace
793  {
794 
795  [[maybe_unused]]
796  bool
797  store(const std::map<armem::MemoryID, core::Graph>& graphs,
798  const std::filesystem::path& baseDirectory)
799  {
800  ARMARX_INFO << "Creating export directory `" << baseDirectory << "`.";
801  std::filesystem::create_directories(baseDirectory);
802 
803  for (const auto& [memoryId, graph] : graphs)
804  {
805  const std::filesystem::path nestedSubDir =
806  std::filesystem::path(memoryId.providerSegmentName) / memoryId.coreSegmentName;
807  const std::filesystem::path dir = baseDirectory / nestedSubDir;
808 
809  std::filesystem::create_directories(dir);
810 
811  nlohmann::json j;
812 
813  // source -> target
814  std::vector<std::pair<std::size_t, std::size_t>> outgoingEdges;
815  std::transform(graph.m_edges.begin(),
816  graph.m_edges.end(),
817  std::back_inserter(outgoingEdges),
818  [](const auto& edge)
819  { return std::make_pair(edge.m_source, edge.m_target); });
820 
821  j["edges"] = outgoingEdges;
822  j["vertices"] = {};
823 
824  for (const auto& vertex : graph.m_vertices)
825  {
826 
827  armarx::armem::MemoryID locationId;
828  fromAron(vertex.m_property.aron.locationID, locationId);
829 
830  nlohmann::json jVertex;
831  jVertex["locationID"] = locationId.getEntityID().str();
832  jVertex["vertexID"] = vertex.m_property.aron.vertexID;
833 
834  j["vertices"].push_back(jVertex);
835  }
836 
837  // save to disk
838  const std::filesystem::path filename = dir / (memoryId.entityName + ".json");
839  ARMARX_VERBOSE << "Saving file `" << filename << "`.";
840  std::ofstream ofs(filename);
841  ofs << std::setw(4) << j;
842  }
843 
844  return true;
845  }
846 
847  bool
848  store(const std::map<armem::MemoryID, location::arondto::Location>& locations,
849  const std::filesystem::path& baseDirectory)
850  {
851  ARMARX_INFO << "Creating export directory `" << baseDirectory << "`.";
852  std::filesystem::create_directories(baseDirectory);
853 
854  // key: provider id
855  std::map<std::string, nlohmann::json> js;
856 
857  for (const auto& [memoryId, location] : locations)
858  {
859  auto& j = js[memoryId.providerSegmentName];
860 
861  if (j.count("locations") == 0)
862  {
863  j["locations"] = {};
864  }
865 
866  nlohmann::json jLoc;
867  nlohmann::json framedPose;
868 
869  framedPose["agent"] = location.framedPose.header.agent;
870  framedPose["frame"] = location.framedPose.header.frame;
871 
872  // utilize ice conversion of eigen
873  std::vector<std::vector<float>> poseAsVec;
874  armarx::core::eigen::toIce(location.framedPose.pose, poseAsVec);
875  framedPose["pose"] = poseAsVec;
876 
877  jLoc["framedPose"] = framedPose;
878 
879  auto entityId = memoryId.getEntityID();
880  j["locations"][entityId.entityName] = jLoc;
881  }
882 
883  // save to disk
884  for (const auto& [providerId, j] : js)
885  {
886  const std::filesystem::path subDir = std::filesystem::path(providerId);
887  const std::filesystem::path dir = baseDirectory / subDir;
888 
889  if (not std::filesystem::exists(dir))
890  {
891  std::filesystem::create_directories(dir);
892  }
893 
894  const std::filesystem::path filename = dir / "locations.json";
895  ARMARX_VERBOSE << "Saving file `" << filename << "`.";
896  std::ofstream ofs(filename);
897  ofs << std::setw(4) << j;
898  }
899 
900 
901  return true;
902  }
903 
904  } // namespace
905 
906  bool
907  Component::storeLocationGraph(const armarx::data::PackagePath& packagePath,
908  const Ice::Current& /*current*/)
909  {
910  armem::server::wm::CoreSegment& locationCoreSegment =
912  armem::server::wm::CoreSegment& graphCoreSegment =
914 
915  // obtain locations and graphs
916 
917  const std::map<armem::MemoryID, location::arondto::Location> locations =
918  [&locationCoreSegment]()
919  {
920  std::map<armem::MemoryID, location::arondto::Location> locations;
921  locationCoreSegment.doLocked(
922  [&]()
923  {
924  locationCoreSegment.forEachEntity(
925  [&](const armarx::armem::server::wm::Entity& entity) -> bool
926  {
927  if (const armarx::armem::server::wm::EntityInstance* instance =
928  entity.findLatestInstance())
929  {
930  locations[entity.id()].fromAron(instance->data());
931  }
932 
933  return true;
934  });
935 
936  return true;
937  });
938 
939  return locations;
940  }();
941 
942  const auto graphs = [&graphCoreSegment]()
943  {
944  std::map<armem::MemoryID, core::Graph> graphs;
945  graphCoreSegment.doLocked(
946  [&]()
947  {
948  graphCoreSegment.forEachEntity(
949  [&](const armarx::armem::server::wm::Entity& entity) -> bool
950  {
951  core::Graph& graph = graphs[entity.id()];
952  if (const armarx::armem::server::wm::EntityInstance* instance =
953  entity.findLatestInstance())
954  {
956  aron.fromAron(instance->data());
957  fromAron(aron, graph);
958  }
959 
960  return true;
961  });
962  });
963 
964  return graphs;
965  }();
966 
967 
968  // store on disk
969 
970  const std::filesystem::path baseDirectory = armarx::PackagePath(packagePath).toSystemPath();
971 
972  store(locations, baseDirectory);
973 
974  // The graph is no longer relevant.
975  // store(graphs, baseDirectory);
976 
977  return true;
978  }
979 
980 
981 } // namespace armarx::navigation::components::navigation_memory
Visu.h
armarx::SimpleRunningTask
Usage:
Definition: TaskUtil.h:85
armarx::viz::Client::commit
CommitResult commit(StagedCommit const &commit)
Definition: Client.cpp:89
armarx::navigation::graph::coreSegmentID
const armem::MemoryID coreSegmentID
Definition: constants.h:30
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::navigation::components::navigation_memory::Component::Properties::LocationGraph
Definition: Component.h:120
armarx::navigation::components::navigation_memory::Component::storeLocationGraph
bool storeLocationGraph(const armarx::data::PackagePath &packagePath, const Ice::Current &current) override
Definition: Component.cpp:907
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::navigation::memory::constants::CostmapCoreSegmentName
const std::string CostmapCoreSegmentName
Definition: constants.h:36
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::armem::Commit
A bundle of updates to be sent to the memory.
Definition: Commit.h:84
QUOTED
#define QUOTED(x)
Definition: StringHelpers.h:199
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::priorknowledge::util::FramedLocation::frame
std::string frame
Definition: Location.h:50
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
ObjectPoseClientPlugin.h
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:51
armarx::navigation::components::navigation_memory::Component::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Component.cpp:93
armarx::navigation::rooms::coreSegmentID
const armem::MemoryID coreSegmentID
Definition: constants.h:10
MemoryID.h
armarx::armem::base::MemoryBase::getCoreSegment
CoreSegmentT & getCoreSegment(const std::string &name)
Definition: MemoryBase.h:132
armarx::navigation::components::navigation_memory::Component::RemoteGui_update
void RemoteGui_update() override
Definition: Component.cpp:360
armarx::RemoteGui::Client::GridLayout::add
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition: Widgets.cpp:438
constants.h
forward_declarations.h
ice_conversions.h
armarx::armem::MemoryID::str
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition: MemoryID.cpp:102
trace.h
armarx::navigation::components::navigation_memory::Component::onExitComponent
void onExitComponent() override
Definition: Component.cpp:329
Layer.h
armarx::navigation::components::navigation_memory::Component
Definition: Component.h:62
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::navigation::components::navigation_memory::Component::onDisconnectComponent
void onDisconnectComponent() override
Definition: Component.cpp:324
aron_conversions.h
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::visuLocations
armarx::RemoteGui::Client::CheckBox visuLocations
Definition: Component.h:168
armarx::armem::server::wm::Entity
Definition: memory_definitions.h:27
armarx::armem::server::plugins::ReadWritePluginUser::workingMemory
server::wm::Memory & workingMemory()
Definition: ReadWritePluginUser.cpp:106
armarx::armem::MemoryID::coreSegmentName
std::string coreSegmentName
Definition: MemoryID.h:51
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
armarx::armem::base::detail::ForEachEntityMixin::forEachEntity
bool forEachEntity(FunctionT &&func)
Definition: iteration_mixins.h:259
armarx::navigation::components::navigation_memory::ARMARX_REGISTER_COMPONENT_EXECUTABLE
ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName())
StringHelpers.h
constants.h
armarx::navigation::memory::constants::ExceptionsCoreSegmentName
const std::string ExceptionsCoreSegmentName
Definition: constants.h:39
armarx::navigation::components::navigation_memory::Component::onInitComponent
void onInitComponent() override
Definition: Component.cpp:234
memory_definitions.h
visionx::voxelgrid::Label
uint32_t Label
Type of an object label.
Definition: types.h:6
LocationLoader.h
armarx::navigation::memory::Visu
Definition: Visu.h:54
armarx::armem::server::ltm::mongodb::util::store
void store(const mongocxx::database &db, const armem::wm::Memory &m)
Definition: operations.cpp:260
armarx::RemoteGui::Client::GridLayout
Definition: Widgets.h:186
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::reloadSnapshot
armarx::RemoteGui::Client::Button reloadSnapshot
Definition: Component.h:167
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::navigation::components::navigation_memory::Component::Component
Component()
Definition: Component.cpp:228
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::PackagePath::toSystemPath
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
Definition: PackagePath.cpp:47
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::navigation::core::Graph
Definition: Graph.h:89
armarx::core::time::Frequency::HertzDouble
static Frequency HertzDouble(double hertz)
Definition: Frequency.cpp:30
armarx::navigation::components::navigation_memory
Definition: Component.cpp:87
armarx::RemoteGui::Client::GroupBox
Definition: Widgets.h:193
armarx::navigation::components::navigation_memory::Component::getDefaultName
std::string getDefaultName() const override
Definition: Component.cpp:334
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::navigation::memory::constants::GraphCoreSegmentName
const std::string GraphCoreSegmentName
Definition: constants.h:34
armarx::armem::base::MemoryBase::addCoreSegment
CoreSegmentT & addCoreSegment(const std::string &name, aron::type::ObjectPtr coreSegmentType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
Add an empty core segment with the given name, type and prediction engines.
Definition: MemoryBase.h:259
Metronome.h
armarx::armem::server::plugins::ReadWritePluginUser::iceAdapter
MemoryToIceAdapter & iceAdapter()
Definition: ReadWritePluginUser.cpp:112
armarx::Graph
boost::subgraph< CloudGraph > Graph
Definition: Common.h:58
armarx::armem::base::EntityBase::findLatestInstance
auto * findLatestInstance(int instanceIndex=0)
Definition: EntityBase.h:355
TaskUtil.h
armarx::core::eigen::toIce
void toIce(const Eigen::Vector2f &e, Ice::FloatSeq &ice)
Definition: ice_conversions.cpp:17
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:25
armarx::RemoteGui::Client::Button::setLabel
void setLabel(std::string const &label)
Definition: Widgets.cpp:123
armarx::armem::server::wm::CoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: memory_definitions.h:110
armarx::armem::MemoryID::entityName
std::string entityName
Definition: MemoryID.h:53
armarx::navigation::memory::constants::HumanCoreSegmentName
const std::string HumanCoreSegmentName
Definition: constants.h:37
aron_conversions.h
armarx::navigation::memory::constants::EventsCoreSegmentName
const std::string EventsCoreSegmentName
Definition: constants.h:33
forward_declarations.h
armarx::RemoteGui::Client::GroupBox::setLabel
void setLabel(std::string const &text)
Definition: Widgets.cpp:420
Component.h
aron_conversions.h
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT >>
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:351
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:119
Commit.h
armarx::armem::server::wm::CoreSegment
base::CoreSegmentBase
Definition: memory_definitions.h:75
armarx::priorknowledge::util::FramedLocation
Definition: Location.h:48
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
Decoupled.h
armarx::armem::MemoryID::getEntityID
MemoryID getEntityID() const
Definition: MemoryID.cpp:310
Graph.h
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::armem::MemoryID::withEntityName
MemoryID withEntityName(const std::string &name) const
Definition: MemoryID.cpp:425
armarx::navigation::components::navigation_memory::Component::onConnectComponent
void onConnectComponent() override
Definition: Component.cpp:305
armarx::priorknowledge::util::LocationLoader::LoadLocations
static std::vector< LocationPtr > LoadLocations(const std::string &dataset, const nlohmann::json &)
Definition: LocationLoader.cpp:143
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
Location.h
PropertyDefinitionContainer.h
armarx::ArVizComponentPluginUser::arviz
armarx::viz::Client arviz
Definition: ArVizComponentPlugin.h:42
armarx::RemoteGui::Client::CheckBox::setValue
void setValue(bool newValue)
Definition: Widgets.cpp:252
armarx::navigation::components::navigation_memory::Component::GetDefaultName
static std::string GetDefaultName()
Definition: Component.cpp:340
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_createTab
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
Definition: LightweightRemoteGuiComponentPlugin.cpp:103
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::core::time::Metronome
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition: Metronome.h:34
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::visuGraphEdges
armarx::RemoteGui::Client::CheckBox visuGraphEdges
Definition: Component.h:169
armarx::navigation::memory::constants::GlobalPlannerResultCoreSegment
const std::string GlobalPlannerResultCoreSegment
Definition: constants.h:41
NavigationGraphFinder.h
armarx::ends_with
bool ends_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:53
armarx::fromAron
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
armarx::navigation::memory::constants::ParameterizationCoreSegmentName
const std::string ParameterizationCoreSegmentName
Definition: constants.h:32
constants.h
Widgets.h
armarx::navigation::location::coreSegmentID
const armem::MemoryID coreSegmentID
Definition: constants.h:30
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:108
armarx::RemoteGui::Client::Button
Definition: Widgets.h:120
Logging.h
armarx::toAron
void toAron(arondto::PackagePath &dto, const PackageFileLocation &bo)
names.h
armarx::ObjectPoseClientPluginUser::getClient
objpose::ObjectPoseClient getClient() const
Definition: ObjectPoseClientPlugin.cpp:70
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::priorknowledge::navigation_graphs::NavigationGraphFinder
Definition: NavigationGraphFinder.h:7
armarx::navigation::memory::constants::LocalPlannerResultCoreSegment
const std::string LocalPlannerResultCoreSegment
Definition: constants.h:42
armarx::PackagePath
Definition: PackagePath.h:52
armarx::priorknowledge::util::LocationType::FRAMED_LOCATION
@ FRAMED_LOCATION
armarx::navigation::components::navigation_memory::Component::createRemoteGuiTab
void createRemoteGuiTab()
Definition: Component.cpp:346
armarx::navigation::components::navigation_memory::Component::Properties::LocationGraph::visuGraphEdges
bool visuGraphEdges
Definition: Component.h:123
armarx::navigation::memory::constants::LaserScannerFeaturesCoreSegment
const std::string LaserScannerFeaturesCoreSegment
Definition: constants.h:38
armarx::core::time::DateTime::Invalid
static DateTime Invalid()
Definition: DateTime.cpp:57
armarx::armem::base::MemoryBase::setName
void setName(const std::string &name)
Definition: MemoryBase.h:246
armarx::armem::server::MemoryToIceAdapter::commitLocking
data::CommitResult commitLocking(const data::Commit &commitIce, Time timeArrived)
Definition: MemoryToIceAdapter.cpp:166
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::update
void update(Component &owner) const
Definition: Component.cpp:400
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::group
armarx::RemoteGui::Client::GroupBox group
Definition: Component.h:165
armarx::armem::server::MemoryToIceAdapter::commit
data::CommitResult commit(const data::Commit &commitIce, Time timeArrived)
Definition: MemoryToIceAdapter.cpp:115
armarx::core::time::Duration::MilliSeconds
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
Definition: Duration.cpp:48
armarx::navigation::components::navigation_memory::Component::RemoteGuiTab::LocationGraph::setup
void setup(Component &owner)
Definition: Component.cpp:366
constants.h
armarx::navigation::components::navigation_memory::Component::Properties::LocationGraph::visuLocations
bool visuLocations
Definition: Component.h:122
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:38
PackagePath.h
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:28