Navigator.cpp
Go to the documentation of this file.
1 #include "Navigator.h"
2 
3 #include <algorithm>
4 #include <chrono>
5 #include <cmath>
6 #include <cstddef>
7 #include <optional>
8 #include <thread>
9 
10 #include <boost/graph/dijkstra_shortest_paths.hpp>
11 #include <boost/graph/named_function_params.hpp>
12 #include <boost/graph/properties.hpp>
13 #include <boost/graph/subgraph.hpp>
14 
15 #include <Eigen/Geometry>
16 
17 #include <SimoxUtility/math/convert/mat3f_to_rpy.h>
18 #include <VirtualRobot/Robot.h>
19 
26 
28 
46 
47 #include "range/v3/algorithm/reverse.hpp"
48 #include "range/v3/range/conversion.hpp"
49 #include <SemanticObjectRelations/Shapes/Shape.h>
50 #include <range/v3/view.hpp>
51 #include <range/v3/view/reverse.hpp>
52 
54 {
55  void
57  {
58  if (task)
59  {
60  task->stop();
61  }
62  }
63 
64  Navigator::Navigator(const Config& config, const InjectedServices& services) :
65  config{config}, srv{services}
66  {
67  ARMARX_CHECK_NOT_NULL(srv.sceneProvider) << "The scene provider must be set!";
68  // ARMARX_CHECK_NOT_NULL(services.executor) << "The executor service must be set!";
69  ARMARX_CHECK_NOT_NULL(services.publisher) << "The publisher service must be set!";
70  }
71 
73  {
74  ARMARX_INFO << "Navigator destructor";
75  stop();
76 
77  stopAllThreads();
78  }
79 
80  void
81  Navigator::setGraphEdgeCosts(core::Graph& graph) const
82  {
83  const auto cost = [](const core::Pose& p1, const core::Pose& p2)
84  {
85  const core::Pose diff = p1.inverse() * p2;
86 
87  // FIXME consider rotation as well
88  return diff.translation().norm();
89  };
90 
91  // graph -> trajectory (set costs)
92  for (auto edge : graph.edges())
93  {
94  const core::Pose start = resolveGraphVertex(edge.source());
95  const core::Pose goal = resolveGraphVertex(edge.target());
96 
97  switch (edge.attrib().strategy)
98  {
100  {
101  ARMARX_VERBOSE << "Global planning from " << start.translation() << " to "
102  << goal.translation();
104 
105  try
106  {
107  const auto globalPlan = config.stack.globalPlanner->plan(start, goal);
108  if (globalPlan.has_value())
109  {
110  ARMARX_CHECK(globalPlan->trajectory.isValid());
111 
112  edge.attrib().trajectory = globalPlan->trajectory;
113  ARMARX_VERBOSE << "Free path length: "
114  << globalPlan->trajectory.length();
115  edge.attrib().cost() = globalPlan->trajectory.length();
116  }
117  else
118  {
119  ARMARX_VERBOSE << "Global planning failed for this edge.";
120  edge.attrib().cost() = std::numeric_limits<float>::max();
121  }
122  }
123  catch (...)
124  {
125  ARMARX_VERBOSE << "Global planning failed due to exception "
127  edge.attrib().cost() = std::numeric_limits<float>::max();
128  }
129 
130 
131  break;
132  }
134  {
135  edge.attrib().cost() = cost(start, goal);
136  break;
137  }
138  }
139 
140  ARMARX_VERBOSE << "Edge cost: " << edge.attrib().cost();
141  }
142  }
143 
144  void
145  Navigator::moveTo(const std::vector<core::Pose>& waypoints,
146  core::NavigationFrame navigationFrame)
147  {
148  ARMARX_INFO << "Received moveTo() request.";
149 
150  std::vector<core::Pose> globalWaypoints;
151  switch (navigationFrame)
152  {
154  globalWaypoints = waypoints;
155  break;
157  globalWaypoints.reserve(waypoints.size());
158 
160 
161  const core::Pose global_T_robot(srv.sceneProvider->scene().robot->getGlobalPose());
162  ARMARX_VERBOSE << "Initial robot pose: " << global_T_robot.matrix();
163 
164  std::transform(std::begin(waypoints),
165  std::end(waypoints),
166  std::back_inserter(globalWaypoints),
167  [&](const core::Pose& p) { return global_T_robot * p; });
168  break;
169  }
170 
171  ARMARX_TRACE;
172  moveToAbsolute(globalWaypoints);
173  }
174 
175  void
176  Navigator::update(const std::vector<core::Pose>& waypoints,
177  core::NavigationFrame navigationFrame)
178  {
179  ARMARX_INFO << "Received update() request.";
180 
181  std::vector<core::Pose> globalWaypoints;
182  switch (navigationFrame)
183  {
185  globalWaypoints = waypoints;
186  break;
188  globalWaypoints.reserve(waypoints.size());
190  std::begin(waypoints),
191  std::end(waypoints),
192  std::back_inserter(globalWaypoints),
193  [&](const core::Pose& p)
194  { return core::Pose(srv.sceneProvider->scene().robot->getGlobalPose()) * p; });
195  break;
196  }
197 
198  ARMARX_TRACE;
199  updateAbsolute(globalWaypoints);
200  }
201 
202  using GraphPath = std::vector<semrel::ShapeID>;
203 
204  GraphPath
206  const core::Graph::ConstVertex& startVertex,
207  const core::Graph::ConstVertex& goalVertex)
208  {
209  ARMARX_VERBOSE << "Graph consists of " << graph.numVertices() << " vertices and "
210  << graph.numEdges() << " edges.";
211 
212  std::vector<core::Graph::VertexDescriptor> predecessors(graph.numVertices());
213  std::vector<int> d(num_vertices(graph));
214 
215  // FIXME ARMARX_CHECK(graphBuilder.startVertex.has_value());
216 
217  auto weightMap = boost::get(&core::EdgeAttribs::m_value, graph);
218 
219  core::Graph::VertexDescriptor start = startVertex.descriptor();
220 
221  auto predecessorMap = boost::make_iterator_property_map(
222  predecessors.begin(), boost::get(boost::vertex_index, graph));
223 
224  auto params = boost::predecessor_map(predecessorMap)
225  .distance_map(boost::make_iterator_property_map(
226  d.begin(), boost::get(boost::vertex_index, graph)))
227  .weight_map(weightMap);
228 
229  ARMARX_TRACE;
230  ARMARX_INFO << graph;
231  ARMARX_TRACE;
232 
233  ARMARX_VERBOSE << "Edge weights:";
234  for (const auto& edge : graph.edges())
235  {
236  ARMARX_VERBOSE << edge.sourceObjectID() << " -> " << edge.targetObjectID() << ": "
237  << edge.attrib().m_value;
238  }
239 
240  std::vector<core::Graph::EdgeDescriptor> edgesToBeRemoved;
241  for (const auto edge : graph.edges())
242  {
243  if (edge.attrib().m_value == std::numeric_limits<float>::max())
244  {
245  edgesToBeRemoved.push_back(edge.descriptor());
246  }
247  }
248 
249  for (const auto edge : edgesToBeRemoved)
250  {
251  boost::remove_edge(edge, graph);
252  }
253  ARMARX_VERBOSE << "Edge weights after removal of inf edges:";
254 
255  for (const auto& edge : graph.edges())
256  {
257  ARMARX_VERBOSE << edge.sourceObjectID() << " -> " << edge.targetObjectID() << ": "
258  << edge.attrib().m_value;
259  ARMARX_VERBOSE << "Edge: " << edge << "cost: " << edge.attrib().cost()
260  << ", type: " << static_cast<int>(edge.attrib().strategy)
261  << " , has traj " << edge.attrib().trajectory.has_value();
262  }
263 
264  ARMARX_VERBOSE << "Searching shortest path from vertex with id `"
265  << graph.vertex(start).objectID() << "` to vertex `"
266  << graph.vertex(goalVertex.descriptor()).objectID() << "`";
267 
268  boost::dijkstra_shortest_paths(graph, start, params);
269 
270  // find shortest path
271  ARMARX_TRACE;
272 
273  // WARNING: shortest path will be from goal to start first
274  GraphPath shortestPath;
275 
276  core::Graph::VertexDescriptor currentVertex = goalVertex.descriptor();
277  while (currentVertex != startVertex.descriptor())
278  {
279  shortestPath.push_back(graph.vertex(currentVertex).objectID());
280 
281  ARMARX_TRACE;
282 
283  auto parent = predecessorMap[currentVertex];
284  ARMARX_VERBOSE << "Parent id: " << parent;
285 
286  ARMARX_TRACE;
287 
288  // find edge between parent and currentVertex
289  auto outEdges = graph.vertex(parent).outEdges();
290  ARMARX_VERBOSE << "Parent has " << std::distance(outEdges.begin(), outEdges.end())
291  << " out edges";
292 
293  ARMARX_CHECK_GREATER(std::distance(outEdges.begin(), outEdges.end()), 0)
294  << "Cannot reach another vertex from vertex `"
295  << graph.vertex(parent).objectID(); // not empty
296 
297  auto edgeIt = std::find_if(outEdges.begin(),
298  outEdges.end(),
299  [&currentVertex](const auto& edge) -> bool
300  { return edge.target().descriptor() == currentVertex; });
301 
302  ARMARX_CHECK(edgeIt != outEdges.end());
303  // shortestPath.edges.push_back(edgeIt->descriptor());
304 
305  currentVertex = parent;
306  }
307 
308  shortestPath.push_back(startVertex.objectID());
309 
310  // ARMARX_CHECK_EQUAL(shortestPath.vertices.size() - 1, shortestPath.edges.size());
311 
312  ARMARX_TRACE;
313  // reverse the range => now it is from start to goal again
314  shortestPath = shortestPath | ranges::views::reverse | ranges::to_vector;
315  // shortestPath.edges = shortestPath.edges | ranges::views::reverse | ranges::to_vector;
316 
317  ARMARX_TRACE;
318  return shortestPath;
319  }
320 
322  Navigator::convertToTrajectory(const GraphPath& shortestPath, const core::Graph& graph) const
323  {
324  ARMARX_TRACE;
325 
326  ARMARX_CHECK_GREATER_EQUAL(shortestPath.size(), 2)
327  << "At least start and goal vertices must be available";
328 
329  // ARMARX_CHECK_EQUAL(shortestPath.size() - 1, shortestPath.edges.size());
330 
331  std::vector<core::GlobalTrajectoryPoint> trajectoryPoints;
332 
333  // TODO add the start
334  // trajectoryPoints.push_back(core::TrajectoryPoint{
335  // .waypoint = {.pose = graph.vertex(shortestPath.front()).attrib().getPose()},
336  // .velocity = 0.F});
337 
338  ARMARX_VERBOSE << "Shortest path with " << shortestPath.size() << " vertices";
339  ARMARX_VERBOSE << graph;
340 
341  for (size_t i = 0; i < shortestPath.size() - 1; i++)
342  {
343  // ARMARX_CHECK(graph.hasEdge(shortestPath.edges.at(i).m_source,
344  // shortestPath.edges.at(i).m_target));
345 
346  // TODO add method edge(shapeId, shapeId)
347  const core::Graph::ConstEdge edge =
348  graph.edge(graph.vertex(shortestPath.at(i)), graph.vertex(shortestPath.at(i + 1)));
349 
350  ARMARX_TRACE;
351  ARMARX_VERBOSE << "Index " << i;
352  ARMARX_VERBOSE << static_cast<int>(edge.attrib().strategy);
353  ARMARX_VERBOSE << edge;
354  switch (edge.attrib().strategy)
355  {
357  {
358  ARMARX_INFO << "Free navigation on edge";
359 
360  ARMARX_TRACE;
361  ARMARX_CHECK(edge.attrib().trajectory.has_value());
362 
363  ARMARX_TRACE;
364  ARMARX_INFO << "Length: " << edge.attrib().trajectory->length();
365 
366 
367  ARMARX_TRACE;
368  ARMARX_INFO << "Free navigation with "
369  << edge.attrib().trajectory->points().size() << " waypoints";
370 
371  // we have a trajectory
372  // FIXME trajectory points can be invalid => more points than expected. Why?
373  ARMARX_TRACE;
374  const std::vector<core::GlobalTrajectoryPoint> edgeTrajectoryPoints =
375  edge.attrib().trajectory->points();
376 
377  // if trajectory is being initialized, include the start, otherwise skip it
378  const int offset = trajectoryPoints.empty() ? 0 : 1;
379 
380  if (edgeTrajectoryPoints.size() > 2) // not only start and goal position
381  {
382  ARMARX_TRACE;
383  // append `edge trajectory` to `trajectory` (without start and goal points)
384  trajectoryPoints.insert(trajectoryPoints.end(),
385  edgeTrajectoryPoints.begin() + offset,
386  edgeTrajectoryPoints.end());
387  }
388 
389 
390  ARMARX_TRACE;
391  // clang-format off
392  // trajectoryPoints.push_back(
393  // core::TrajectoryPoint
394  // {
395  // .waypoint =
396  // {
397  // .pose = graph.vertex(shortestPath.at(i+1)).attrib().getPose()
398  // },
399  // .velocity = std::numeric_limits<float>::max()
400  // });
401  // clang-format on
402 
403  break;
404  }
405 
407  {
408  ARMARX_INFO << "Point2Point navigation on edge";
409 
410  // FIXME variable
411  const float point2pointVelocity = 400;
412 
413  const core::GlobalTrajectoryPoint currentTrajPt = {
414  .waypoint = {.pose = resolveGraphVertex(graph.vertex(shortestPath.at(i)))},
415  .velocity = point2pointVelocity};
416 
417  const core::GlobalTrajectoryPoint nextTrajPt{
418  .waypoint = {.pose =
419  resolveGraphVertex(graph.vertex(shortestPath.at(i + 1)))},
420  .velocity = 0};
421 
422  // resample event straight lines
423  // ARMARX_CHECK_NOT_EMPTY(trajectoryPoints);
424 
425  // const core::Trajectory segmentTraj({trajectoryPoints.back(), nextTrajPt});
426  // ARMARX_INFO << "Segment trajectory length: " << segmentTraj.length();
427 
428  // const auto resampledTrajectory = segmentTraj.resample(500); // FIXME param
429 
430  // ARMARX_INFO << "Resampled trajectory contains "
431  // << resampledTrajectory.points().size() << " points";
432 
433  // this is the same pose as the goal of the previous segment but with a different velocity
434  // FIXME MUST set velocity here.
435  // trajectoryPoints.push_back(
436  // core::TrajectoryPoint{.waypoint = trajectoryPoints.back().waypoint,
437  // .velocity = std::numeric_limits<float>::max()});
438 
439  ARMARX_TRACE;
440  // trajectoryPoints.insert(trajectoryPoints.end(),
441  // resampledTrajectory.points().begin(),
442  // resampledTrajectory.points().end());
443  trajectoryPoints.push_back(currentTrajPt);
444  trajectoryPoints.push_back(nextTrajPt);
445 
446  break;
447  }
448  default:
449  {
450  ARMARX_ERROR << "Boom.";
451  }
452  }
453  }
454 
455  ARMARX_INFO << "Trajectory consists of " << trajectoryPoints.size() << " points";
456 
457  for (const auto& pt : trajectoryPoints)
458  {
459  ARMARX_INFO << pt.waypoint.pose.translation();
460  }
461 
462  return {trajectoryPoints};
463  }
464 
465  GraphBuilder
466  Navigator::convertToGraph(const std::vector<client::WaypointTarget>& targets) const
467  {
468  //
469  GraphBuilder graphBuilder;
470  graphBuilder.initialize(core::Pose(srv.sceneProvider->scene().robot->getGlobalPose()));
471 
472  // std::optional<Graph*> activeSubgraph;
473  for (const auto& target : targets)
474  {
475  ARMARX_INFO << "Adding target `" << target << "` to graph";
476  // if the last location was on a subgraph, that we are about to leave
477  // const bool leavingSubgraph = [&]() -> bool
478  // {
479  // if (not activeSubgraph.has_value())
480  // {
481  // return false;
482  // }
483 
484  // // if a user specifies a pose, then this pose is not meant to be part of a graph
485  // // -> can be reached directly
486  // if (target.pose.has_value())
487  // {
488  // return true;
489  // }
490 
491  // if (not target.locationId->empty())
492  // {
493  // const auto& subgraph = core::getSubgraph(target.locationId.value(),srv.sceneProvider->scene().graph->subgraphs);
494  // return subgraph.name() != activeSubgraph;
495  // }
496 
497  // throw LocalException("this line should not be reachable");
498  // }();
499 
500  // if(leavingSubgraph)
501  // {
502  // const auto activeNodes = graph.activeVertices();
503  // ARMARX_CHECK(activeNodes.size() == 1);
504  // graph.connect(activeSubgraph->getRoutesFrom(activeNodes.front()));
505  // }
506 
507 
508  // if a user specifies a pose, then this pose is not meant to be part of a graph
509  // -> can be reached directly
510  if (target.pose.has_value())
511  {
512  graphBuilder.connect(target.pose.value(), target.strategy);
513  continue;
514  }
515 
516  // if a user specified a vertex of a subgraph (aka location), then this vertex
517  // might not be reachable directly. It might be needed to navigate on the graph
518  // instead. Thus, we collect all routes to reach the node.
519  if (not target.locationId->empty())
520  {
521  const auto& subgraph = core::getSubgraph(
522  target.locationId.value(), srv.sceneProvider->scene().graph->subgraphs);
523 
524  const auto vertex = core::getVertexByName(target.locationId.value(), subgraph);
525 
526  ARMARX_INFO << "Vertex `" << target.locationId.value() << "` resolved to "
527  << vertex.attrib().getPose();
528 
529  const std::vector<core::GraphPath> routes = core::findPathsTo(vertex, subgraph);
530  // const auto routes = subgraph->getRoutesTo(target.locationId);
531 
532  ARMARX_INFO << "Found " << routes.size() << " routes to location `"
533  << target.locationId.value();
534 
535  ARMARX_CHECK(not routes.empty()) << "The location `" << target.locationId.value()
536  << "` is not a reachable vertex on the graph!";
537 
538  // we now add all routes to the graph that take us to the desired location
539  graphBuilder.connect(routes,
540  target.strategy); // TODO: all routes to the same target
541 
542  continue;
543  }
544 
545  ARMARX_ERROR << "Either `location_id` or `pose` has to be provided!";
546  }
547 
548  const auto goalVertex = graphBuilder.getGraph().vertex(graphBuilder.goalVertex());
549  ARMARX_INFO << "Goal vertex is `" << goalVertex.attrib().getName() << "`";
550 
551  return graphBuilder;
552  }
553 
554  core::Pose
555  Navigator::resolveGraphVertex(const core::Graph::ConstVertex& vertex) const
556  {
557  const auto goal = core::resolveLocation(srv.sceneProvider->scene().staticScene->objectMap,
558  srv.sceneProvider->scene().staticScene->objectInfo,
559  vertex.attrib().getPose());
560  ARMARX_CHECK(goal.pose.has_value())
561  << "The location of vertex " << vertex.attrib().getName() << " couldn't be resolved ("
562  << goal.errorMsg << ")";
563  return goal.pose.value();
564  }
565 
566  void
567  Navigator::moveTo(const std::vector<client::WaypointTarget>& targets,
568  core::NavigationFrame navigationFrame)
569  {
571  << "only absolute movement implemented atm.";
572 
573  ARMARX_TRACE;
574 
575  validate(targets);
576 
577  ARMARX_CHECK_NOT_EMPTY(targets) << "At least the goal has to be provided!";
578  ARMARX_INFO << "Navigating to " << targets.back();
579 
580  // update static scene including locations
581  updateScene(true);
582 
583  auto graphBuilder = convertToGraph(targets);
584 
585  ARMARX_TRACE;
586 
587  core::Graph graph = graphBuilder.getGraph();
588  auto startVertex = graphBuilder.startVertex;
589  auto goalVertex = graphBuilder.getGraph().vertex(graphBuilder.goalVertex());
590 
591  ARMARX_INFO << "Goal pose according to graph is " << graphBuilder.goalPose().matrix();
592 
593  ARMARX_CHECK(startVertex.has_value());
594 
595  ARMARX_TRACE;
596 
597  goalReachedMonitor = std::nullopt;
598  goalReachedMonitor = GoalReachedMonitor(
599  graphBuilder.goalPose(), srv.sceneProvider->scene(), GoalReachedMonitorConfig());
600 
601  if (goalReachedMonitor->goalReached(false))
602  {
603  ARMARX_IMPORTANT << "Already at goal position "
604  << goalReachedMonitor->goal().translation().head<2>()
605  << ". Robot won't move.";
606 
608  {armarx::Clock::Now()},
609  core::Pose(srv.sceneProvider->scene().robot->getGlobalPose())});
610 
611  return;
612  }
613 
614  ARMARX_TRACE;
615  setGraphEdgeCosts(graph);
616 
617  ARMARX_VERBOSE << graph;
618 
619  srv.introspector->onGlobalGraph(graph);
620 
621  ARMARX_TRACE;
622  const auto shortestPath = findShortestPath(graph, startVertex.value(), goalVertex);
623 
624  // print
625  ARMARX_TRACE;
626 
627  std::vector<core::Pose> vertexPoses;
628  vertexPoses.emplace_back(srv.sceneProvider->scene().robot->getGlobalPose());
629 
630  ARMARX_INFO << "Navigating along the following nodes:";
631  for (const semrel::ShapeID& vertex : shortestPath)
632  {
633  ARMARX_INFO << " - " << graph.vertex(vertex).attrib().getName();
634  vertexPoses.push_back(resolveGraphVertex(graph.vertex(vertex)));
635  }
636 
637  srv.introspector->onGlobalShortestPath(vertexPoses);
638 
639 
640  // convert graph / vertex chain to trajectory
641  ARMARX_TRACE;
642  core::GlobalTrajectory globalPlanTrajectory = convertToTrajectory(shortestPath, graph);
643 
644  // globalPlanTrajectory.setMaxVelocity(1000); // FIXME
645 
646  // move ...
647 
648  // this is our `global plan`
649  ARMARX_TRACE;
650 
651  globalPlan = global_planning::GlobalPlannerResult{.trajectory = globalPlanTrajectory};
652 
653  // the following is similar to moveToAbsolute
654  // TODO(fabian.reister): remove code duplication
655 
656  srv.executor->execute(globalPlan->trajectory);
657 
658  ARMARX_TRACE;
659  srv.publisher->globalTrajectoryUpdated(globalPlan.value());
660 
661  ARMARX_TRACE;
662  srv.introspector->onGlobalPlannerResult(globalPlan.value());
663 
664  ARMARX_INFO << "Global planning completed. Will now start all required threads";
665  ARMARX_TRACE;
666 
667  startStack();
668  }
669 
670  void
671  Navigator::startStack()
672  {
673 
674  ARMARX_TRACE;
675 
676  ARMARX_INFO << "Starting stack.";
677 
678  // FIXME instead of PeriodicTask, use RunningTask.
679  runningTask = new PeriodicTask<Navigator>(this,
680  &Navigator::run,
682  false,
683  "PeriodicTask");
684  runningTask->start();
685 
686  // FIXME create separate function for this.
687  if (hasLocalPlanner())
688  {
690  }
691  else
692  {
694  }
695 
696  // Could be required if pauseMovement() has been called in the past.
697  resume();
698  srv.publisher->movementStarted(core::MovementStartedEvent{
699  {armarx::Clock::Now()}, core::Pose(srv.sceneProvider->scene().robot->getGlobalPose())});
700  }
701 
702  void
703  Navigator::moveToAbsolute(const std::vector<core::Pose>& waypoints)
704  {
705  ARMARX_TRACE;
706 
707  // if this navigator is in use, stop the movement ...
708  pause();
709  // ... and all threads
710  stopAllThreads();
711 
712  // FIXME remove
713  //std::this_thread::sleep_for(std::chrono::seconds(1));
714 
715  ARMARX_TRACE;
716  ARMARX_CHECK_NOT_EMPTY(waypoints);
717 
719 
720  ARMARX_INFO << "Request to move from " << srv.sceneProvider->scene().robot->getGlobalPose()
721  << " to " << waypoints.back().matrix();
722 
723  // first we check if we are already at the goal position
724  goalReachedMonitor = std::nullopt;
725  goalReachedMonitor = GoalReachedMonitor(
726  waypoints.back(), srv.sceneProvider->scene(), GoalReachedMonitorConfig());
727 
728  if (goalReachedMonitor->goalReached(false))
729  {
730  ARMARX_INFO << "Already at goal position. Robot won't move.";
731 
732  srv.publisher->goalReached(core::GoalReachedEvent{
733  {armarx::Clock::Now()},
734  core::Pose(srv.sceneProvider->scene().robot->getGlobalPose())});
735 
736  return;
737  }
738 
739  // global planner
740  ARMARX_INFO << "Planning global trajectory";
742  // TODO plan on multiple waypoints, ignoring waypoints for now
743  // idea: compute multiple global trajectories, one for each segment between waypoints.
744 
745  srv.introspector->onGoal(waypoints.back());
746  globalPlan = config.stack.globalPlanner->plan(waypoints.back());
747 
748  ARMARX_TRACE;
749 
750  if (not globalPlan.has_value())
751  {
752  ARMARX_WARNING << "No global trajectory. Cannot move.";
754  core::GlobalPlanningFailedEvent{{.timestamp = armarx::Clock::Now()}, {""}});
755 
756  srv.introspector->failure();
757  return;
758  }
759 
760  ARMARX_TRACE;
761  srv.publisher->globalTrajectoryUpdated(globalPlan.value());
762  srv.introspector->onGlobalPlannerResult(globalPlan.value());
763 
764  if (not hasLocalPlanner())
765  {
766  updateExecutor(globalPlan.value());
767  }
768 
769  ARMARX_INFO << "Global planning completed. Will now start all required threads";
770  ARMARX_TRACE;
771 
772  startStack();
773 
774  ARMARX_INFO << "Movement started.";
775  }
776 
777  void
778  Navigator::updateAbsolute(const std::vector<core::Pose>& waypoints)
779  {
780  ARMARX_TRACE;
781  ARMARX_CHECK_NOT_EMPTY(waypoints);
782 
783 
784  // global planner
785  ARMARX_INFO << "Planning global trajectory";
787  // TODO plan on multiple waypoints, ignoring waypoints for now
788  // idea: compute multiple global trajectories, one for each segment between waypoints.
789 
790  srv.introspector->onGoal(waypoints.back());
791  globalPlan = config.stack.globalPlanner->plan(waypoints.back());
792 
793  ARMARX_TRACE;
794 
795  if (not globalPlan.has_value())
796  {
797  ARMARX_WARNING << "No global trajectory. Cannot move.";
799  core::GlobalPlanningFailedEvent{{.timestamp = armarx::Clock::Now()}, {""}});
800 
801  srv.introspector->failure();
802  return;
803  }
804 
805  ARMARX_TRACE;
806  srv.publisher->globalTrajectoryUpdated(globalPlan.value());
807  srv.introspector->onGlobalPlannerResult(globalPlan.value());
808  // srv.executor->execute(globalPlan->trajectory);
809 
810  ARMARX_INFO << "Global planning completed. Will now start all required threads";
811  ARMARX_TRACE;
812 
813  startStack();
814 
815  ARMARX_INFO << "Movement started.";
816  }
817 
818  void
820  {
821  }
822 
823  void
824  Navigator::moveToLocation(const std::string& location)
825  {
826  // update static scene including locations
827  updateScene(true);
828 
829  const auto resolveLocation = [&](const std::string& location)
830  {
831  const auto locations = srv.sceneProvider->scene().staticScene->locations;
832  ARMARX_CHECK(locations.count(location) > 0) << "Unknown location `" << location << "`.";
833  return locations.at(location);
834  };
835 
836  const auto split = simox::alg::split(location, ":");
837  ARMARX_CHECK(0 < split.size() && split.size() <= 2)
838  << "The given location does not match the format <location>(:<instance-id>)? '"
839  << location << "'.";
840 
841  std::string instanceID;
842  if (split.size() == 2)
843  {
844  // An instance-id was given in the location
845  instanceID = split[1];
846  }
847  const auto goal = core::resolveLocation(srv.sceneProvider->scene().staticScene->objectMap,
848  srv.sceneProvider->scene().staticScene->objectInfo,
849  resolveLocation(split[0]).framedPose,
850  instanceID);
851 
852  if (goal.pose.has_value())
853  {
854  moveToAbsolute({goal.pose.value()});
855  }
856  else
857  {
858  ARMARX_ERROR << goal.errorMsg;
859  }
860  }
861 
862  void
863  Navigator::moveTowardsAbsolute(const core::Direction& direction)
864  {
865  }
866 
867  void
868  Navigator::run()
869  {
870  // TODO(fabian.reister): add debug observer logging
871 
872  // scene update
873  {
874  ARMARX_DEBUG << "Updating scene";
875 
876  const Duration duration =
877  armarx::core::time::StopWatch::measure([&]() { updateScene(); });
878 
880  << "Scene update: " << duration.toMilliSecondsDouble() << "ms.";
881 
882  srv.debugObserverHelper->setDebugObserverDatafield("scene update [ms]",
883  duration.toMilliSecondsDouble());
884  }
885 
886  // eventually, draw
887  if (srv.introspector and srv.sceneProvider and srv.sceneProvider->scene().robot)
888  {
889  ARMARX_DEBUG << "Drawing robot pose";
891  core::Pose(srv.sceneProvider->scene().robot->getGlobalPose()));
892  }
893 
894  // global planner update if goal has changed
895  {
896  std::lock_guard g{globalPlanningRequestMtx};
897 
898  if (globalPlanningRequest.has_value())
899  {
900  const auto& waypoints = globalPlanningRequest.value();
901 
902  // recreate goal monitor
903  {
904  // first we check if we are already at the goal position
905  goalReachedMonitor = std::nullopt;
906  goalReachedMonitor = GoalReachedMonitor(
907  waypoints.back(), srv.sceneProvider->scene(), GoalReachedMonitorConfig());
908 
909  if (goalReachedMonitor->goalReached(false))
910  {
911  ARMARX_INFO << "Already at goal position. Robot won't move.";
912 
913  srv.publisher->goalReached(core::GoalReachedEvent{
914  {armarx::Clock::Now()},
915  core::Pose(srv.sceneProvider->scene().robot->getGlobalPose())});
916 
917  return;
918  }
919  }
920 
921  // global planning
922  {
923  // global planner
924  ARMARX_INFO << "Update/Planning global trajectory";
926  // TODO plan on multiple waypoints, ignoring waypoints for now
927  // idea: compute multiple global trajectories, one for each segment between waypoints.
928 
929  srv.introspector->onGoal(waypoints.back());
930  globalPlan = config.stack.globalPlanner->plan(waypoints.back());
931 
932  ARMARX_TRACE;
933 
934  if (not globalPlan.has_value())
935  {
936  ARMARX_WARNING << "No global trajectory. Cannot move.";
937  srv.publisher->globalPlanningFailed(core::GlobalPlanningFailedEvent{
938  {.timestamp = armarx::Clock::Now()}, {""}});
939 
940  srv.introspector->failure();
941  return;
942  }
943 
944  ARMARX_TRACE;
945  srv.publisher->globalTrajectoryUpdated(globalPlan.value());
946  srv.introspector->onGlobalPlannerResult(globalPlan.value());
947 
948  if (not hasLocalPlanner())
949  {
950  updateExecutor(globalPlan.value());
951  }
952  }
953  }
954  }
955 
956  // local planner update
957  {
958  ARMARX_DEBUG << "Local planner update";
959 
961  [&]()
962  {
963  if (hasLocalPlanner())
964  {
965  const auto localPlannerResult = updateLocalPlanner();
966  updateExecutor(localPlannerResult);
967  updateIntrospector(localPlannerResult);
968 
969  if (srv.executor != nullptr)
970  {
973  }
974  }
975  else if (srv.executor != nullptr)
976  {
979  }
980  });
982  << "Local planner update: " << duration.toMilliSecondsDouble() << "ms.";
983 
984  srv.debugObserverHelper->setDebugObserverDatafield("local planner update [ms]",
985  duration.toMilliSecondsDouble());
986  }
987 
988  // monitor update
989  {
990  ARMARX_DEBUG << "Monitor update";
991 
992  const Duration duration =
993  armarx::core::time::StopWatch::measure([&]() { updateMonitor(); });
994 
996  << "Monitor update: " << duration.toMilliSecondsDouble() << "ms.";
997 
998  srv.debugObserverHelper->setDebugObserverDatafield("monitor update [ms]",
999  duration.toMilliSecondsDouble());
1000  }
1001  }
1002 
1003  void
1004  Navigator::updateScene(const bool fullUpdate)
1005  {
1007  srv.sceneProvider->synchronize(armarx::Clock::Now(), fullUpdate);
1008  }
1009 
1010  std::optional<local_planning::LocalPlannerResult>
1011  Navigator::updateLocalPlanner()
1012  {
1013  ARMARX_CHECK(hasLocalPlanner());
1014 
1015  ARMARX_VERBOSE << "Updating local plan";
1016 
1017  try
1018  {
1019  localPlan = config.stack.localPlanner->plan(globalPlan->trajectory);
1020  if (localPlan.has_value())
1021  {
1022  srv.publisher->localTrajectoryUpdated(localPlan.value());
1023  }
1024  return localPlan;
1025  }
1026  catch (...)
1027  {
1028  ARMARX_WARNING << "Failure in local planner: " << GetHandledExceptionString();
1029  srv.publisher->localPlanningFailed(core::LocalPlanningFailedEvent{
1030  {.timestamp = armarx::Clock::Now()}, {GetHandledExceptionString()}});
1031 
1032  return std::nullopt;
1033  }
1034 
1035  srv.publisher->localPlanningFailed(core::LocalPlanningFailedEvent{
1036  {.timestamp = armarx::Clock::Now()}, {"Unknown reason"}});
1037 
1038  return std::nullopt;
1039  }
1040 
1041  void
1042  Navigator::updateExecutor(const std::optional<local_planning::LocalPlannerResult>& localPlan)
1043  {
1044  if (srv.executor == nullptr)
1045  {
1046  return;
1047  }
1048 
1049 
1050  if (isPaused() or isStopped())
1051  {
1052  // [[unlikely]]
1053  ARMARX_VERBOSE << deactivateSpam(1) << "stopped or paused";
1054  return;
1055  }
1056 
1057  if (not localPlan.has_value())
1058  {
1059  ARMARX_INFO << "Local plan is invalid!";
1060  srv.executor->stop();
1061  return;
1062  }
1063 
1064 
1065  // const core::Rotation robot_R_world(srv.sceneProvider->scene().robot->getGlobalOrientation().inverse());
1066 
1067  // ARMARX_VERBOSE
1068  // << deactivateSpam(100) << "Robot orientation "
1069  // << simox::math::mat3f_to_rpy(srv.sceneProvider->scene().robot->getGlobalOrientation()).z();
1070 
1071  // core::Twist robotFrameVelocity;
1072 
1073  // robotFrameVelocity.linear = robot_R_world * twist.linear;
1074  // // FIXME fix angular velocity
1075  // robotFrameVelocity.angular = twist.angular;
1076 
1077  // ARMARX_VERBOSE << deactivateSpam(1) << "velocity in robot frame "
1078  // << robotFrameVelocity.linear;
1079 
1080  srv.executor->execute(localPlan->trajectory, true);
1081  }
1082 
1083  void
1084  Navigator::updateExecutor(const std::optional<global_planning::GlobalPlannerResult>& globalPlan)
1085  {
1086  if (srv.executor == nullptr)
1087  {
1088  return;
1089  }
1090 
1091  ARMARX_IMPORTANT << "Requested to execute global plan with "
1092  << globalPlan->trajectory.points().size() << " points.";
1093 
1094 
1095  // if (isPaused() or isStopped())
1096  // {
1097  // // [[unlikely]]
1098  // ARMARX_VERBOSE << deactivateSpam(1) << "stopped or paused";
1099  // return;
1100  // }
1101 
1102  if (not globalPlan.has_value())
1103  {
1104  ARMARX_INFO << "Global plan is invalid!";
1105  srv.executor->stop();
1106  return;
1107  }
1108 
1109  ARMARX_IMPORTANT << "Executing global plan with " << globalPlan->trajectory.points().size()
1110  << " points.";
1111  srv.executor->execute(globalPlan->trajectory, false);
1112  }
1113 
1114  void
1115  Navigator::updateIntrospector(
1116  const std::optional<local_planning::LocalPlannerResult>& localPlan)
1117  {
1119 
1120  srv.introspector->onLocalPlannerResult(localPlan);
1121  }
1122 
1123  void
1124  Navigator::updateMonitor()
1125  {
1126  ARMARX_TRACE;
1127  ARMARX_CHECK(goalReachedMonitor.has_value());
1128 
1129  if (not isPaused() and goalReachedMonitor->goalReached())
1130  {
1131  // [[unlikely]]
1132 
1133  ARMARX_INFO << "Goal " << goalReachedMonitor->goal().translation().head<2>()
1134  << " reached!";
1135 
1136  stop();
1137 
1138  srv.publisher->goalReached(core::GoalReachedEvent{
1139  {armarx::Clock::Now()},
1140  {core::Pose(srv.sceneProvider->scene().robot->getGlobalPose())}});
1141 
1142  srv.introspector->success();
1143 
1144  // stop all threads, including this one
1145  ARMARX_INFO << "Stopping all threads";
1146  stopAllThreads();
1147 
1148  goalReachedMonitor.reset();
1149  goalReachedMonitor = std::nullopt;
1150  }
1151  }
1152 
1153  void
1154  Navigator::stopAllThreads()
1155  {
1156  stopIfRunning(runningTask);
1157  }
1158 
1159  // bool
1160  // Navigator::isStackResultValid() const noexcept
1161  // {
1162 
1163  // // global planner
1164  // if (config.stack.globalPlanner != nullptr)
1165  // {
1166  // if (not globalPlan.has_value())
1167  // {
1168  // ARMARX_VERBOSE << deactivateSpam(1) << "Global trajectory not yet set.";
1169  // return false;
1170  // }
1171  // }
1172 
1173  // // local planner
1174  // if (config.stack.localPlanner != nullptr)
1175  // {
1176  // if (not localPlan.has_value())
1177  // {
1178  // ARMARX_VERBOSE << deactivateSpam(1) << "Local trajectory not yet set.";
1179  // return false;
1180  // }
1181  // }
1182 
1183  // // [[likely]]
1184  // return true;
1185  // }
1186 
1187  // const core::Trajectory& Navigator::currentTrajectory() const
1188  // {
1189  // ARMARX_CHECK(isStackResultValid());
1190 
1191  // if(localPlan.has_value())
1192  // {
1193  // return localPlan->trajectory;
1194  // }
1195 
1196  // return globalPlan->trajectory;
1197  // }
1198 
1199  void
1201  {
1202  ARMARX_INFO << "Paused.";
1203 
1204  executorEnabled.store(false);
1205 
1206  if (srv.executor != nullptr)
1207  {
1208  ARMARX_INFO << "Stopping executor.";
1209  srv.executor->stop();
1210 
1211  }
1212  }
1213 
1214  void
1216  {
1217  ARMARX_INFO << "Resume.";
1218 
1219  executorEnabled.store(true);
1220 
1221  if (srv.executor != nullptr)
1222  {
1223  if (hasLocalPlanner())
1224  {
1226  }
1227  else
1228  {
1230  }
1231  }
1232  }
1233 
1234  void
1236  {
1237  ARMARX_INFO << "Stopping.";
1238 
1239  pause();
1240 
1241  // stop all threads, including this one
1242  stopAllThreads();
1243 
1244  goalReachedMonitor.reset();
1245  goalReachedMonitor = std::nullopt;
1246  }
1247 
1248  bool
1249  Navigator::isPaused() const noexcept
1250  {
1251  return not executorEnabled.load();
1252  }
1253 
1254  bool
1255  Navigator::isStopped() const noexcept
1256  {
1257  // TODO: Implement.
1258  return false;
1259  }
1260 
1261  Navigator::Navigator(Navigator&& other) noexcept :
1262  config{std::move(other.config)},
1263  srv{std::move(other.srv)},
1264  executorEnabled{other.executorEnabled.load()}
1265  {
1266  }
1267 } // namespace armarx::navigation::server
armarx::navigation::server::GraphPath
std::vector< semrel::ShapeID > GraphPath
Definition: Navigator.cpp:202
ice_conversions.h
armarx::navigation::core::GlobalTrajectory
Definition: Trajectory.h:68
armarx::navigation::core::Scene::graph
std::optional< core::SceneGraph > graph
Definition: types.h:81
armarx::navigation::server::IntrospectorInterface::failure
virtual void failure()=0
armarx::navigation::core::Scene::robot
VirtualRobot::RobotPtr robot
Definition: types.h:78
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::navigation::server::ExecutorInterface::stop
virtual void stop()=0
armarx::navigation::server::Navigator::InjectedServices::debugObserverHelper
armarx::DebugObserverHelper * debugObserverHelper
Definition: Navigator.h:86
armarx::navigation::server::Navigator::isPaused
bool isPaused() const noexcept override
Definition: Navigator.cpp:1249
armarx::navigation::core::resolveLocation
void resolveLocation(Graph::Vertex &vertex, const aron::data::DictPtr &locationData)
Definition: Graph.cpp:244
armarx::navigation::core::Scene::staticScene
std::optional< core::StaticScene > staticScene
Definition: types.h:75
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
LocalException.h
StackResult.h
armarx::navigation::core::NavigationFrame
NavigationFrame
Definition: types.h:43
armarx::navigation::server::EventPublishingInterface::goalReached
virtual void goalReached(const core::GoalReachedEvent &event)=0
Will be called whenever the navigator reached the goal.
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::navigation::server::ExecutorInterface::ControllerType::GlobalTrajectory
@ GlobalTrajectory
types.h
armarx::navigation::server::Navigator::~Navigator
~Navigator() override
Definition: Navigator.cpp:72
StopWatch.h
basic_types.h
armarx::navigation::client::GlobalPlanningStrategy::Free
@ Free
armarx::navigation::server::Navigator::InjectedServices::publisher
EventPublishingInterface * publisher
Definition: Navigator.h:83
armarx::navigation::server::Navigator::moveTowards
void moveTowards(const core::Direction &direction, core::NavigationFrame navigationFrame) override
Definition: Navigator.cpp:819
armarx::navigation::server::Navigator::InjectedServices::sceneProvider
scene_provider::SceneProviderInterface * sceneProvider
Definition: Navigator.h:88
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::navigation::global_planning::GlobalPlannerResult::trajectory
core::GlobalTrajectory trajectory
Definition: GlobalPlanner.h:40
LocalPlanner.h
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:688
ARMARX_CHECK_GREATER
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
Definition: ExpressionException.h:116
GoalReachedMonitor.h
trace.h
armarx::navigation::server::scene_provider::SceneProviderInterface::synchronize
virtual bool synchronize(const DateTime &timestamp, bool fullUpdate=false)=0
armarx::navigation::server::IntrospectorInterface::onGlobalGraph
virtual void onGlobalGraph(const core::Graph &graph)=0
armarx::navigation::server::Navigator::Config
Definition: Navigator.h:66
armarx::core::time::Duration::toMilliSecondsDouble
double toMilliSecondsDouble() const
Returns the amount of milliseconds.
Definition: Duration.cpp:76
armarx::navigation::server::Navigator::resume
void resume() override
Definition: Navigator.cpp:1215
armarx::navigation::server::Navigator::InjectedServices::introspector
IntrospectorInterface * introspector
Definition: Navigator.h:84
armarx::navigation::server::Navigator
Definition: Navigator.h:62
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
armarx::navigation::server::ExecutorInterface::ControllerType::LocalTrajectory
@ LocalTrajectory
armarx::navigation::server::Navigator::Config::general
General general
Definition: Navigator.h:77
armarx::navigation::server::Navigator::stop
void stop() override
Definition: Navigator.cpp:1235
armarx::navigation::server::EventPublishingInterface::localTrajectoryUpdated
virtual void localTrajectoryUpdated(const local_planning::LocalPlannerResult &res)=0
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
Clock.h
armarx::navigation::server::NavigationStack::localPlanner
local_planning::LocalPlannerPtr localPlanner
Definition: NavigationStack.h:37
GraphBuilder.h
events.h
armarx::navigation::server::ExecutorInterface::execute
virtual void execute(const core::LocalTrajectory &trajectory, bool activateController=false)=0
armarx::navigation::server
This file is part of ArmarX.
Definition: EventPublishingInterface.h:10
armarx::navigation::server::GoalReachedMonitor
Definition: GoalReachedMonitor.h:45
armarx::reverse
T reverse(const T &o)
Definition: container.h:32
armarx::navigation::server::Navigator::moveToLocation
void moveToLocation(const std::string &location) override
Definition: Navigator.cpp:824
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
armarx::navigation::server::Navigator::pause
void pause() override
Definition: Navigator.cpp:1200
armarx::navigation::core::NavigationFrame::Absolute
@ Absolute
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:147
armarx::navigation::server::IntrospectorInterface::onGoal
virtual void onGoal(const core::Pose &goal)=0
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::navigation::server::IntrospectorInterface::onGlobalShortestPath
virtual void onGlobalShortestPath(const std::vector< core::Pose > &path)=0
armarx::navigation::server::EventPublishingInterface::localPlanningFailed
virtual void localPlanningFailed(const core::LocalPlanningFailedEvent &event)=0
armarx::navigation::server::Navigator::Config::stack
server::NavigationStack stack
Definition: Navigator.h:76
LocationUtils.h
PathBuilder.h
armarx::navigation::server::EventPublishingInterface::globalPlanningFailed
virtual void globalPlanningFailed(const core::GlobalPlanningFailedEvent &event)=0
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
ObjectID.h
armarx::navigation::core::Graph
Definition: Graph.h:88
armarx::navigation::server::GoalReachedMonitorConfig
Definition: GoalReachedMonitor.h:34
armarx::navigation::server::ExecutorInterface::start
virtual void start(ControllerType controllerType)=0
GlobalPlanner.h
armarx::navigation::core::findPathsTo
std::vector< GraphPath > findPathsTo(Graph::ConstVertex vertex, const Graph &graph)
Definition: Graph.cpp:159
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::navigation::server::Navigator::InjectedServices
Definition: Navigator.h:80
controller_types.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::navigation::server::EventPublishingInterface::globalTrajectoryUpdated
virtual void globalTrajectoryUpdated(const global_planning::GlobalPlannerResult &res)=0
armarx::navigation::server::Navigator::isStopped
bool isStopped() const noexcept override
Definition: Navigator.cpp:1255
armarx::navigation::server::Navigator::InjectedServices::executor
ExecutorInterface * executor
Definition: Navigator.h:82
armarx::navigation::global_planning::GlobalPlannerResult
Definition: GlobalPlanner.h:38
armarx::navigation::server::ExecutorInterface::ensureIsActive
virtual void ensureIsActive(ControllerType controllerType)=0
ARMARX_CHECK_GREATER_EQUAL
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
Definition: ExpressionException.h:123
armarx::navigation::core::GoalReachedEvent
Event describing that the targeted goal was successfully reached.
Definition: events.h:49
armarx::navigation::server::EventPublishingInterface::movementStarted
virtual void movementStarted(const core::MovementStartedEvent &event)=0
armarx::navigation::server::scene_provider::SceneProviderInterface::scene
virtual const core::Scene & scene() const =0
ExpressionException.h
armarx::navigation::client::validate
void validate(const std::vector< WaypointTarget > &path)
Definition: ice_conversions.h:70
Graph.h
armarx::DebugObserverHelper::setDebugObserverDatafield
void setDebugObserverDatafield(const std::string &channelName, const std::string &datafieldName, const TimedVariantPtr &value) const
Definition: DebugObserverHelper.cpp:74
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::core::time::StopWatch::measure
static Duration measure(std::function< void(void)> subjectToMeasure, ClockType clockType=ClockType::Virtual)
Measures the duration needed to execute the given lambda and returns it.
Definition: StopWatch.cpp:34
armarx::navigation::server::IntrospectorInterface::success
virtual void success()=0
armarx::navigation::core::NavigationFrame::Relative
@ Relative
IceUtil::Handle
Definition: forward_declarations.h:29
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:315
armarx::navigation::core::Direction
Eigen::Vector3f Direction
Definition: basic_types.h:39
armarx::core::time::Duration
Represents a duration.
Definition: Duration.h:17
armarx::navigation::server::Navigator::moveTo
void moveTo(const std::vector< core::Pose > &waypoints, core::NavigationFrame navigationFrame) override
Definition: Navigator.cpp:145
armarx::navigation::server::Navigator::Config::General::tasks
struct armarx::navigation::server::Navigator::Config::General::@67 tasks
SceneProviderInterface.h
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:97
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::navigation::server::stopIfRunning
void stopIfRunning(PeriodicTask< Navigator >::pointer_type &task)
Definition: Navigator.cpp:56
armarx::navigation::server::Navigator::update
void update(const std::vector< core::Pose > &waypoints, core::NavigationFrame navigationFrame) override
Definition: Navigator.cpp:176
armarx::PeriodicTask
Definition: ArmarXManager.h:70
Logging.h
armarx::navigation::server::IntrospectorInterface::onLocalPlannerResult
virtual void onLocalPlannerResult(const std::optional< local_planning::LocalPlannerResult > &result)=0
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::navigation::server::Navigator::Navigator
Navigator(const Config &config, const InjectedServices &services)
Definition: Navigator.cpp:64
Trajectory.h
armarx::navigation::server::IntrospectorInterface::onGlobalPlannerResult
virtual void onGlobalPlannerResult(const global_planning::GlobalPlannerResult &result)=0
armarx::navigation::client::GlobalPlanningStrategy::Point2Point
@ Point2Point
armarx::navigation::server::NavigationStack::globalPlanner
global_planning::GlobalPlannerPtr globalPlanner
Definition: NavigationStack.h:36
armarx::navigation::server::findShortestPath
GraphPath findShortestPath(core::Graph graph, const core::Graph::ConstVertex &startVertex, const core::Graph::ConstVertex &goalVertex)
Definition: Navigator.cpp:205
armarx::navigation::server::IntrospectorInterface::onRobotPose
virtual void onRobotPose(const core::Pose &pose)=0
armarx::navigation::core::EdgeAttribs::m_value
float m_value
Definition: Graph.h:81
types.h
armarx::navigation::server::Navigator::Config::General::replanningUpdatePeriod
int replanningUpdatePeriod
Definition: Navigator.h:72
Navigator.h
armarx::armem::Duration
armarx::core::time::Duration Duration
Definition: forward_declarations.h:14
Reader.h
armarx::navigation::core::getSubgraph
const core::Graph & getSubgraph(const std::string &vertexName, const Graphs &graphs)
Definition: Graph.cpp:211
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
armarx::navigation::core::getVertexByName
Graph::ConstVertex getVertexByName(const std::string &vertexName, const Graph &graph)
Definition: Graph.cpp:186