RobotIK.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2015-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 RobotComponents::ArmarXObjects::RobotIK
19 * @author Joshua Haustein ( joshua dot haustein at gmail dot com )
20 * @date 2015
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#pragma once
26
27#include <mutex>
28
29#include <VirtualRobot/IK/GenericIKSolver.h>
30
34
35#include <RobotAPI/interface/core/RobotState.h>
36#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
38
39#include <RobotComponents/interface/components/RobotIK.h>
40
41namespace armarx
42{
43 /**
44 * \class RobotIKPropertyDefinition
45 * \brief
46 */
48 {
49 public:
51 {
53 "RobotFileName", "Filename of VirtualRobot robot model (e.g. robot_model.xml)");
54 //Define optional properties
56 "RobotStateComponentName",
57 "RobotStateComponent",
58 "Name of the robot state component that should be used");
59 defineOptionalProperty<std::string>("ReachabilitySpacesFolder",
60 "Path to a folder containing reachability spaces");
62 "NumIKTrials", 10, "Number of trials to find an ik solution");
64 "InitialReachabilitySpaces",
65 "",
66 "Reachability spaces to load initially (semi-colon separated)");
67 }
68 };
69
70 /**
71 * \defgroup Component-RobotIK RobotIK
72 * \ingroup RobotComponents-Components
73 * \brief Provides IK solving methods from VirtualRobot (see [Simox](http://simox.sourceforge.net/)).
74 *
75 * RobotIK provides a set of functions that allow computing IKs for any kinematic chain
76 * in a robot. This component requires the following properties:
77 * - RobotFileName: The VirtualRobot robot model to be used.
78 * - RobotStateComponentName: The name of a robot state component.
79 *
80 * \image html Armar3_IK_small.png "An exemplary IK task and its solution."
81 *
82 * Furthermore, there are the following optional properties:
83 * - ReachabilitySpacesFolder: A Path to a folder containing reachability spaces.
84 * - NumIKTrials: The number of trials the underlying ik solver tries to find a solution before giving up (default: 10).
85 *
86 * The robot model is required to solve the IK. Some of the provided functionalities require the current robot state,
87 * which is retrieved from the robot state component specified in the properties. These functions will only work properly,
88 * if the robot model used by the robot state component is identical to the robot model of this component.
89 *
90 * The functionalities include:
91 * - computation of an IK solution for a kinematic chain given a goal TCP pose.
92 * - computation of an IK solution for a set of robot joints such that
93 * the projection of the center of mass to the support surface lies within a goal region.
94 * - computation of a joint value gradient to minimize the workspace error for several tasks simultaneously.
95 * - creation and query of reachability spaces for kinematic chains.
96 *
97 * A reachability space for a kinematic chain allows a fast check whether
98 * a TCP pose is reachable. Creating a reachability space, however, is a computational intensive process
99 * that should be done offline. You may create a reachability space by calling the respective function
100 * or by specifying a path to a folder, ReachabilitySpacesFolder, that contains a set of reachability spaces.
101 * If ReachabilitySpacesFolder is specified, each file in the folder is attempted to be loaded as reachability space
102 * during initialization.
103 *
104 * While this implementation allows parallel access to its interface functions,
105 * it is not optimized towards maximizing parallelism.
106 * If you need to access this component from a large number of threads/processes
107 * and you care about performance, you should consider creating multiple instances
108 * of this component or using local instances of the IK solver from Simox instead.
109 *
110 * Furthermore, at the beginning of an operation this component synchronizes its
111 * internal robot state with that provided by the robot state component.
112 * This can lead to invalid IK solutions if the robot state changes while computation is still in progress.
113 * For example, imagine you compute an IK solution just
114 * for the forearm and the wrist given a global eef pose. If during the computation the configuration
115 * of the elbow changes, the computed ik solution will no longer achieve the desired eef pose.
116 *
117 * Also see [Simox-Tutorial] (http://sourceforge.net/p/simox/wiki/VirtualRobot/) for more information
118 * of how to use Simox for IK solving.
119 */
120
121 /**
122 * @ingroup Component-RobotIK
123 * @brief Refer to \ref Component-RobotIK
124 */
126 virtual public Component,
127 virtual public RobotIKInterface
128 {
129 public:
130 /**
131 * \return the robot xml filename as specified in the configuration
132 */
133 virtual std::string getRobotFilename(const Ice::Current&) const;
134
135 /**
136 * Create an instance of RobotIKPropertyDefinitions.
137 */
139
140 std::string
141 getDefaultName() const override
142 {
143 return "RobotIK";
144 }
145
146 /**
147 * @brief Computes a single IK solution for the given robot node set and desired TCP pose.
148 * @details The TCP pose can be defined in any frame and is converted internally to a global pose
149 * according to the current robot state. The CartesianSelection
150 * parameter defines which part of the target pose should be reached.
151 *
152 * @param robotNodeSetName The name of a robot node set (robot node set) that is either stored
153 * within the robot model or has been defined via \ref defineRobotNodeSet.
154 * @param tcpPose The framed target pose for the TCP.
155 * @param cs Specifies which part of the pose needs to be reached by the IK, e.g. the position only,
156 * the orientation only or all.
157 * @return A map that maps each joint name to its value in the found IK solution.
158 */
159 NameValueMap computeIKFramedPose(const std::string& robotNodeSetName,
160 const FramedPoseBasePtr& tcpPose,
161 armarx::CartesianSelection cs,
162 const Ice::Current& = Ice::emptyCurrent) override;
163
164 /**
165 * @brief Computes a single IK solution for the given robot node set and desired global TCP pose.
166 * @details The TCP pose is assumed to be in the global frame. The CartesianSelection
167 * parameter defines which part of the target pose should be reached.
168 *
169 * @param robotNodeSetName The name of a robot node set (robot node set) that is either stored
170 * within the robot model or has been defined via \ref defineRobotNodeSet.
171 * @param tcpPose The global target pose for the TCP.
172 * @param cs Specifies which part of the pose needs to be reached by the IK, e.g. the position only,
173 * the orientation only or all.
174 * @return A map that maps each joint name to its value in the found IK solution.
175 */
176 NameValueMap computeIKGlobalPose(const std::string& robotNodeSetName,
177 const PoseBasePtr& tcpPose,
178 armarx::CartesianSelection cs,
179 const Ice::Current& = Ice::emptyCurrent) override;
180
181 /**
182 * @brief Computes a single IK solution, error and reachability for the given robot node set and desired global TCP pose.
183 * @details The TCP pose is assumed to be in the global frame. The CartesianSelection
184 * parameter defines which part of the target pose should be reached.
185 *
186 * @param robotNodeSetName The name of a robot node set (robot node set) that is either stored
187 * within the robot model or has been defined via \ref defineRobotNodeSet.
188 * @param tcpPose The global target pose for the TCP.
189 * @param cs Specifies which part of the pose needs to be reached by the IK, e.g. the position only,
190 * the orientation only or all.
191 * @return A map that maps each joint name to its value in the found IK solution, the reachability and computational error.
192 */
193 ExtendedIKResult
194 computeExtendedIKGlobalPose(const std::string& robotNodeSetName,
195 const PoseBasePtr& tcpPose,
196 armarx::CartesianSelection cs,
197 const Ice::Current& = Ice::emptyCurrent) override;
198
199 /**
200 * @brief Computes an IK solution for the given robot joints such that the center of mass lies above the
201 * given point.
202 * @details
203 *
204 * @param robotNodeSetJoints Name of the robot node set that contains the joints you wish to compute the IK for.
205 * @param comIK A center of mass description. Note that the priority field is relevant for this function as there
206 * is only a single CoM of descriptor.
207 *
208 * @return The ik-solution. Returns an empty vector if there is no solution.
209 */
210 NameValueMap computeCoMIK(const std::string& robotNodeSetJoints,
211 const CoMIKDescriptor& desc,
212 const Ice::Current& = Ice::emptyCurrent) override;
213
214 /**
215 * @brief Computes a configuration gradient in order to solve several tasks/constraints simultaneously.
216 * @details This function allows you to use the HierarchicalIK solver provided by Simox.
217 * It computes a configuration gradient for the given robot node set that minimizes the workspace errors
218 * for multiple tasks simultaneously. You can specify IK tasks, a center of mass task and a joint limit avoidance task.
219 * For details for the different type of tasks, see the parameter description. You must define a priority for each task.
220 * The task with maximal priority is the first task to be solved. Each subsequent task is then solved
221 * within the null space of the previous task. <b> Note that this function returns a gradient and NOT
222 * an absolute IK solution. The gradient is computed on the current configuration of the robot. <\b>.
223 * The gradient is computed from the current robot configuration.
224 *
225 * See @url http://simox.sourceforge.net/documentation/class_virtual_robot_1_1_hierarchical_i_k.html
226 * and @url http://sourceforge.net/p/simox/wiki/VirtualRobot/#hierarchical-ik-solving for more information.
227 *
228 * @param robotNodeSet The robot node set (e.g. kinematic tree) you wish to compute the gradient for.
229 * @param diffIKs A list of IK tasks. Each IK task specifies a TCP and a desired pose for this TCP.
230 * @param comIK A center of mass tasks. Defines where the center should be and its priority. Is only used if the
231 CoM-task is enabled.
232 * @param stepSize
233 * @param avoidJointLimits Set whether or not to avoid joint limits.
234 * @param enableCenterOfMass Set whether or not to adjust the center of mass.
235 * @return A configuration gradient...
236 */
237 NameValueMap computeHierarchicalDeltaIK(const std::string& robotNodeSet,
238 const IKTasks& iktasks,
239 const CoMIKDescriptor& comIK,
240 float stepSize,
241 bool avoidJointLimits,
242 bool enableCenterOfMass,
243 const Ice::Current& = Ice::emptyCurrent) override;
244
245 /**
246 * @brief Creates a new reachability space for the given robot node set.
247 * @details If there is no reachability space for the given robot node set yet, a new one is created. This may take
248 * some time. The function returns true iff a reachability space for the given robot node set exists after
249 * execution of this function.
250 *
251 * @param chainName The name of a defined robot node set. This can be either a robot node set that is defined in the
252 * robot model or a robot node set that has been manually defined calling \ref defineRobotNodeSet.
253 * @param coordinateSystem The name of the robot node in whose coordinate system the reachability space shall be defined
254 * in. If you wish to choose the global coordinate system, pass an empty string.
255 * Note, however, that any reachability space defined in the
256 * global coordinate system gets invalidated once the robot moves.
257 * @param stepTranslation The extend of a voxel dimension in translational dimensions (x,y,z) [mm]
258 * @param stepRotation The extend of a voxel dimension in rotational dimensions (roll,pitch,yaw) [rad]
259 * @param minBounds The minimum workspace poses (x,y,z,ro,pi,ya) given in the base node's coordinate system [mm and rad]
260 * @param maxBounds The maximum workspace poses (x,y,z,ro,pi,ya) given in base node's coordinate system [mm and rad]
261 * @param numSamples The number of tcp samples to take to create the reachability space (e.g 1000000)
262 * @return True iff the a reachability space for the given robot node set is available after execution of this function.
263 * False in case of a failure, e.g. there is no chain with the given name.
264 */
265 bool createReachabilitySpace(const std::string& chainName,
266 const std::string& coordinateSystem,
267 float stepTranslation,
268 float stepRotation,
269 const WorkspaceBounds& minBounds,
270 const WorkspaceBounds& maxBounds,
271 int numSamples,
272 const Ice::Current& = Ice::emptyCurrent) override;
273
274 /**
275 * @brief Defines a new robot node set.
276 * @details Define a new robot node set with the given name that consists out of the given list of nodes with given
277 * TCP and root frame. Iff the chain is successfully added or already exists, <it>true</it> is returned.
278 * @param name The name of the robot node set.
279 * @param nodes The list of robot nodes that make up the robot node set.
280 * @param tcpName The name of the TCP node.
281 * @param rootNode The name of the kinematic root.
282 *
283 * @return True, iff chain was added or already exists. False, iff a different chain with similar name already exists.
284 */
285 bool defineRobotNodeSet(const std::string& name,
286 const NodeNameList& nodes,
287 const std::string& tcpName,
288 const std::string& rootNode,
289 const Ice::Current& = Ice::emptyCurrent) override;
290
291 /**
292 * @brief Returns whether this component has a reachability space for the given robot node set.
293 * @details True if there is a reachability space available, else false.
294 *
295 * @param chainName Name of the robot node set.
296 * @return True if there is a reachability space available, else false.
297 */
298 bool hasReachabilitySpace(const std::string& chainName,
299 const Ice::Current& = Ice::emptyCurrent) const override;
300
301 /**
302 * @brief Returns whether a given framed pose is currently reachable by the TCP of the given robot node set.
303 * @details To determine whether a pose is reachable a reachability space for the given robot node set is
304 * required. If no such space exists, the function returns <it>false<\it>.
305 * Call \ref createReachabilitySpace first to ensure there is such a space.
306 *
307 * @param chainName A name of a robot node set either defined in the robot model or previously defined via
308 * \ref defineRobotNodeSet.
309 * @param framedPose A framed pose to check for reachability. The pose is transformed into a global pose using the
310 * current robot state.
311 *
312 * @return True, if the pose is reachable by the TCP of the given chain. False, if it is not reachable or
313 * there is no reachability space for the given chain available.
314 */
315 bool isFramedPoseReachable(const std::string& chainName,
316 const FramedPoseBasePtr& tcpPose,
317 const Ice::Current& = Ice::emptyCurrent) const override;
318
319 /**
320 * @brief Returns whether a given global pose is currently reachable by the TCP of the given robot node set.
321 * @details To determine whether a pose is reachable a reachability space for the given robot node set is
322 * required. If no such space exists, the function returns <it>false<\it>.
323 * Call \ref createReachabilitySpace first to ensure there is such a space.
324 *
325 * @param chainName A name of a robot node set either defined in the robot model or previously defined via
326 * \ref defineRobotNodeSet.
327 * @param pose A global pose to check for reachability.
328 *
329 * @return True, if the pose is reachable by the TCP of the given chain. False, if it is not reachable or
330 * there is no reachability space for the given chain available.
331 */
332 bool isPoseReachable(const std::string& chainName,
333 const PoseBasePtr& tcpPose,
334 const Ice::Current& = Ice::emptyCurrent) const override;
335
336 /**
337 * @brief Loads the reachability space from the given file.
338 * @details If loading the reachability space succeeds, the reachability space is ready to be used after this function
339 * terminates. A reachability space can only be loaded if there is no reachability space for the respective
340 * robot node set yet.
341 *
342 * @param filename Binary file containing a reachability space. Ensure that the path is valid and accessible from
343 * where this component is running.
344 * @return True iff loading the reachability space was successful.
345 */
346 bool loadReachabilitySpace(const std::string& filename,
347 const Ice::Current& = Ice::emptyCurrent) override;
348
349 /**
350 * @brief Saves a previously created reachability space of the given robot node set.
351 * @details A reachability space for a robot node set can only be saved, if actually is one.
352 * You can check whether a reachability space is available by calling \ref hasReachabilitySpace(robotNodeSet).
353 *
354 * @param robotNodeSet The robot node set for which you wish to save the reachability space.
355 * @param filename The filename if the file(must be an accessible path for this component) you wish to save the space in.
356 * @return True iff saving was successful.
357 */
358 bool saveReachabilitySpace(const std::string& robotNodeSet,
359 const std::string& filename,
360 const Ice::Current& = Ice::emptyCurrent) const override;
361
362
363 protected:
364 /**
365 * Load and create a VirtualRobot::Robot instance from the RobotFileName
366 * property.
367 */
368 void onInitComponent() override;
369 void onConnectComponent() override;
370 void onDisconnectComponent() override;
371
372 private:
373 bool solveIK(const Eigen::Matrix4f& tcpPose,
374 armarx::CartesianSelection cs,
375 VirtualRobot::RobotNodeSetPtr nodeSet);
376 void computeIK(const std::string& robotNodeSetName,
377 const Eigen::Matrix4f& tcpPose,
378 armarx::CartesianSelection cs,
379 NameValueMap& iksolution);
380
381 void computeIK(VirtualRobot::RobotNodeSetPtr nodeSet,
382 const Eigen::Matrix4f& tcpPose,
383 armarx::CartesianSelection cs,
384 NameValueMap& iksolution);
385
386 void computeIK(const std::string& robotNodeSetName,
387 const Eigen::Matrix4f& tcpPose,
388 armarx::CartesianSelection cs,
389 ExtendedIKResult& iksolution);
390
391 void computeIK(VirtualRobot::RobotNodeSetPtr nodeSet,
392 const Eigen::Matrix4f& tcpPose,
393 armarx::CartesianSelection cs,
394 ExtendedIKResult& iksolution);
395
396 Eigen::Matrix4f toGlobalPose(const FramedPoseBasePtr& tcpPose) const;
397 Eigen::Matrix4f toReachabilityMapFrame(const FramedPoseBasePtr& tcpPose,
398 const std::string& chainName) const;
399
400 bool isReachable(const std::string& setName, const Eigen::Matrix4f& tcpPose) const;
401
402 VirtualRobot::IKSolver::CartesianSelection
403 convertCartesianSelection(armarx::CartesianSelection cs) const;
404
405 VirtualRobot::JacobiProvider::InverseJacobiMethod
406 convertInverseJacobiMethod(armarx::InverseJacobiMethod aenum) const;
407
408 void synchRobot() const;
409
410 // Lock this mutex if you plan to modify the robot model
411 // Exception: When adding node sets we don't need to.
412 // Invariant: We never delete node sets nor nodes!
413 mutable std::recursive_mutex _modifyRobotModelMutex;
414 // Lock this mutex if you are adding a node set, to ensure we do not add
415 // a similar node set at the same time.
416 mutable std::recursive_mutex _editRobotNodeSetsMutex;
417 // Lock this mutex if you are reading or editing the reachability cache.
418 mutable std::recursive_mutex _accessReachabilityCacheMutex;
419 // Needs to be locked when computing IKs! Internally thread safe though.
420 VirtualRobot::RobotPtr _robotModel;
421 std::string _robotFile;
422 RobotStateComponentInterfacePrx _robotStateComponentPrx;
423 SharedRobotInterfacePrx _synchronizedRobot;
424 DebugDrawerInterfacePrx debugDrawer;
425
426 // Reachability cache: not thread safe, always lock!
427 using ReachabilityCacheType =
428 std::map<std::string, VirtualRobot::WorkspaceRepresentationPtr>;
429 ReachabilityCacheType _reachabilities;
430 int _numIKTrials;
431 };
432
433} // namespace armarx
#define ARMARXCOMPONENT_IMPORT_EXPORT
ComponentPropertyDefinitions(std::string prefix, bool hasObjectNameParameter=true)
Definition Component.cpp:46
Component()
Protected default constructor. Used for virtual inheritance. Use createManagedIceObject() instead.
Definition Component.cpp:66
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
PropertyDefinition< PropertyType > & defineRequiredProperty(const std::string &name, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
RobotIKPropertyDefinitions(std::string prefix)
Definition RobotIK.h:50
Refer to RobotIK.
Definition RobotIK.h:128
virtual std::string getRobotFilename(const Ice::Current &) const
Definition RobotIK.cpp:449
PropertyDefinitionsPtr createPropertyDefinitions() override
Create an instance of RobotIKPropertyDefinitions.
Definition RobotIK.cpp:143
std::string getDefaultName() const override
Retrieve default name of component.
Definition RobotIK.h:141
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
::IceInternal::ProxyHandle<::IceProxy::armarx::SharedRobotInterface > SharedRobotInterfacePrx
Definition FramedPose.h:59
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx