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