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