CartesianPositionControlIK.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2014-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 RobotSkillTemplates::MotionControlGroup
19 * @author Peter Kaiser ( peter dot kaiser at kit dot edu )
20 * @date 2014
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
26
27#include <VirtualRobot/IK/ConstrainedOptimizationIK.h>
28#include <VirtualRobot/IK/GenericIKSolver.h>
29#include <VirtualRobot/IK/constraints/OrientationConstraint.h>
30#include <VirtualRobot/IK/constraints/PositionConstraint.h>
31#include <VirtualRobot/LinkedCoordinate.h>
32#include <VirtualRobot/MathTools.h>
33#include <VirtualRobot/RobotNodeSet.h> // IWYU pragma: keep
34#include <VirtualRobot/XML/RobotIO.h>
35
37
41
43
44using namespace armarx;
45using namespace MotionControlGroup;
46
47// DO NOT EDIT NEXT LINE
48CartesianPositionControlIK::SubClassRegistry
49 CartesianPositionControlIK::Registry(CartesianPositionControlIK::GetName(),
51
57
58void
60{
61 // Create and install timeout condition
62 if (in.getTimeout() > 0)
63 {
64 setTimeoutEvent(in.getTimeout(), createEventTimeout());
65 }
66}
67
68void
70{
72 getContext<MotionControlGroupStatechartContext>();
73
74 std::string kinChainName = in.getKinematicChainName();
75 float positionTolerance = in.getTcpPositionTolerance();
76 float orientationTolerance = in.getTcpOrientationTolerance();
77
78
79 VirtualRobot::RobotPtr robot = context->getLocalRobot() /*->clone("Armar3")*/;
81 context->getRobotStateComponent()->getSynchronizedRobot());
82
83 // std::string robotfilepath = context->getRobotStateComponent()->getRobotFilename();
84 // if (!ArmarXDataPath::getAbsolutePath(robotfilepath, robotfilepath))
85 // {
86 // auto packages = context->getRobotStateComponent()->getArmarXPackages();
87 // for (auto & p : packages)
88 // {
89 // CMakePackageFinder finder(p);
90 // ArmarXDataPath::addDataPaths(finder.getDataDir());
91 // }
92 // if (!ArmarXDataPath::getAbsolutePath(robotfilepath, robotfilepath))
93 // {
94 // ARMARX_WARNING << "Could not get absolute robot model filepath for relative path : " << robotfilepath << " - using network clone";
95 // robotfilepath = "";
96 // }
97 // }
98 VirtualRobot::RobotPtr localrobot = robot; //VirtualRobot::RobotIO::loadRobot(robotfilepath);
99 // RemoteRobot::synchronizeLocalClone(localrobot, context->getRobotStateComponent()->getSynchronizedRobot());
100
101 if (!robot)
102 {
103 ARMARX_WARNING << "Could not create robot" << flush;
104 emitFailure();
105 }
106
107 if (!robot->hasRobotNodeSet(kinChainName))
108 {
109 ARMARX_WARNING << "Kinematic Chain '" << kinChainName << "' not available" << flush;
110 emitFailure();
111 }
112
113 auto nodeSet = localrobot->getRobotNodeSet(kinChainName);
114
115 FramedPosePtr target(new FramedPose());
116 VirtualRobot::IKSolver::CartesianSelection ikType = VirtualRobot::IKSolver::All;
117 if (isInputParameterSet("TcpTargetPosition") && isInputParameterSet("TcpTargetOrientation"))
118 {
119 ikType = VirtualRobot::IKSolver::All;
120
121 FramedPositionPtr targetPosition = in.getTcpTargetPosition();
122 FramedOrientationPtr targetOrientation = in.getTcpTargetOrientation();
123 ARMARX_INFO << "Target position (Frame = " << targetPosition->getFrame()
124 << "): " << targetPosition->toEigen();
125 ARMARX_INFO << "Target orientation (Frame = " << targetOrientation->getFrame()
126 << "): " << targetOrientation->toEigen();
127 Eigen::Vector3f rpy;
128 Eigen::Matrix4f mat = Eigen::Matrix4f::Identity();
129 mat.block<3, 3>(0, 0) = targetOrientation->toEigen();
130 VirtualRobot::MathTools::eigen4f2rpy(mat, rpy);
131 ARMARX_INFO << "rpy in same frame: " << rpy;
132
133 targetPosition->changeToGlobal(robot);
134 targetOrientation->changeToGlobal(robot);
135
136 target = new FramedPose(
137 targetOrientation->toEigen(), targetPosition->toEigen(), armarx::GlobalFrame, "");
138 }
139 else if (isInputParameterSet("TcpTargetPosition"))
140 {
141 ikType = VirtualRobot::IKSolver::Position;
142
143 FramedPositionPtr targetPosition = in.getTcpTargetPosition();
144
145 targetPosition->changeToGlobal(robot);
146
147 ARMARX_INFO << "Target position (Frame = " << targetPosition->getFrame() << ": "
148 << targetPosition->toEigen();
149
150 target = new FramedPose(
151 Eigen::Matrix3f::Identity(), targetPosition->toEigen(), armarx::GlobalFrame, "");
152 }
153 else if (isInputParameterSet("TcpTargetOrientation"))
154 {
155 ikType = VirtualRobot::IKSolver::Orientation;
156
157 FramedOrientationPtr targetOrientation = in.getTcpTargetOrientation();
158
159 targetOrientation->changeToGlobal(robot);
160
161 ARMARX_INFO << "Target orientation (Frame = " << targetOrientation->getFrame() << ": "
162 << targetOrientation->toEigen();
163
164 target = new FramedPose(
165 targetOrientation->toEigen(), Eigen::Vector3f(0, 0, 0), armarx::GlobalFrame, "");
166 }
167 ARMARX_VERBOSE << VAROUT(*target);
168 ARMARX_VERBOSE << VAROUT(robot->getGlobalPose());
169 context->getDebugDrawerTopicProxy()->setPoseDebugLayerVisu("RobotPose",
170 new Pose(robot->getGlobalPose()));
171 // Eigen::Matrix4f globalTargetPose = target->toRootEigen(robot);
172 // robot->setGlobalPose(Eigen::Matrix4f::Identity());
173
174 Eigen::Matrix4f globalTargetPose = target->toEigen();
175 VirtualRobot::ConstraintPtr positionConstraint(
176 new VirtualRobot::PositionConstraint(localrobot,
177 nodeSet,
178 nodeSet->getTCP(),
179 globalTargetPose.block<3, 1>(0, 3),
180 ikType,
181 positionTolerance));
182 positionConstraint->setOptimizationFunctionFactor(1);
183
184 VirtualRobot::ConstraintPtr orientationConstraint(
185 new VirtualRobot::OrientationConstraint(localrobot,
186 nodeSet,
187 nodeSet->getTCP(),
188 globalTargetPose.block<3, 3>(0, 0),
189 ikType,
190 orientationTolerance));
191 orientationConstraint->setOptimizationFunctionFactor(1000);
192
193 // VirtualRobot::GenericIKSolver ikSolver(robot->getRobotNodeSet(kinChainName), VirtualRobot::JacobiProvider::eSVDDamped);
194 // ikSolver.setMaximumError(positionTolerance, orientationTolerance);
195 // ikSolver.setupJacobian(jacobianStepSize, jacobianMaxLoops);
196 // ikSolver.solve(globalTargetPose, ikType, ikMaxLoops);
197 // Instantiate solver and generate IK solution
198 IceUtil::Time start = IceUtil::Time::now();
199 VirtualRobot::ConstrainedOptimizationIK ikSolver(localrobot, nodeSet);
200 ARMARX_INFO << "IK " << VAROUT(positionTolerance) << VAROUT(orientationTolerance);
201 ikSolver.addConstraint(positionConstraint);
202 ikSolver.addConstraint(orientationConstraint);
203 ikSolver.initialize();
204
205 bool ikSuccess = ikSolver.solve();
206 ARMARX_INFO << "Solving IK took: " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
207 << " ms " << VAROUT(ikSuccess);
208
209 float remainingErrorPos =
210 (globalTargetPose.block<3, 1>(0, 3) - nodeSet->getTCP()->getGlobalPose().block<3, 1>(0, 3))
211 .norm();
212 Eigen::Matrix4f deltaMat = globalTargetPose * nodeSet->getTCP()->getGlobalPose().inverse();
213 Eigen::AngleAxisf aa(deltaMat.block<3, 3>(0, 0));
214 float remaingErrorOri = fabs(aa.angle());
215 // ikSuccess = (remainingErrorPos < positionTolerance && remaingErrorOri < orientationTolerance && ikType == VirtualRobot::IKSolver::All)
216 // || (ikType == VirtualRobot::IKSolver::Position && remainingErrorPos < positionTolerance)
217 // || (ikType == VirtualRobot::IKSolver::Orientation && remaingErrorOri < orientationTolerance);
218 ARMARX_DEBUG << VAROUT(globalTargetPose) << "Delta: " << deltaMat;
219 if (ikSuccess)
220 {
221 ARMARX_INFO << "Found IK solution: remaining position error " << remainingErrorPos
222 << " mm, orientation error: " << remaingErrorOri << " rad ("
223 << (remaingErrorOri * 180 / M_PI) << " deg)";
224 }
225 else
226 {
227 ARMARX_WARNING << "IK Solver failed: remaining position error " << remainingErrorPos
228 << " mm, orientation error: " << remaingErrorOri << " rad ("
229 << (remaingErrorOri * 180 / M_PI) << " deg)";
230 ARMARX_DEBUG << "Reached Pose: " << nodeSet->getTCP()->getGlobalPose();
231 context->getDebugDrawerTopicProxy()->setPoseDebugLayerVisu(
232 "UnreachedIKPose", new Pose(target->toGlobalEigen(robot)));
233 robot->setGlobalPose(robot->getGlobalPose());
234 context->getDebugDrawerTopicProxy()->setPoseDebugLayerVisu(
235 "BestFoundIKPose", new Pose(nodeSet->getTCP()->getGlobalPose()));
236 if (in.getAlwaysExecuteBestFoundIkSolution())
237 {
239 << "Using failed IK anyway due to AlwaysExecuteBestFoundIkSolution == true";
240 }
241 }
242
243 if (!ikSuccess && !in.getAlwaysExecuteBestFoundIkSolution())
244 {
245 emitFailure();
246 }
247 else
248 {
249 // Convert solution to state output format
250 std::map<std::string, float> jointTargetValues;
251 std::map<std::string, float> jointVelocities;
252
253 VirtualRobot::RobotNodeSetPtr kinematicChain = localrobot->getRobotNodeSet(kinChainName);
254
255 for (unsigned int i = 0; i < kinematicChain->getSize(); i++)
256 {
257 VirtualRobot::RobotNodePtr node = kinematicChain->getNode(i);
258
259 jointTargetValues[node->getName()] = node->getJointValue();
260 jointVelocities[node->getName()] = 1.0f;
261 }
262
263 out.setJointTargetValues(jointTargetValues);
264 out.setJointVelocities(jointVelocities);
265 out.setJointTargetTolerance(0.1f);
266
267 emitSuccess();
268 }
269}
270
271void
275
276void
280
281// DO NOT EDIT NEXT FUNCTION
#define M_PI
Definition MathTools.h:17
#define VAROUT(x)
The FramedPose class.
Definition FramedPose.h:281
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
custom implementation of the StatechartContext for a statechart
The Pose class.
Definition Pose.h:243
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
Class for legacy to stay compatible with old statecharts.
Definition XMLState.h:147
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
IceInternal::Handle< FramedOrientation > FramedOrientationPtr
Definition FramedPose.h:207
const LogSender::manipulator flush
Definition LogSender.h:251
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition XMLState.h:64
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272