GraphMemorySegment.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "GraphMemorySegment.h"
25 
26 #include <limits>
27 #include <unordered_map>
28 #include <unordered_set>
29 
31 
33 
34 memoryx::GraphMemorySegment::GraphMemorySegment(CollectionInterfacePrx entityCollection,
36  bool useMongoIds) :
37  PersistentEntitySegment(entityCollection, ic, useMongoIds), GraphMemorySegmentBase()
38 {
39 }
40 
42 {
43 }
44 
45 Ice::StringSeq
46 memoryx::GraphMemorySegment::getScenes(const Ice::Current& c) const
47 {
48  std::unordered_set<std::string> names{};
49  const auto ids = getAllEntityIds(c);
50 
51  for (const auto& id : ids)
52  {
53  auto elem = getNodeById(id, c);
54 
55  if (elem)
56  {
57  names.insert(elem->getScene());
58  }
59  }
60 
61  return Ice::StringSeq{names.begin(), names.end()};
62 }
63 
64 memoryx::GraphNodeBaseList
65 memoryx::GraphMemorySegment::getNodesByScene(const std::string& sceneName, const Ice::Current& c)
66 {
67  memoryx::GraphNodeBaseList result{};
68  auto filtered = getEntitiesByAttrValue(memoryx::GraphNode::GRAPH_NODE_ATTR_SCENE, sceneName, c);
69 
70  for (auto& elem : filtered)
71  {
72  auto ptr = memoryx::GraphNodeBasePtr::dynamicCast(elem);
73 
74  if (ptr)
75  {
76  result.push_back(ptr);
77  }
78  }
79 
80  return result;
81 }
82 
83 memoryx::GraphNodeBasePtr
84 memoryx::GraphMemorySegment::getNodeById(const std::string& entityId, const Ice::Current& c)
85 {
86  return memoryx::GraphNodeBasePtr::dynamicCast(getEntityById(entityId, c));
87 }
88 
89 memoryx::GraphNodeBasePtr
90 memoryx::GraphMemorySegment::getNodeById(const std::string& entityId, const Ice::Current& c) const
91 {
92  return memoryx::GraphNodeBasePtr::dynamicCast(getEntityById(entityId, c));
93 }
94 
95 memoryx::GraphNodeBasePtr
96 memoryx::GraphMemorySegment::getNodeByName(const std::string& entityName, const Ice::Current& c)
97 {
98  return memoryx::GraphNodeBasePtr::dynamicCast(getEntityByName(entityName, c));
99 }
100 
101 memoryx::GraphNodeBaseList
103 {
104  memoryx::GraphNodeBaseList nodes{};
105  const auto ids = getAllEntityIds(c);
106 
107  for (const auto& id : ids)
108  {
109  auto elem = getNodeById(id, c);
110 
111  if (elem)
112  {
113  nodes.push_back(elem);
114  }
115  }
116 
117  return nodes;
118 }
119 
120 void
121 memoryx::GraphMemorySegment::clearScene(const std::string& sceneName, const Ice::Current& c)
122 {
123  ARMARX_INFO_S << "GraphMemorySegment: clearing scene " << sceneName << "...";
124  auto filtered = getEntitiesByAttrValue(memoryx::GraphNode::GRAPH_NODE_ATTR_SCENE, sceneName, c);
125 
126  for (auto& elem : filtered)
127  {
128  removeEntity(elem->getId(c));
129  }
130 
131  ARMARX_INFO_S << "GraphMemorySegment: clearing scene " << sceneName << ". Removed "
132  << filtered.size() << " elements";
133 }
134 
135 bool
136 memoryx::GraphMemorySegment::removeNode(const std::string& nodeId, const Ice::Current&)
137 {
138  GraphNodeBasePtr node = getNodeById(nodeId);
139  auto allnodes = getAllNodes();
140  for (auto& curNode : allnodes)
141  {
142  if (curNode->removeAdjacentNode(nodeId))
143  {
144  updateEntity(curNode->getId(), curNode);
145  }
146  }
147  if (node)
148  {
149  removeEntity(nodeId);
150  return true;
151  }
152  return false;
153 }
154 
155 bool
156 memoryx::GraphMemorySegment::removeEdge(const std::string& startNodeId,
157  const std::string& endNodeId,
158  const Ice::Current&)
159 {
160  GraphNodeBasePtr startNode = getNodeById(startNodeId);
161  if (startNode)
162  {
163  if (startNode->removeAdjacentNode(endNodeId))
164  {
165  updateEntity(startNodeId, startNode);
166  return true;
167  }
168  }
169  return false;
170 }
171 
172 std::string
173 memoryx::GraphMemorySegment::addNode(const memoryx::GraphNodeBasePtr& node, const Ice::Current& c)
174 {
175  ARMARX_INFO_S << "GraphMemorySegment adding node " << (node ? node->getName() : "NULL node");
176  return addEntity(node, c);
177 }
178 
179 bool
180 memoryx::GraphMemorySegment::addEdge(const std::string& fromId,
181  const std::string& toId,
182  const Ice::Current& c)
183 {
184  ARMARX_INFO_S << "GraphMemorySegment adding edge " << fromId << " -> " << toId << "...";
185  auto fromNode = getNodeById(fromId, c);
186 
187  if (!fromNode)
188  {
189  ARMARX_ERROR_S << "GraphMemorySegment addEdge: Id " << fromId
190  << " does not reference a node";
191  return false;
192  }
193 
194  auto toNode = getNodeById(toId, c);
195 
196  if (!toNode)
197  {
198  ARMARX_ERROR_S << "GraphMemorySegment addEdge: Id " << toId << " does not reference a node";
199  return false;
200  }
201 
202  //this does not change the data stored in the segment
203  fromNode->addAdjacentNode(getEntityRefById(toId, c), c);
204  //update memory
205  updateEntity(fromId, fromNode, c);
206  ARMARX_INFO_S << "GraphMemorySegment adding edge " << fromId << " -> " << toId << "done!";
207  return true;
208 }
209 
210 bool
211 memoryx::GraphMemorySegment::hasScene(const ::std::string& sceneName, const ::Ice::Current& c)
212 {
213  return getEntitiesByAttrValue(memoryx::GraphNode::GRAPH_NODE_ATTR_SCENE, sceneName, c).size() >
214  0;
215 }
216 
217 bool
218 memoryx::GraphMemorySegment::hasNodeWithName(const ::std::string& sceneName,
219  const ::std::string& nodeName,
220  const ::Ice::Current&)
221 {
222  auto nodes = getNodesByScene(sceneName);
223 
224  for (const auto& node : nodes)
225  {
226  if (node->getName() == nodeName)
227  {
228  return true;
229  }
230  }
231 
232  return false;
233 }
234 
235 memoryx::GraphNodeBasePtr
237  const ::std::string& nodeName,
238  const ::Ice::Current&)
239 {
240  auto nodes = getNodesByScene(sceneName);
241 
242  for (const auto& node : nodes)
243  {
244  if (node->getName() == nodeName)
245  {
246  return node;
247  }
248  }
249 
250  return memoryx::GraphNodeBasePtr{};
251 }
252 
253 //std::string memoryx::GraphMemorySegment::getIdOfNearestNode(const ::std::string& sceneName, ::Ice::Float x, ::Ice::Float y, const ::Ice::Current&)
254 //{
255 // auto distQuad = [x, y](armarx::FramedPoseBasePtr && node)
256 // {
257 // float deltaX = x - node->position->x;
258 // float deltaY = y - node->position->y;
259 // return deltaX * deltaX + deltaY * deltaY;
260 // };
261 
262 // auto nodes = getNodesByScene(sceneName);
263 // std::string nearestId {};
264 // float distance = std::numeric_limits<float>::max();
265 
266 // for (const auto& nodeBase : nodes)
267 // {
268 // GraphNodePtr node = GraphNodePtr::dynamicCast(nodeBase);
269 // if (node->isMetaEntity())
270 // {
271 // continue;
272 // }
273 
274 // if (node->getPose()->frame == armarx::GlobalFrame || node->getPose()->frame.empty())
275 // {
276 // float currentDistance = distQuad(node->getPose());
277 
278 // if (currentDistance < distance)
279 // {
280 // nearestId = node->getId();
281 // distance = currentDistance;
282 // }
283 // }
284 // }
285 
286 // if (nearestId.empty())
287 // {
288 // ARMARX_WARNING_S << "Could not find nearest node for " << VAROUT(x) << VAROUT(y) << VAROUT(type) << VAROUT(sceneName);
289 // }
290 
291 // return nearestId;
292 //}
293 
294 memoryx::GraphNodeBaseList
295 memoryx::GraphMemorySegment::aStar(const ::std::string& idFrom,
296  const ::std::string& idTo,
297  const ::Ice::Current&)
298 {
299  //check everything
300  auto start = getNodeById(idFrom);
301  auto goal = getNodeById(idTo);
302 
303  if (!start)
304  {
305  std::stringstream s{};
306  s << "aStar: Node from: No node with ID: " << idFrom;
307  ARMARX_ERROR_S << s.str();
308  throw memoryx::EntityNotFoundException{s.str()};
309  }
310 
311  if (!goal)
312  {
313  std::stringstream s{};
314  ARMARX_ERROR_S << s.str();
315  s << "aStar: Node to: No node with ID: " << idTo;
316  throw memoryx::EntityNotFoundException{s.str()};
317  }
318 
319  ARMARX_VERBOSE_S << "memoryx::GraphMemorySegment::aStar from " << start->getPose()->frame
320  << " to " << goal->getPose()->frame;
321 
322 
323  if (start->getScene() != goal->getScene())
324  {
325  std::stringstream s{};
326  ARMARX_ERROR_S << s.str();
327  s << "aStar: Nodes from and to belong to different scenes: " << start->getScene() << " | "
328  << goal->getScene();
329  throw armarx::InvalidArgumentException{s.str()};
330  }
331 
332  /// TODO add some mutex
333  //copy state (in case the state gets altered during search) + memoryx::GraphNodeBasePtr now can be compared (ptr addresses are unique)
334  std::unordered_map<std::string, memoryx::GraphNodeBasePtr> nodes{};
335 
336  for (const auto& node : getNodesByScene(start->getScene()))
337  {
338  nodes[node->getId()] = node;
339  }
340 
341  //override start and goal to keep uniqueness
342  nodes[start->getId()] = start;
343  nodes[goal->getId()] = goal;
344 
345 
346  //init
347  auto dist = [](memoryx::GraphNodeBasePtr n1, memoryx::GraphNodeBasePtr n2)
348  {
349  auto p1 = n1->getPose();
350  auto p2 = n2->getPose();
351  const float dX = p1->position->x - p2->position->x;
352  const float dY = p1->position->y - p2->position->y;
353  return std::sqrt(dX * dX + dY * dY);
354  };
355 
356  memoryx::GraphNodeBaseList path{};
357  memoryx::GraphNodeBaseList closedSet{};
358  memoryx::GraphNodeBaseList openSet{};
359  openSet.push_back(start);
360 
361  std::unordered_map<std::string, float> gScore;
362  gScore[start->getId()] = 0.f;
363  std::unordered_map<std::string, float> fScore;
364  fScore[start->getId()] = gScore.at(start->getId()) + dist(start, goal);
365  std::unordered_map<std::string, memoryx::GraphNodeBasePtr> cameFrom;
366  cameFrom[goal->getId()] = start; //in case start==goal
367 
368  ARMARX_VERBOSE_S << "memoryx::GraphMemorySegment::aStar from " << idFrom << " to " << idTo
369  << ". Start path search.";
370 
371  while (!openSet.empty())
372  {
373  //find best neighbour
374  auto currentIT = std::min_element(
375  openSet.begin(),
376  openSet.end(),
377  [&fScore](const memoryx::GraphNodeBasePtr& a, const memoryx::GraphNodeBasePtr& b)
378  { return fScore.at(a->getId()) < fScore.at(b->getId()); });
379  assert(currentIT != openSet.end());
380  memoryx::GraphNodeBasePtr current = *currentIT;
381 
382 
383  //check if done
384  if (current->getId() == goal->getId())
385  {
386  auto cameFromNode = goal;
387 
388  while (cameFromNode->getId() != start->getId())
389  {
390  path.insert(path.begin(), cameFromNode);
391  cameFromNode = cameFrom.at(cameFromNode->getId());
392  }
393 
394  path.insert(path.begin(), start);
395  break;
396  }
397 
398  openSet.erase(currentIT);
399  closedSet.push_back(current);
400 
401  //update
402  for (int i = 0; i < current->getOutdegree(); i++)
403  {
404  auto neighbor = nodes.at(current->getAdjacentNode(i)->getEntity()->getId());
405 
406  assert(neighbor);
407 
408  if (std::find(closedSet.begin(), closedSet.end(), neighbor) != closedSet.end())
409  {
410  continue;
411  }
412 
413  float tentativeGScore = gScore.at(current->getId()) + dist(current, neighbor);
414  bool notInOS = std::find(openSet.begin(), openSet.end(), neighbor) == openSet.end();
415 
416  if (notInOS || tentativeGScore < gScore.at(neighbor->getId()))
417  {
418  cameFrom[neighbor->getId()] = current;
419  gScore[neighbor->getId()] = tentativeGScore;
420  fScore[neighbor->getId()] = tentativeGScore + dist(neighbor, goal);
421 
422  if (notInOS)
423  {
424  openSet.push_back(neighbor);
425  }
426  }
427  }
428  }
429 
430  ARMARX_VERBOSE_S << "memoryx::GraphMemorySegment::aStar from " << idFrom << " to " << idTo
431  << ". Done!";
432  return path;
433 }
memoryx::GraphMemorySegment::addEdge
bool addEdge(const std::string &fromId, const std::string &toId, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:180
cyberglove_with_calib_22dof.ic
ic
Definition: cyberglove_with_calib_22dof.py:22
memoryx::GraphMemorySegment::getNodesByScene
memoryx::GraphNodeBaseList getNodesByScene(const std::string &sceneName, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:65
memoryx::GraphMemorySegment::GraphMemorySegment
GraphMemorySegment(CollectionInterfacePrx entityCollection, Ice::CommunicatorPtr ic, bool useMongoIds=true)
Definition: GraphMemorySegment.cpp:34
memoryx::GraphMemorySegment::removeEdge
bool removeEdge(const std::string &startNodeId, const std::string &endNodeId, const Ice::Current &) override
Definition: GraphMemorySegment.cpp:156
memoryx::GraphMemorySegment::removeNode
bool removeNode(const std::string &, const Ice::Current &) override
Definition: GraphMemorySegment.cpp:136
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
memoryx::GraphMemorySegment::getNodeFromSceneByName
::memoryx::GraphNodeBasePtr getNodeFromSceneByName(const ::std::string &sceneName, const ::std::string &nodeName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:236
IceInternal::Handle<::Ice::Communicator >
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
FramedPose.h
memoryx::GraphMemorySegment::hasScene
bool hasScene(const ::std::string &sceneName, const ::Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:211
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:216
memoryx::GraphMemorySegment::getScenes
Ice::StringSeq getScenes(const Ice::Current &c=Ice::emptyCurrent) const override
Definition: GraphMemorySegment.cpp:46
memoryx::GraphMemorySegment::clearScene
void clearScene(const std::string &sceneName, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:121
GraphNode.h
memoryx::GraphMemorySegment::~GraphMemorySegment
~GraphMemorySegment() override
Definition: GraphMemorySegment.cpp:41
memoryx::GraphNode::GRAPH_NODE_ATTR_SCENE
static const std::string GRAPH_NODE_ATTR_SCENE
Definition: GraphNode.h:60
memoryx::GraphMemorySegment::getNodeByName
memoryx::GraphNodeBasePtr getNodeByName(const std::string &entityName, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:96
memoryx::GraphMemorySegment::hasNodeWithName
bool hasNodeWithName(const ::std::string &sceneName, const ::std::string &nodeName, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:218
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
armarx::viz::data::ElementFlags::names
const simox::meta::IntEnumNames names
Definition: json_elements.cpp:13
memoryx::GraphMemorySegment::getNodeById
memoryx::GraphNodeBasePtr getNodeById(const std::string &entityId, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:84
memoryx::PersistentEntitySegment
The PersistentEntitySegment class is the base class for all memory segments containing memoryx::Entit...
Definition: PersistentEntitySegment.h:105
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
memoryx::GraphMemorySegment::addNode
std::string addNode(const memoryx::GraphNodeBasePtr &node, const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:173
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
memoryx::GraphMemorySegment::getAllNodes
memoryx::GraphNodeBaseList getAllNodes(const Ice::Current &c=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:102
GraphMemorySegment.h
memoryx::GraphMemorySegment::aStar
::memoryx::GraphNodeBaseList aStar(const ::std::string &idFrom, const ::std::string &idTo, const ::Ice::Current &=Ice::emptyCurrent) override
Definition: GraphMemorySegment.cpp:295
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33