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