NaturalIK.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 Simon Ottenhaus (simon dot ottenhaus at kit dot edu)
20 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
24#include "NaturalIK.h"
25
26#include <SimoxUtility/math/convert/deg_to_rad.h>
27#include <SimoxUtility/math/convert/rad_to_deg.h>
28#include <VirtualRobot/Nodes/RobotNode.h>
29#include <VirtualRobot/RobotNodeSet.h>
30#include <VirtualRobot/math/Helpers.h>
31
34
35using namespace armarx;
36
37NaturalIK::NaturalIK(std::string side, Eigen::Vector3f shoulderPos, float scale) :
38 side(side), shoulderPos(shoulderPos), scale(scale)
39{
40}
41
43NaturalIK::solveSoechtingIK(const Eigen::Vector3f& targetPos, std::optional<float> minElbowHeight)
44{
45 Eigen::Vector3f vtgt = targetPos;
46
49 for (int i = 1; i < soechtingIterations; i++)
50 {
51 Eigen::Vector3f err = targetPos - fwd.wrist;
52 vtgt = vtgt + err;
54 }
55
56
57 //ARMARX_IMPORTANT << VAROUT(fwd.elbow.z()) << VAROUT(minElbowHeight.value_or(-999));
58
59 // this could be solved analytically.
60 if (minElbowHeight.has_value() && minElbowHeight.value() > fwd.elbow.z())
61 {
62 float mEH = minElbowHeight.value();
63 float lo = 0;
64 float hi = side == "Right" ? -M_PI : M_PI;
65 Eigen::Vector3f wri_n = (fwd.wrist - shoulderPos).normalized();
66 Eigen::Vector3f elb = fwd.elbow;
67 for (int i = 0; i < 20; i++)
68 {
69 float a = (lo + hi) / 2;
70 Eigen::AngleAxisf aa(a, wri_n);
71 elb = shoulderPos + aa * (fwd.elbow - shoulderPos);
72 if (elb.z() > mEH)
73 {
74 hi = a;
75 }
76 else
77 {
78 lo = a;
79 }
80 }
81 fwd.elbow = elb;
82 }
83
84 return fwd;
85}
86
88NaturalIK::calculateIK(const Eigen::Matrix4f& targetPose,
89 ArmJoints arm,
91{
92 Eigen::Vector3f targetPos = math::Helpers::Position(targetPose);
94 solveSoechtingIK(targetPos, params.minimumElbowHeight);
95 return NaturalDiffIK::CalculateDiffIK(targetPose,
96 fwd.elbow,
97 arm.rns,
98 arm.tcp,
99 arm.elbow,
101 params.diffIKparams);
102}
103
105NaturalIK::calculateIKpos(const Eigen::Vector3f& targetPos,
108{
109 Eigen::Matrix4f targetPose = math::Helpers::Pose(targetPos, Eigen::Matrix3f::Identity());
111 solveSoechtingIK(targetPos, params.minimumElbowHeight);
112 return NaturalDiffIK::CalculateDiffIK(targetPose,
113 fwd.elbow,
114 arm.rns,
115 arm.tcp,
116 arm.elbow,
118 params.diffIKparams);
119}
120
122NaturalIK::calculateIK(const Eigen::Matrix4f& targetPose,
124 NaturalDiffIK::Mode setOri,
126{
127 Eigen::Vector3f targetPos = math::Helpers::Position(targetPose);
129 solveSoechtingIK(targetPos, params.minimumElbowHeight);
130 //VirtualRobot::IKSolver::CartesianSelection mode = setOri ? VirtualRobot::IKSolver::All : VirtualRobot::IKSolver::Position;
132 targetPose, fwd.elbow, arm.rns, arm.tcp, arm.elbow, setOri, params.diffIKparams);
133}
134
135Eigen::Vector3f
137{
138 return shoulderPos;
139}
140
143{
144 target = target - shoulderPos;
145 if (side == "Right")
146 {
147 target = target / scale;
148 }
149 else if (side == "Left")
150 {
151 target = target / scale;
152 target(0) = -target(0);
153 }
154 else
155 {
156 throw LocalException("Unsupported side: ") << side << ". supported are Left|Right.";
157 }
158
159 target = target / 10; // Soechting is defined in cm
160 float x = target(0);
161 float y = target(1);
162 float z = target(2);
163
164 float R = target.norm();
165 float Chi = simox::math::rad_to_deg(std::atan2(x, y));
166 float Psi = simox::math::rad_to_deg(std::atan2(z, std::sqrt(x * x + y * y)));
167
168 //ARMARX_IMPORTANT << "target: " << target.transpose() << " " << VAROUT(R) << VAROUT(Chi) << VAROUT(Psi);
169
170 // Angles derived from accurate pointing
171 //SoechtingAngles sa;
172 //sa.SE = -6.7 + 1.09*R + 1.10*Psi;
173 //sa.EE = 47.6 + 0.33*R - 0.95*Psi;
174 //sa.EY = -11.5 + 1.27*Chi - 0.54*Psi;
175 //sa.SY = 67.7 + 1.00*Chi - 0.68*R;
176
177 // Angles derived from pointing in the dark
179 sa.SE = -4.0 + 1.10 * R + 0.90 * Psi;
180 sa.EE = 39.4 + 0.54 * R - 1.06 * Psi;
181 sa.SY = 13.2 + 0.86 * Chi + 0.11 * Psi;
182 sa.EY = -10.0 + 1.08 * Chi - 0.35 * Psi;
183
184 sa.SE = simox::math::deg_to_rad(sa.SE);
185 sa.SY = simox::math::deg_to_rad(sa.SY);
186 sa.EE = simox::math::deg_to_rad(sa.EE);
187 sa.EY = simox::math::deg_to_rad(sa.EY);
188
189 if (side == "Left")
190 {
191 sa.SY = -sa.SY;
192 sa.EY = -sa.EY;
193 }
194
195 return sa;
196}
197
200{
201 Eigen::AngleAxisf aaSE(sa.SE, Eigen::Vector3f::UnitX());
202 Eigen::AngleAxisf aaSY(-sa.SY, Eigen::Vector3f::UnitZ());
203 Eigen::AngleAxisf aaEE(-sa.EE, Eigen::Vector3f::UnitX());
204 Eigen::AngleAxisf aaEY(-sa.EY, Eigen::Vector3f::UnitZ());
205 Eigen::Vector3f elb = -Eigen::Vector3f::UnitZ() * upperArmLength;
206 elb = aaSY * aaSE * elb;
207 Eigen::Vector3f wri = Eigen::Vector3f::UnitZ() * lowerArmLength;
208 wri = aaEY * aaEE * wri;
209 //ARMARX_IMPORTANT << VAROUT(elb.transpose()) << VAROUT(wri.transpose());
210
212 res.shoulder = shoulderPos;
213 res.elbow = shoulderPos + elb;
214 res.wrist = shoulderPos + elb + wri;
215 res.soechtingAngles = sa;
216
217 return res;
218}
219
220void
222{
223 this->scale = scale;
224}
225
226float
228{
229 return scale;
230}
231
232float
234{
235 return upperArmLength;
236}
237
238void
240{
241 upperArmLength = value;
242}
243
244float
246{
247 return lowerArmLength;
248}
249
250void
252{
253 lowerArmLength = value;
254}
255
257 const NaturalIK::ArmJoints& arm,
258 const NaturalDiffIK::Mode& setOri,
259 const NaturalIK::Parameters& params) :
260 natik(natik), arm(arm), setOri(setOri), params(params)
261{
262}
263
265NaturalIKProvider::SolveAbsolute(const Eigen::Matrix4f& targetPose)
266{
267 params.diffIKparams.resetRnsValues = true;
268 NaturalDiffIK::Result result = natik.calculateIK(targetPose, arm, setOri, params);
269 DiffIKResult r;
270 r.jointValues = arm.rns->getJointValuesEigen();
271 r.oriError = result.oriError;
272 r.posError = result.posError;
273 r.reachable = result.reached;
274 return r;
275}
276
278NaturalIKProvider::SolveRelative(const Eigen::Matrix4f& targetPose,
279 const Eigen::VectorXf& startJointValues)
280{
281 params.diffIKparams.resetRnsValues = false;
282 arm.rns->setJointValues(startJointValues);
283 NaturalDiffIK::Result result = natik.calculateIK(targetPose, arm, setOri, params);
284 DiffIKResult r;
285 r.jointValues = arm.rns->getJointValuesEigen();
286 r.oriError = result.oriError;
287 r.posError = result.posError;
288 r.reachable = result.reached;
289 return r;
290}
#define lo(x)
#define hi(x)
#define M_PI
Definition MathTools.h:17
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())
DiffIKResult SolveAbsolute(const Eigen::Matrix4f &targetPose)
DiffIKResult SolveRelative(const Eigen::Matrix4f &targetPose, const Eigen::VectorXf &startJointValues)
NaturalIKProvider(const NaturalIK &natik, const NaturalIK::ArmJoints &arm, const NaturalDiffIK::Mode &setOri, const NaturalIK::Parameters &params=NaturalIK::Parameters())
The NaturalIK class.
Definition NaturalIK.h:53
Eigen::Vector3f getShoulderPos()
NaturalIK::SoechtingForwardPositions solveSoechtingIK(const Eigen::Vector3f &targetPos, std::optional< float > minElbowHeight=std::nullopt)
Definition NaturalIK.cpp:43
NaturalDiffIK::Result calculateIK(const Eigen::Matrix4f &targetPose, ArmJoints arm, NaturalIK::Parameters params=NaturalIK::Parameters())
Definition NaturalIK.cpp:88
NaturalDiffIK::Result calculateIKpos(const Eigen::Vector3f &targetPos, ArmJoints arm, NaturalIK::Parameters params=NaturalIK::Parameters())
NaturalIK(std::string side, Eigen::Vector3f shoulderPos=Eigen::Vector3f::Zero(), float scale=1)
Definition NaturalIK.cpp:37
float getUpperArmLength() const
SoechtingForwardPositions forwardKinematics(SoechtingAngles sa)
SoechtingAngles CalculateSoechtingAngles(Eigen::Vector3f target)
NaturalIK::CalculateSoechtingAngles.
void setUpperArmLength(float value)
float getLowerArmLength() const
void setLowerArmLength(float value)
void setScale(float scale)
This file offers overloads of toIce() and fromIce() functions for STL container types.
Eigen::VectorXf jointValues
VirtualRobot::RobotNodePtr elbow
Definition NaturalIK.h:68
VirtualRobot::RobotNodeSetPtr rns
Definition NaturalIK.h:67
VirtualRobot::RobotNodePtr tcp
Definition NaturalIK.h:70
NaturalDiffIK::Parameters diffIKparams
Definition NaturalIK.h:61
std::optional< float > minimumElbowHeight
Definition NaturalIK.h:62