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
28
31
32namespace memoryx
33{
34
38
39 void
41 {
42 usingProxy(getProperty<std::string>("WorkingMemoryName").getValue());
43 // usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
44 usingProxy("PriorKnowledge");
45 }
46
47 void
49 {
51 getProperty<std::string>("WorkingMemoryName").getValue());
52 prior = getProxy<PriorKnowledgeInterfacePrx>("PriorKnowledge");
53
54 try
55 {
56 sleep(1); //let's wait for it a bit
58 getProperty<std::string>("RobotStateComponentName").getValue());
59 }
60 catch (...)
61 {
62 ARMARX_IMPORTANT << "RobotStateComponent proxy not found, continuing without...";
63 }
64
65 graphSegment = prior->getGraphSegment();
66 objectInstances = wm->getObjectInstancesSegment();
67
68 relativePlacesettingPositions["placesetting"]["cup"] =
69 new armarx::FramedPosition(Eigen::Vector3f{180.f, 180.f, 0.f}, "roundtable", "");
70 }
71
72 void
76
77 void
81
84 const GraphNodeBasePtr& node)
85 {
86 auto objSeg = prior->getObjectClassesSegment();
87
88 for (const auto& placesetting : relativePlacesettingPositions)
89 {
90 std::string settingName = placesetting.first;
91
92 if (node->getName().find(settingName) != std::string::npos)
93 {
94 for (const auto& relativePosition : placesetting.second)
95 {
96 if (objectClassName != relativePosition.first &&
97 !objSeg->isParentClass(objectClassName, relativePosition.first))
98 {
99 continue;
100 }
101
102 armarx::FramedPositionPtr pos = relativePosition.second;
103 auto poseMat = armarx::FramedPosePtr::dynamicCast(node->getPose())->toEigen();
104 auto offset = poseMat.block<3, 3>(0, 0) * pos->toEigen();
105 poseMat.block<3, 1>(0, 3) += offset;
106 return new armarx::FramedPose(poseMat, pos->frame, "");
107 break;
108 }
109 }
110 }
111
112 return armarx::FramedPosePtr();
113 }
114
115 GraphNodePoseResolver::CachedNodeInfo
116 GraphNodePoseResolver::getCacheEntry(const std::string& nodeId)
117 {
118 std::unique_lock lock(cacheMutex);
119 auto it = nodeInfoCache.find(nodeId);
120 if (it != nodeInfoCache.end())
121 {
122 return it->second;
123 }
124
125 GraphNodePtr node = GraphNodePtr::dynamicCast(graphSegment->getEntityById(nodeId));
126 const auto nodePose = armarx::FramedPosePtr::dynamicCast(node->getPose());
127
128 armarx::FramedPosePtr globalPose = nodePose;
129
130 if (nodePose->frame != armarx::GlobalFrame && !nodePose->frame.empty())
131 {
132 auto instances = objectInstances->getObjectInstancesByClass(nodePose->frame);
133
134 if (instances.empty())
135 {
136 ARMARX_WARNING_S << "No object instances of object class " + nodePose->frame +
137 " found";
138 throw NodeNotResolveableException("No object instances of object class " +
139 nodePose->frame + " found");
140 }
141
142 ObjectInstancePtr objInstance = ObjectInstancePtr::dynamicCast(instances.front());
143
144 armarx::FramedPosePtr instancePose = objInstance->getPose();
145 bool instanceFrameGlobal =
146 instancePose->frame == armarx::GlobalFrame || instancePose->frame.empty();
147 bool needToConvertToGlobal = !instanceFrameGlobal && rsc &&
148 rsc->getSynchronizedRobot() &&
149 rsc->getSynchronizedRobot()->getGlobalPose();
150 ARMARX_CHECK_EXPRESSION(!needToConvertToGlobal)
151 << "RobotStateComponent cannot be null when an object's frame is not global "
152 "(object '"
153 << objInstance->getName() << "', frame: '" << instancePose->frame << "')";
154
155 Eigen::Matrix4f globalObjPose;
156 if (needToConvertToGlobal)
157 {
158 globalObjPose = instancePose->toGlobal(rsc->getSynchronizedRobot())->toEigen();
159 }
160 else
161 {
162 globalObjPose = instancePose->toEigen();
163 }
164
165 Eigen::Matrix4f localNodePose = nodePose->toEigen();
166 Eigen::Matrix4f globalNodePose = globalObjPose * localNodePose;
167 globalPose = new armarx::FramedPose(globalNodePose, armarx::GlobalFrame, "");
168 }
169
170 CachedNodeInfo newInfo{node, globalPose, node->getAllParentsAsStringList()};
171 nodeInfoCache.insert({node->getId(), newInfo});
172 return newInfo;
173 }
174
175 GraphNodeBasePtr
176 GraphNodePoseResolver::getNearestNodeToPoseImpl(const std::string& sceneName,
177 const std::string& nodeParentName,
178 const Eigen::Matrix4f& pose,
179 bool ignoreOrientation,
180 bool ignoreParent)
181 {
182 bool graphHasParent = graphSegment->getNodeFromSceneByName(sceneName, nodeParentName);
183 float distDeltaThreshold = 200.f;
184 float minDist = std::numeric_limits<float>::max();
185 float minDegDist = std::numeric_limits<float>::max();
186 float degDist = minDist;
187 GraphNodePtr closestNode;
188 Eigen::Matrix4f closestNodeEigenPose = Eigen::Matrix4f::Identity();
189
190 std::unique_lock lock(cacheMutex);
191 auto it = sceneNodesCache.find(sceneName);
192 if (it == sceneNodesCache.end())
193 {
194 it =
195 sceneNodesCache.insert({sceneName, graphSegment->getNodesByScene(sceneName)}).first;
196 }
197
198 for (const auto& node : it->second)
199 {
200 CachedNodeInfo nodeInfo;
201 try
202 {
203 nodeInfo = getCacheEntry(node->getId());
204 }
205 catch (armarx::LocalException& e)
206 {
207 ARMARX_ERROR << e.what();
208 continue;
209 }
210
211 //last term is for backwards-compability; where nodes don't have parents yet
212 bool validParentship =
213 ignoreParent ||
214 std::find(nodeInfo.parents.cbegin(), nodeInfo.parents.cend(), nodeParentName) !=
215 nodeInfo.parents.cend() ||
216 (!graphHasParent && nodeInfo.parents.empty());
217 auto nodePoseEigen = nodeInfo.globalPose->toEigen();
218
219 if (!validParentship || nodeInfo.node->getScene() != sceneName ||
220 nodeInfo.node->isMetaEntity())
221 {
222 continue;
223 }
224
225 if (!ignoreOrientation)
226 {
227 Eigen::Matrix3f diffRot =
228 pose.block<3, 3>(0, 0) * nodePoseEigen.block<3, 3>(0, 0).inverse();
229
230 Eigen::Matrix4f diffPose = Eigen::Matrix4f::Identity();
231 diffPose.block<3, 3>(0, 0) = diffRot;
232 Eigen::Vector3f axis;
233 VirtualRobot::MathTools::eigen4f2axisangle(diffPose, axis, degDist);
234 degDist *= 180 / M_PI;
235 }
236
237 const float dist = (pose.block<2, 1>(0, 3) - nodePoseEigen.block<2, 1>(0, 3)).norm();
238 const float candidateDist =
239 (closestNodeEigenPose.block<2, 1>(0, 3) - nodePoseEigen.block<2, 1>(0, 3)).norm();
240
241 ARMARX_DEBUG << "for query (" << pose(0, 3) << ", " << pose(1, 3)
242 << "), considering node: '" << nodeInfo.node->getName() << "', scene '"
243 << nodeInfo.node->getScene() << "'"
244 << ", distances: " << dist << ", " << candidateDist << ", " << degDist;
245
246 const bool inAmbiguousZone = candidateDist < distDeltaThreshold;
247
248 if (!closestNode || (inAmbiguousZone && fabs(degDist) < minDegDist) ||
249 (!inAmbiguousZone && fabs(dist) <= minDist))
250 {
251 minDist = dist;
252 minDegDist = degDist;
253 closestNode = nodeInfo.node;
254 closestNodeEigenPose = nodePoseEigen;
255 }
256 }
257
258 ARMARX_CHECK_EXPRESSION(closestNode) << "Could not find closest node to query: '"
259 << sceneName << "', '" << nodeParentName << "',\n"
260 << pose;
261 return closestNode;
262 }
263
264 armarx::FramedPoseBasePtr
265 GraphNodePoseResolver::resolveToGlobalPose(const GraphNodeBasePtr& node, const Ice::Current&)
266 {
267 ARMARX_CHECK_EXPRESSION(node) << "input node cannot be null";
268
269 return getCacheEntry(node->getId()).globalPose;
270 }
271
272 std::string
274 const std::string& nodeParentName,
275 Ice::Float x,
276 Ice::Float y,
277 const Ice::Current&)
278 {
279 return getNearestNodeToPosition(sceneName, nodeParentName, x, y)->getId();
280 }
281
282 GraphNodeBasePtr
284 const std::string& nodeParentName,
285 Ice::Float x,
286 Ice::Float y,
287 const Ice::Current&)
288 {
289 Eigen::Matrix4f pose = Eigen::Matrix4f::Identity();
290 pose(0, 3) = x;
291 pose(1, 3) = y;
292
293 return getNearestNodeToPoseImpl(
294 sceneName, nodeParentName, pose, true, nodeParentName.empty());
295 }
296
297 std::string
299 const std::string& nodeParentName,
300 const armarx::FramedPoseBasePtr& pose,
301 const Ice::Current&)
302 {
303 return getNearestNodeToPose(sceneName, nodeParentName, pose)->getId();
304 }
305
306 GraphNodeBasePtr
308 const std::string& nodeParentName,
309 const armarx::FramedPoseBasePtr& pose,
310 const Ice::Current&)
311 {
312 auto poseEigen = armarx::FramedPosePtr::dynamicCast(pose)->toEigen();
313 return getNearestNodeToPoseImpl(
314 sceneName, nodeParentName, poseEigen, false, nodeParentName.empty());
315 }
316
317 std::string
319 const Ice::Current&)
320 {
321 return getNearestRobotLocationNode(node)->getId();
322 }
323
324 GraphNodeBasePtr
326 const Ice::Current&)
327 {
328 ARMARX_CHECK_EXPRESSION(node) << "node argument cannot be null";
329
330 const CachedNodeInfo& inputNodeInfo = getCacheEntry(node->getId());
331 return getNearestNodeToPoseImpl(
332 inputNodeInfo.node->getScene(), "robotlocation", inputNodeInfo.globalPose->toEigen());
333 }
334
335 void
336 GraphNodePoseResolver::forceRefetch(const std::string& nodeId, const Ice::Current&)
337 {
338 std::unique_lock lock(cacheMutex);
339 auto it = nodeInfoCache.find(nodeId);
340 if (it != nodeInfoCache.end())
341 {
342 nodeInfoCache.erase(it);
343 }
344 sceneNodesCache.clear();
345 }
346
347 void
349 {
350 std::unique_lock lock(cacheMutex);
351 nodeInfoCache.clear();
352 sceneNodesCache.clear();
353 }
354
355 std::string
357 {
358 return "GraphNodePoseResolver";
359 }
360} // namespace memoryx
361
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
#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