GraphBuilder.cpp
Go to the documentation of this file.
1 #include "GraphBuilder.h"
2 
3 #include <algorithm>
4 #include <cstddef>
5 #include <optional>
6 #include <vector>
7 
11 
13 
16 #include <armarx/navigation/core/aron/Graph.aron.generated.h>
18 
19 #include <SemanticObjectRelations/Shapes/Shape.h>
20 
22 {
23  const core::arondto::Edge ARON_UNSET_EDGE_VALUES = []()
24  {
25  core::arondto::Edge edge;
26  edge.sourceVertexID = -1;
27  edge.targetVertexID = -1;
28  return edge;
29  }();
30 
31  void
33  {
34  core::VertexAttribs attribs;
35  attribs.setPose(FramedPose(pose.matrix(), armarx::GlobalFrame, ""));
36 
37  const semrel::ShapeID shapeId(++vertexIdCnt);
38  graph.addVertex(shapeId, attribs);
39 
40  startVertex = graph.vertex(shapeId);
41 
42  // pedantic check
43  ARMARX_CHECK(startVertex->attrib().hasPose()) << "Start vertex must have a pose!";
44 
45  activeVertices_ = {shapeId};
46  }
47 
48  // const std::vector<core::Graph::VertexDescriptor>&
49  // GraphBuilder::activeVertices() const
50  // {
51  // return activeVertices_;
52  // }
53  void
55  {
57  getGraph(); // FIXME remove
58 
59  core::VertexAttribs attribs;
60  attribs.setPose(FramedPose(pose.matrix(), armarx::GlobalFrame, ""));
61 
62  const semrel::ShapeID shapeId(++vertexIdCnt); // TODO implement newShapeId()
63  graph.addVertex(shapeId, attribs);
64 
65 
66  // pedantic check
67  ARMARX_CHECK(graph.vertex(shapeId).attrib().hasPose()) << "Vertex pose must be set!";
68 
70  getGraph(); // FIXME remove
71 
72 
73  for (const semrel::ShapeID& activeVertexId : activeVertices_)
74  {
75  graph.addEdge(activeVertexId,
76  shapeId,
77  core::Graph::EdgeAttrib{.aron = ARON_UNSET_EDGE_VALUES,
78  .strategy = strategy,
79  .trajectory = std::nullopt});
80  }
81 
82  activeVertices_ = {shapeId};
83  }
84 
85  void
86  GraphBuilder::connect(const std::vector<core::Graph::VertexDescriptor>& routes,
87  const client::GlobalPlanningStrategy& strategy)
88  {
89  // for (const auto& vertex : activeVertices_)
90  // {
91  // graph.addEdge()
92  // }
93  }
94 
95  semrel::ShapeID
96  GraphBuilder::addOrGetVertex(const core::Graph::VertexAttrib& attributes)
97  {
98  const auto vertex = getVertexByAttributes(attributes);
99  if (vertex.has_value())
100  {
101  return vertex.value();
102  }
103 
104  const semrel::ShapeID shapeId(++vertexIdCnt);
105  graph.addVertex(shapeId, attributes);
106 
107  return shapeId;
108  }
109 
110  bool
111  operator==(const core::Graph::VertexAttrib& lhs, const core::Graph::VertexAttrib& rhs)
112  {
113  if (lhs.hasName() and rhs.hasName())
114  {
115  return lhs.getName() == rhs.getName();
116  };
117 
118  // otherwise:
119  // (1) only one of both has a name => not equal
120  // (2) both are 'anonymous' => not equal (by definition)
121  return false;
122  }
123 
124  std::optional<semrel::ShapeID>
125  GraphBuilder::getVertexByAttributes(const core::Graph::VertexAttrib& attributes)
126  {
127  auto vertices = graph.vertices();
128  const auto vIt = std::find_if(vertices.begin(),
129  vertices.end(),
130  [&attributes](const core::Graph::ConstVertex& vertex)
131  { return vertex.attrib() == attributes; });
132 
133  if (vIt != vertices.end()) // vertex exists
134  {
135  ARMARX_DEBUG << "Found matching vertex `" << vIt->attrib().getName() << "`";
136  return vIt->objectID();
137  }
138 
139  return std::nullopt;
140  }
141 
142  void
143  GraphBuilder::connect(const std::vector<core::GraphPath>& routes,
144  const client::GlobalPlanningStrategy& strategy)
145  {
146  ARMARX_CHECK(not routes.empty())
147  << "Routes must exist. Otherwise, the graph will not have any active connections!";
148 
149  // all active vertices will be connected to all routes
150  for (const auto& vertex : activeVertices_)
151  {
152  for (const auto& route : routes)
153  {
154  if (route.empty())
155  {
156  continue;
157  }
158 
159  // The shape ids of the routes passed to this function are not meaningful. They will be changed.
160  std::vector<semrel::ShapeID> routeShapeIds;
161 
162  ARMARX_TRACE;
163 
164  // add all vertices to the graph
165  for (const auto& vertex : route)
166  {
167  ARMARX_CHECK(vertex.attrib().hasPose())
168  << "Vertex on the route must have a pose!";
169 
170  const semrel::ShapeID shapeId = addOrGetVertex(vertex.attrib());
171  routeShapeIds.push_back(shapeId);
172 
173  // pedantic check
174  ARMARX_CHECK(graph.vertex(shapeId).attrib().hasPose())
175  << "Vertex pose must be set!";
176  }
177 
178  ARMARX_TRACE;
179 
180  // add all edges to the graph (between consecutive vertices)
181  for (size_t i = 0; i < route.size() - 1; i++)
182  {
183  graph.addEdge(routeShapeIds.at(i),
184  routeShapeIds.at(i + 1),
185  core::Graph::EdgeAttrib{
186  .aron = ARON_UNSET_EDGE_VALUES,
187  .strategy = client::GlobalPlanningStrategy::Point2Point,
188  .trajectory = std::nullopt});
189  }
190 
191  ARMARX_TRACE;
192  // connect `vertex` an this path
193  graph.addEdge(graph.vertex(vertex).objectID(),
194  routeShapeIds.front(),
195  core::Graph::EdgeAttrib{.aron = ARON_UNSET_EDGE_VALUES,
196  .strategy = strategy,
197  .trajectory = std::nullopt});
198  }
199  }
200 
201  // By definition, all routes share the same final vertex, which is the new active vertex ...
202  const auto targetDescriptor = routes.front().back().descriptor();
203  // ... this is ensured by the following check ...
204  ARMARX_CHECK(std::none_of(routes.begin(),
205  routes.end(),
206  [&targetDescriptor](const auto& route) -> bool
207  { return route.back().descriptor() != targetDescriptor; }));
208 
209  // ... and will be the new active vertex.
210  const std::optional<semrel::ShapeID> shapeId =
211  getVertexByAttributes(routes.front().back().attrib());
212  ARMARX_CHECK(shapeId.has_value()) << "Vertex exists. This should not have happened";
213 
214 
215  activeVertices_ = {shapeId.value()};
216  }
217 
218  inline void
219  GraphBuilder::validate(auto&& vertices) const
220  {
221  ARMARX_TRACE;
222  std::for_each(vertices.begin(),
223  vertices.end(),
224  [](const core::Graph::ConstVertex& vertex)
225  {
226  // ARMARX_CHECK(graph.vertex(vertex.objectID()).attrib().hasPose())
227  // << "Check 1: Vertex `" << vertex.attrib().getName() << "`"
228  // << " with ID " << vertex.attrib().objectID
229  // << " does not have pose attribute!";
230 
231  ARMARX_CHECK(vertex.attrib().hasPose())
232  << "Check 2: Vertex `" << vertex.attrib().getName() << "`"
233  << " with ID " << vertex.attrib().objectID
234  << " does not have pose attribute!";
235  });
236  }
237 
238  const core::Graph&
240  {
241  validate(graph.vertices());
242  return graph;
243  }
244 
245  core::Graph::VertexDescriptor
247  {
248  ARMARX_CHECK(activeVertices_.size() == 1) << "There should be only one goal vertex.";
249  return activeVertices_.front();
250  }
251 
252  core::Pose
254  {
255  return getGraph().vertex(goalVertex()).attrib().requireGlobal();
256  }
257 
258  // void
259  // GraphBuilder::addEdge(const std::vector<core::Graph::VertexDescriptor>& sources,
260  // const std::vector<core::Graph::VertexDescriptor>& targets)
261  // {
262 
263  // for (const core::Graph::VertexDescriptor& source : sources)
264  // {
265  // for (const core::Graph::VertexDescriptor& target : targets)
266  // {
267  // // connect source and target
268  // // FIXME implement graph.addEdge(source.)
269  // }
270  // }
271  // }
272 } // namespace armarx::navigation::server
armarx::navigation::server::operator==
bool operator==(const core::Graph::VertexAttrib &lhs, const core::Graph::VertexAttrib &rhs)
Definition: GraphBuilder.cpp:111
armarx::navigation::server::GraphBuilder::getGraph
const core::Graph & getGraph() const
Definition: GraphBuilder.cpp:239
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
types.h
basic_types.h
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:36
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
trace.h
armarx::navigation::server::GraphBuilder::goalVertex
core::Graph::VertexDescriptor goalVertex() const
Definition: GraphBuilder.cpp:246
armarx::navigation::server::GraphBuilder::initialize
void initialize(const core::Pose &pose)
Definition: GraphBuilder.cpp:32
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
GraphBuilder.h
armarx::navigation::server
This file is part of ArmarX.
Definition: EventPublishingInterface.h:6
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
FramedPose.h
armarx::navigation::server::GraphBuilder::startVertex
std::optional< core::Graph::ConstVertex > startVertex
Definition: GraphBuilder.h:64
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::navigation::core::Graph
Definition: Graph.h:89
armarx::navigation::server::GraphBuilder::goalPose
core::Pose goalPose() const
Definition: GraphBuilder.cpp:253
armarx::navigation::server::GraphBuilder::connect
void connect(const core::Pose &pose, const client::GlobalPlanningStrategy &strategy)
Definition: GraphBuilder.cpp:54
ExpressionException.h
armarx::navigation::server::ARON_UNSET_EDGE_VALUES
const core::arondto::Edge ARON_UNSET_EDGE_VALUES
Definition: GraphBuilder.cpp:23
Graph.h
armarx::navigation::core::VertexAttribs
Definition: Graph.h:44
armarx::navigation::client::GlobalPlanningStrategy
GlobalPlanningStrategy
Definition: types.h:27
Logging.h
armarx::navigation::core::VertexAttribs::setPose
void setPose(const FramedPose &pose)
Definition: Graph.cpp:78