NaturalDiffIK.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),
5 * Karlsruhe Institute of Technology (KIT), all rights reserved.
6 *
7 * ArmarX is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * ArmarX is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author SecondHands Demo (shdemo at armar6)
20 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
24
25#include "NaturalDiffIK.h"
26
27#include <cfloat>
28
29#include <VirtualRobot/IK/DifferentialIK.h>
30#include <VirtualRobot/Nodes/RobotNode.h>
31#include <VirtualRobot/RobotNodeSet.h>
32
35
36namespace armarx
37{
38 Eigen::VectorXf
39 NaturalDiffIK::LimitInfNormTo(Eigen::VectorXf vec, float maxValue)
40 {
41 float infNorm = vec.lpNorm<Eigen::Infinity>();
42 if (infNorm > maxValue)
43 {
44 vec = vec / infNorm * maxValue;
45 }
46 return vec;
47 }
48
50 NaturalDiffIK::CalculateDiffIK(const Eigen::Matrix4f& targetPose,
51 const Eigen::Vector3f& elbowTarget,
52 VirtualRobot::RobotNodeSetPtr rns,
53 VirtualRobot::RobotNodePtr tcp,
54 VirtualRobot::RobotNodePtr elbow,
55 Mode setOri,
56 Parameters params)
57 {
58 VirtualRobot::IKSolver::CartesianSelection mode = ModeToCartesianSelection(setOri);
59
62 CartesianVelocityController vcElb(rns, elbow);
63 CartesianPositionController pcElb(elbow);
64
65 if (params.resetRnsValues)
66 {
67 for (VirtualRobot::RobotNodePtr rn : rns->getAllRobotNodes())
68 {
69 if (rn->isLimitless())
70 {
71 rn->setJointValue(0);
72 }
73 else
74 {
75 rn->setJointValue((rn->getJointLimitHi() + rn->getJointLimitLo()) / 2);
76 }
77 }
78 }
79
80
81 //std::stringstream ss;
82
83 //ARMARX_IMPORTANT << "start";
84
85 int posMet = 0;
86 int oriMet = 0;
87
88 std::vector<IKStep> ikSteps;
89 Eigen::VectorXf currentJointValues = rns->getJointValuesEigen();
90 for (size_t i = 0; i <= params.stepsInitial + params.stepsFineTune; i++)
91 {
92 //ss << pdTcp.norm() << " ## " << odTcp.norm() << " ## " << pdElb.norm() << std::endl;
93
94 int posLen = mode & VirtualRobot::IKSolver::Position ? 3 : 0;
95 int oriLen = mode & VirtualRobot::IKSolver::Orientation ? 3 : 0;
96 Eigen::Vector3f pdTcp =
97 posLen ? pcTcp.getPositionDiff(targetPose) : Eigen::Vector3f::Zero();
98 Eigen::Vector3f odTcp =
99 oriLen ? pcTcp.getOrientationDiff(targetPose) : Eigen::Vector3f::Zero();
100 Eigen::VectorXf cartesianVel(posLen + oriLen);
101 if (posLen)
102 {
103 cartesianVel.block<3, 1>(0, 0) = pdTcp;
104 }
105 if (oriLen)
106 {
107 cartesianVel.block<3, 1>(posLen, 0) = odTcp;
108 }
109
110 Eigen::Vector3f pdElb = pcElb.getPositionDiffVec3(elbowTarget);
111 Eigen::VectorXf cartesianVelElb(3);
112 cartesianVelElb.block<3, 1>(0, 0) = pdElb;
113 Eigen::VectorXf jvElb =
114 params.elbowKp * vcElb.calculate(cartesianVelElb, VirtualRobot::IKSolver::Position);
115 Eigen::VectorXf jvLA =
117 Eigen::VectorXf jv = vcTcp.calculate(cartesianVel, jvElb + jvLA, mode);
118
119
120 float stepLength =
121 i < params.stepsInitial ? params.ikStepLengthInitial : params.ikStepLengthFineTune;
122 Eigen::VectorXf jvClamped = jv * stepLength;
123 jvClamped = LimitInfNormTo(jvClamped, params.maxJointAngleStep);
124
125 if (params.returnIKSteps)
126 {
127 IKStep s;
128 s.pdTcp = pdTcp;
129 s.odTcp = odTcp;
130 s.pdElb = pdElb;
131 s.tcpPose = tcp->getPoseInRootFrame();
132 s.elbPose = elbow->getPoseInRootFrame();
133 s.cartesianVel = cartesianVel;
134 s.cartesianVelElb = cartesianVelElb;
135 s.jvElb = jvElb;
136 s.jvLA = jvLA;
137 s.jv = jv;
138 s.jvClamped = jvClamped;
139 ikSteps.emplace_back(s);
140 }
141
142
143 Eigen::VectorXf newJointValues = currentJointValues + jvClamped;
144 rns->setJointValues(newJointValues);
145 currentJointValues = newJointValues;
146
147 if (pdTcp.norm() > params.maxPosError)
148 {
149 posMet = 0;
150 }
151 else
152 {
153 posMet++;
154 }
155 if (odTcp.norm() > params.maxOriError)
156 {
157 oriMet = 0;
158 }
159 else
160 {
161 oriMet++;
162 }
163
164 // terminate early, if reached for at least 3 iterations
165 if (posMet > 2 && oriMet > 2)
166 {
167 break;
168 }
169 }
170
171 //ARMARX_IMPORTANT << ss.str();
172
173 Result result;
174 result.ikSteps = ikSteps;
175 result.jointValues = rns->getJointValuesEigen();
176 result.posDiff = pcTcp.getPositionDiff(targetPose);
177 result.oriDiff = pcTcp.getOrientationDiff(targetPose);
178 result.posError = pcTcp.getPositionError(targetPose);
179 result.oriError = pcTcp.getOrientationError(targetPose);
180 result.reached = result.posError < params.maxPosError &&
181 (setOri == Mode::Position || result.oriError < params.maxOriError);
182 result.posDiffElbow = pcElb.getPositionDiffVec3(elbowTarget);
183 result.posErrorElbow = result.posDiffElbow.norm();
184
185 result.jointLimitMargins = Eigen::VectorXf::Zero(rns->getSize());
186 result.minimumJointLimitMargin = FLT_MAX;
187 for (size_t i = 0; i < rns->getSize(); i++)
188 {
189 VirtualRobot::RobotNodePtr rn = rns->getNode(i);
190 if (rn->isLimitless())
191 {
192 result.jointLimitMargins(i) = M_PI;
193 }
194 else
195 {
196 result.jointLimitMargins(i) = std::min(rn->getJointValue() - rn->getJointLimitLo(),
197 rn->getJointLimitHi() - rn->getJointValue());
199 std::min(result.minimumJointLimitMargin, result.jointLimitMargins(i));
200 }
201 }
202
203 return result;
204 }
205
206 VirtualRobot::IKSolver::CartesianSelection
208 {
209 return mode == Mode::All ? VirtualRobot::IKSolver::All : VirtualRobot::IKSolver::Position;
210 }
211
212
213} // namespace armarx
#define M_PI
Definition MathTools.h:17
Eigen::Vector3f getPositionDiffVec3(const Eigen::Vector3f &targetPosition) const
float getPositionError(const Eigen::Matrix4f &targetPose) const
float getOrientationError(const Eigen::Matrix4f &targetPose) const
Eigen::Vector3f getOrientationDiff(const Eigen::Matrix4f &targetPose) const
Eigen::Vector3f getPositionDiff(const Eigen::Matrix4f &targetPose) const
Eigen::VectorXf calculate(const Eigen::VectorXf &cartesianVel, VirtualRobot::IKSolver::CartesianSelection mode)
static Result CalculateDiffIK(const Eigen::Matrix4f &targetPose, const Eigen::Vector3f &elbowTarget, VirtualRobot::RobotNodeSetPtr rns, VirtualRobot::RobotNodePtr tcp, VirtualRobot::RobotNodePtr elbow, Mode setOri, Parameters params=Parameters())
static VirtualRobot::IKSolver::CartesianSelection ModeToCartesianSelection(Mode mode)
static Eigen::VectorXf LimitInfNormTo(Eigen::VectorXf vec, float maxValue)
This file offers overloads of toIce() and fromIce() functions for STL container types.
Eigen::VectorXf jointLimitMargins
std::vector< IKStep > ikSteps