GraphNodePoseResolver.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2012-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 MemoryX::ArmarXObjects::GraphNodePoseResolver
19 * @author Valerij Wittenbeck ( valerij.wittenbeck at student dot kit dot edu )
20 * @date 2015
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#include <VirtualRobot/MathTools.h>
26
29
30namespace memoryx
31{
32
36
37 void
39 {
40 usingProxy(getProperty<std::string>("WorkingMemoryName").getValue());
41 // usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
42 usingProxy("PriorKnowledge");
43 }
44
45 void
47 {
49 getProperty<std::string>("WorkingMemoryName").getValue());
50 prior = getProxy<PriorKnowledgeInterfacePrx>("PriorKnowledge");
51
52 try
53 {
54 sleep(1); //let's wait for it a bit
56 getProperty<std::string>("RobotStateComponentName").getValue());
57 }
58 catch (...)
59 {
60 ARMARX_IMPORTANT << "RobotStateComponent proxy not found, continuing without...";
61 }
62
63 graphSegment = prior->getGraphSegment();
64 objectInstances = wm->getObjectInstancesSegment();
65
66 relativePlacesettingPositions["placesetting"]["cup"] =
67 new armarx::FramedPosition(Eigen::Vector3f{180.f, 180.f, 0.f}, "roundtable", "");
68 }
69
70 void
74
75 void
79
82 const GraphNodeBasePtr& node)
83 {
84 auto objSeg = prior->getObjectClassesSegment();
85
86 for (const auto& placesetting : relativePlacesettingPositions)
87 {
88 std::string settingName = placesetting.first;
89
90 if (node->getName().find(settingName) != std::string::npos)
91 {
92 for (const auto& relativePosition : placesetting.second)
93 {
94 if (objectClassName != relativePosition.first &&
95 !objSeg->isParentClass(objectClassName, relativePosition.first))
96 {
97 continue;
98 }
99
100 armarx::FramedPositionPtr pos = relativePosition.second;
101 auto poseMat = armarx::FramedPosePtr::dynamicCast(node->getPose())->toEigen();
102 auto offset = poseMat.block<3, 3>(0, 0) * pos->toEigen();
103 poseMat.block<3, 1>(0, 3) += offset;
104 return new armarx::FramedPose(poseMat, pos->frame, "");
105 break;
106 }
107 }
108 }
109
110 return armarx::FramedPosePtr();
111 }
112
113 GraphNodePoseResolver::CachedNodeInfo
114 GraphNodePoseResolver::getCacheEntry(const std::string& nodeId)
115 {
116 std::unique_lock lock(cacheMutex);
117 auto it = nodeInfoCache.find(nodeId);
118 if (it != nodeInfoCache.end())
119 {
120 return it->second;
121 }
122
123 GraphNodePtr node = GraphNodePtr::dynamicCast(graphSegment->getEntityById(nodeId));
124 const auto nodePose = armarx::FramedPosePtr::dynamicCast(node->getPose());
125
126 armarx::FramedPosePtr globalPose = nodePose;
127
128 if (nodePose->frame != armarx::GlobalFrame && !nodePose->frame.empty())
129 {
130 auto instances = objectInstances->getObjectInstancesByClass(nodePose->frame);
131
132 if (instances.empty())
133 {
134 ARMARX_WARNING_S << "No object instances of object class " + nodePose->frame +
135 " found";
136 throw NodeNotResolveableException("No object instances of object class " +
137 nodePose->frame + " found");
138 }
139
140 ObjectInstancePtr objInstance = ObjectInstancePtr::dynamicCast(instances.front());
141
142 armarx::FramedPosePtr instancePose = objInstance->getPose();
143 bool instanceFrameGlobal =
144 instancePose->frame == armarx::GlobalFrame || instancePose->frame.empty();
145 bool needToConvertToGlobal = !instanceFrameGlobal && rsc &&
146 rsc->getSynchronizedRobot() &&
147 rsc->getSynchronizedRobot()->getGlobalPose();
148 ARMARX_CHECK_EXPRESSION(!needToConvertToGlobal)
149 << "RobotStateComponent cannot be null when an object's frame is not global "
150 "(object '"
151 << objInstance->getName() << "', frame: '" << instancePose->frame << "')";
152
153 Eigen::Matrix4f globalObjPose;
154 if (needToConvertToGlobal)
155 {
156 globalObjPose = instancePose->toGlobal(rsc->getSynchronizedRobot())->toEigen();
157 }
158 else
159 {
160 globalObjPose = instancePose->toEigen();
161 }
162
163 Eigen::Matrix4f localNodePose = nodePose->toEigen();
164 Eigen::Matrix4f globalNodePose = globalObjPose * localNodePose;
165 globalPose = new armarx::FramedPose(globalNodePose, armarx::GlobalFrame, "");
166 }
167
168 CachedNodeInfo newInfo{node, globalPose, node->getAllParentsAsStringList()};
169 nodeInfoCache.insert({node->getId(), newInfo});
170 return newInfo;
171 }
172
173 GraphNodeBasePtr
174 GraphNodePoseResolver::getNearestNodeToPoseImpl(const std::string& sceneName,
175 const std::string& nodeParentName,
176 const Eigen::Matrix4f& pose,
177 bool ignoreOrientation,
178 bool ignoreParent)
179 {
180 bool graphHasParent = graphSegment->getNodeFromSceneByName(sceneName, nodeParentName);
181 float distDeltaThreshold = 200.f;
182 float minDist = std::numeric_limits<float>::max();
183 float minDegDist = std::numeric_limits<float>::max();
184 float degDist = minDist;
185 GraphNodePtr closestNode;
186 Eigen::Matrix4f closestNodeEigenPose = Eigen::Matrix4f::Identity();
187
188 std::unique_lock lock(cacheMutex);
189 auto it = sceneNodesCache.find(sceneName);
190 if (it == sceneNodesCache.end())
191 {
192 it =
193 sceneNodesCache.insert({sceneName, graphSegment->getNodesByScene(sceneName)}).first;
194 }
195
196 for (const auto& node : it->second)
197 {
198 CachedNodeInfo nodeInfo;
199 try
200 {
201 nodeInfo = getCacheEntry(node->getId());
202 }
203 catch (armarx::LocalException& e)
204 {
205 ARMARX_ERROR << e.what();
206 continue;
207 }
208
209 //last term is for backwards-compability; where nodes don't have parents yet
210 bool validParentship =
211 ignoreParent ||
212 std::find(nodeInfo.parents.cbegin(), nodeInfo.parents.cend(), nodeParentName) !=
213 nodeInfo.parents.cend() ||
214 (!graphHasParent && nodeInfo.parents.empty());
215 auto nodePoseEigen = nodeInfo.globalPose->toEigen();
216
217 if (!validParentship || nodeInfo.node->getScene() != sceneName ||
218 nodeInfo.node->isMetaEntity())
219 {
220 continue;
221 }
222
223 if (!ignoreOrientation)
224 {
225 Eigen::Matrix3f diffRot =
226 pose.block<3, 3>(0, 0) * nodePoseEigen.block<3, 3>(0, 0).inverse();
227
228 Eigen::Matrix4f diffPose = Eigen::Matrix4f::Identity();
229 diffPose.block<3, 3>(0, 0) = diffRot;
230 Eigen::Vector3f axis;
231 VirtualRobot::MathTools::eigen4f2axisangle(diffPose, axis, degDist);
232 degDist *= 180 / M_PI;
233 }
234
235 const float dist = (pose.block<2, 1>(0, 3) - nodePoseEigen.block<2, 1>(0, 3)).norm();
236 const float candidateDist =
237 (closestNodeEigenPose.block<2, 1>(0, 3) - nodePoseEigen.block<2, 1>(0, 3)).norm();
238
239 ARMARX_DEBUG << "for query (" << pose(0, 3) << ", " << pose(1, 3)
240 << "), considering node: '" << nodeInfo.node->getName() << "', scene '"
241 << nodeInfo.node->getScene() << "'"
242 << ", distances: " << dist << ", " << candidateDist << ", " << degDist;
243
244 const bool inAmbiguousZone = candidateDist < distDeltaThreshold;
245
246 if (!closestNode || (inAmbiguousZone && fabs(degDist) < minDegDist) ||
247 (!inAmbiguousZone && fabs(dist) <= minDist))
248 {
249 minDist = dist;
250 minDegDist = degDist;
251 closestNode = nodeInfo.node;
252 closestNodeEigenPose = nodePoseEigen;
253 }
254 }
255
256 ARMARX_CHECK_EXPRESSION(closestNode) << "Could not find closest node to query: '"
257 << sceneName << "', '" << nodeParentName << "',\n"
258 << pose;
259 return closestNode;
260 }
261
262 armarx::FramedPoseBasePtr
263 GraphNodePoseResolver::resolveToGlobalPose(const GraphNodeBasePtr& node, const Ice::Current&)
264 {
265 ARMARX_CHECK_EXPRESSION(node) << "input node cannot be null";
266
267 return getCacheEntry(node->getId()).globalPose;
268 }
269
270 std::string
272 const std::string& nodeParentName,
273 Ice::Float x,
274 Ice::Float y,
275 const Ice::Current&)
276 {
277 return getNearestNodeToPosition(sceneName, nodeParentName, x, y)->getId();
278 }
279
280 GraphNodeBasePtr
282 const std::string& nodeParentName,
283 Ice::Float x,
284 Ice::Float y,
285 const Ice::Current&)
286 {
287 Eigen::Matrix4f pose = Eigen::Matrix4f::Identity();
288 pose(0, 3) = x;
289 pose(1, 3) = y;
290
291 return getNearestNodeToPoseImpl(
292 sceneName, nodeParentName, pose, true, nodeParentName.empty());
293 }
294
295 std::string
297 const std::string& nodeParentName,
298 const armarx::FramedPoseBasePtr& pose,
299 const Ice::Current&)
300 {
301 return getNearestNodeToPose(sceneName, nodeParentName, pose)->getId();
302 }
303
304 GraphNodeBasePtr
306 const std::string& nodeParentName,
307 const armarx::FramedPoseBasePtr& pose,
308 const Ice::Current&)
309 {
310 auto poseEigen = armarx::FramedPosePtr::dynamicCast(pose)->toEigen();
311 return getNearestNodeToPoseImpl(
312 sceneName, nodeParentName, poseEigen, false, nodeParentName.empty());
313 }
314
315 std::string
317 const Ice::Current&)
318 {
319 return getNearestRobotLocationNode(node)->getId();
320 }
321
322 GraphNodeBasePtr
324 const Ice::Current&)
325 {
326 ARMARX_CHECK_EXPRESSION(node) << "node argument cannot be null";
327
328 const CachedNodeInfo& inputNodeInfo = getCacheEntry(node->getId());
329 return getNearestNodeToPoseImpl(
330 inputNodeInfo.node->getScene(), "robotlocation", inputNodeInfo.globalPose->toEigen());
331 }
332
333 void
334 GraphNodePoseResolver::forceRefetch(const std::string& nodeId, const Ice::Current&)
335 {
336 std::unique_lock lock(cacheMutex);
337 auto it = nodeInfoCache.find(nodeId);
338 if (it != nodeInfoCache.end())
339 {
340 nodeInfoCache.erase(it);
341 }
342 sceneNodesCache.clear();
343 }
344
345 void
347 {
348 std::unique_lock lock(cacheMutex);
349 nodeInfoCache.clear();
350 sceneNodesCache.clear();
351 }
352} // namespace memoryx
#define M_PI
Definition MathTools.h:17
Property< PropertyType > getProperty(const std::string &name)
The FramedPose class.
Definition FramedPose.h:281
The FramedPosition class.
Definition FramedPose.h:158
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
GraphNodeBasePtr getNearestRobotLocationNode(const GraphNodeBasePtr &node, const ::Ice::Current &=Ice::emptyCurrent) override
GraphNodeBasePtr getNearestNodeToPosition(const std::string &sceneName, const std::string &nodeParentName, ::Ice::Float x, ::Ice::Float y, const ::Ice::Current &=Ice::emptyCurrent) override
GraphNodeBasePtr getNearestNodeToPose(const std::string &sceneName, const std::string &nodeParentName, const armarx::FramedPoseBasePtr &pose, const ::Ice::Current &=Ice::emptyCurrent) override
armarx::FramedPosePtr getRelativeNodePositionForObject(const std::string &objectClassName, const GraphNodeBasePtr &node)
armarx::FramedPoseBasePtr resolveToGlobalPose(const GraphNodeBasePtr &node, const ::Ice::Current &=Ice::emptyCurrent) override
std::string getNearestNodeIdToPose(const std::string &sceneName, const std::string &nodeParentName, const armarx::FramedPoseBasePtr &pose, const ::Ice::Current &=Ice::emptyCurrent) override
void forceRefetch(const std::string &nodeId, const ::Ice::Current &=Ice::emptyCurrent) override
std::string getNearestRobotLocationNodeId(const GraphNodeBasePtr &node, const ::Ice::Current &=Ice::emptyCurrent) override
void forceRefetchForAll(const ::Ice::Current &=Ice::emptyCurrent) override
std::string getNearestNodeIdToPosition(const std::string &sceneName, const std::string &nodeParentName, ::Ice::Float x, ::Ice::Float y, const ::Ice::Current &=Ice::emptyCurrent) override
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
VirtualRobot headers.
IceInternal::Handle< ObjectInstance > ObjectInstancePtr
IceInternal::Handle< GraphNode > GraphNodePtr
Definition GraphNode.h:47
double norm(const Point &a)
Definition point.hpp:102