CartesianNaturalPositionController.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 Raphael Grimm (raphael dot grimm at kit dot edu)
20 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
24
26
27#include <VirtualRobot/IK/DifferentialIK.h>
28#include <VirtualRobot/MathTools.h>
29#include <VirtualRobot/Nodes/RobotNode.h>
30#include <VirtualRobot/math/Helpers.h>
31
34
36
37namespace armarx
38{
40 const VirtualRobot::RobotNodeSetPtr& rns,
41 const VirtualRobot::RobotNodePtr& elbow,
42 float maxPositionAcceleration,
43 float maxOrientationAcceleration,
44 float maxNullspaceAcceleration,
45 const VirtualRobot::RobotNodePtr& tcp) :
46 vcTcp(rns,
47 Eigen::VectorXf::Constant(rns->getSize(), 0.f),
48 VirtualRobot::IKSolver::CartesianSelection::All,
49 maxPositionAcceleration,
50 maxOrientationAcceleration,
51 maxNullspaceAcceleration,
52 tcp ? tcp : rns->getTCP()),
53 pcTcp(tcp ? tcp : rns->getTCP()),
54 vcElb(rns, elbow),
55 pcElb(elbow),
56 lastJointVelocity(Eigen::VectorXf::Constant(rns->getSize(), 0.f)),
57 rns(rns)
58 {
61 }
62
63 Eigen::VectorXf
65 const std::vector<float>& maxValue)
66 {
67 if (maxValue.size() == 0)
68 {
69 return vec;
70 }
71 if (maxValue.size() != 1 && (int)maxValue.size() != vec.rows())
72 {
73 throw std::invalid_argument("maxValue.size != 1 and != maxValue.size");
74 }
75 float scale = 1;
76 for (int i = 0; i < vec.rows(); i++)
77 {
78 int j = maxValue.size() == 1 ? 0 : i;
79 if (std::abs(vec(i)) > maxValue.at(j) && maxValue.at(j) >= 0)
80 {
81 scale = std::min(scale, maxValue.at(j) / std::abs(vec(i)));
82 }
83 }
84 return vec * scale;
85 }
86
87 const Eigen::VectorXf
89 {
90 Eigen::VectorXf jvNT = Eigen::VectorXf(rns->getSize());
91 for (size_t i = 0; i < rns->getSize(); i++)
92 {
93 if (std::isnan(nullspaceTarget(i)))
94 {
95 jvNT(i) = 0;
96 }
97 else
98 {
99 float diff = nullspaceTarget(i) - rns->getNode(i)->getJointValue();
100 if (rns->getNode(i)->isLimitless())
101 {
102 diff = ::math::Helpers::AngleModPI(diff);
103 }
104 jvNT(i) = diff;
105 }
106 }
107 return jvNT;
108 }
109
110 const Eigen::VectorXf
112 VirtualRobot::IKSolver::CartesianSelection mode)
113 {
114
115 //int posLen = mode & VirtualRobot::IKSolver::Position ? 3 : 0;
116 //int oriLen = mode & VirtualRobot::IKSolver::Orientation ? 3 : 0;
117 //Eigen::Vector3f pdTcp = posLen ? pcTcp.getPositionDiff(tcpTarget) : Eigen::Vector3f::Zero();
118 //Eigen::Vector3f odTcp = oriLen ? pcTcp.getOrientationDiff(tcpTarget) : Eigen::Vector3f::Zero();
119 //Eigen::VectorXf cartesianVel(posLen + oriLen);
120 //if (posLen)
121 //{
122 // cartesianVel.block<3, 1>(0, 0) = pdTcp;
123 //}
124 //if (oriLen)
125 //{
126 // cartesianVel.block<3, 1>(posLen, 0) = odTcp;
127 //}
128 Eigen::VectorXf cartesianVelTcp = pcTcp.calculate(tcpTarget, mode);
129
130 //Eigen::Vector3f pdElb = pcElb.getPositionDiffVec3(elbowTarget);
131 ////ARMARX_IMPORTANT << deactivateSpam(0.1) << VAROUT(pdElb) << VAROUT(elbowTarget) << VAROUT(pcElb.getTcp()->getPositionInRootFrame());
132 //Eigen::VectorXf cartesianVelElb(3);
133 //cartesianVelElb.block<3, 1>(0, 0) = pdElb;
134
135 Eigen::VectorXf cartesianVelElb = pcElb.calculatePos(elbowTarget);
136 Eigen::VectorXf jnvClamped = Eigen::VectorXf::Zero(rns->getSize());
138 {
139 Eigen::VectorXf jnv = Eigen::VectorXf::Zero(rns->getSize());
140 Eigen::VectorXf jvElb =
141 vcElb.calculate(cartesianVelElb, VirtualRobot::IKSolver::Position);
142
143 Eigen::VectorXf jvLA =
144 jointLimitAvoidanceKp * vcTcp.controller.calculateJointLimitAvoidance();
145 Eigen::VectorXf jvNT = nullspaceTargetKp * calculateNullspaceTargetDifference();
146 //ARMARX_IMPORTANT << deactivateSpam(1) << VAROUT(jvNT);
147
148 //ARMARX_IMPORTANT << VAROUT(jvElb);
149 jnv = jvElb + jvLA + jvNT;
150 jnvClamped = LimitInfNormTo(jnv, maxNullspaceVelocity);
151 }
152
153 //ARMARX_IMPORTANT << VAROUT(jnv);
154 if (vcTcp.getMode() != mode)
155 {
156 vcTcp.switchMode(lastJointVelocity, mode);
157 }
158 Eigen::VectorXf jv = vcTcp.calculate(cartesianVelTcp, jnvClamped, dt);
159 //ARMARX_IMPORTANT << VAROUT(jv);
160
161 Eigen::VectorXf jvClamped = LimitInfNormTo(jv, maxJointVelocity);
162
164 {
166 }
167
168 lastJointVelocity = jvClamped;
169
170 return jvClamped;
171 }
172
173 void
175 const Eigen::Vector3f& elbowTarget)
176 {
177 this->tcpTarget = tcpTarget;
178 this->elbowTarget = elbowTarget;
179 }
180
181 void
187
188 void
190 const Eigen::Vector3f& feedForwardVelocityPos,
191 const Eigen::Vector3f& feedForwardVelocityOri)
192 {
193 feedForwardVelocity.block<3, 1>(0, 0) = feedForwardVelocityPos;
194 feedForwardVelocity.block<3, 1>(3, 0) = feedForwardVelocityOri;
195 }
196
197 void
199 {
200 this->nullspaceTarget = nullspaceTarget;
201 }
202
203 void
205 const std::vector<float>& nullspaceTarget)
206 {
207 ARMARX_CHECK_EXPRESSION(rns->getSize() == nullspaceTarget.size());
208 for (size_t i = 0; i < rns->getSize(); i++)
209 {
210 this->nullspaceTarget(i) = nullspaceTarget.at(i);
211 }
212 }
213
214 void
216 {
217 this->nullspaceTarget = Eigen::VectorXf::Constant(rns->getSize(), std::nanf(""));
218 }
219
220 void
225
226 float
228 {
229 return pcTcp.getPositionError(getCurrentTarget());
230 }
231
232 float
234 {
235 return pcTcp.getOrientationError(getCurrentTarget());
236 }
237
238 bool
244
245 bool
251
252 const Eigen::Matrix4f&
257
258 const Eigen::Vector3f
260 {
261 return ::math::Helpers::GetPosition(tcpTarget);
262 }
263
264 const Eigen::Vector3f&
269
270 const Eigen::VectorXf&
275
276 bool
278 {
279 for (int i = 0; i < nullspaceTarget.rows(); i++)
280 {
281 if (!std::isnan(nullspaceTarget(i)))
282 {
283 return true;
284 }
285 }
286 return false;
287 }
288
289 void
294
295 std::string
297 {
298 std::stringstream ss;
299 ss.precision(2);
300 ss << std::fixed << "distance: " << getPositionError() << " mm "
301 << VirtualRobot::MathTools::rad2deg(getOrientationError()) << " deg";
302 return ss.str();
303 }
304
305 void
307 const CartesianNaturalPositionControllerConfig& cfg)
308 {
309 jointLimitAvoidanceKp = cfg.jointLimitAvoidanceKp;
310
311 thresholdOrientationNear = cfg.thresholdOrientationNear;
312 thresholdOrientationReached = cfg.thresholdOrientationReached;
313 thresholdPositionNear = cfg.thresholdPositionNear;
314 thresholdPositionReached = cfg.thresholdPositionReached;
315
316 maxJointVelocity = cfg.maxJointVelocity;
317 maxNullspaceVelocity = cfg.maxNullspaceVelocity;
318
319 nullspaceTargetKp = cfg.nullspaceTargetKp;
320
321 pcTcp.maxPosVel = cfg.maxTcpPosVel;
322 pcTcp.maxOriVel = cfg.maxTcpOriVel;
323 pcTcp.KpOri = cfg.KpOri;
324 pcTcp.KpPos = cfg.KpPos;
325 pcElb.maxPosVel = cfg.maxElbPosVel;
326 pcElb.KpPos = cfg.elbowKp;
327
328 vcTcp.setMaxAccelerations(cfg.maxPositionAcceleration,
329 cfg.maxOrientationAcceleration,
330 cfg.maxNullspaceAcceleration);
331 if (cfg.jointCosts.size() > 0)
332 {
333 vcTcp.controller.setJointCosts(cfg.jointCosts);
334 }
335 }
336
337 Eigen::VectorXf
339 {
340 return (vcTcp.controller.ik->getJacobianMatrix(VirtualRobot::IKSolver::All) * jointVel);
341 }
342
343 Eigen::VectorXf
345 {
346 return (vcElb.jacobi * jointVel);
347 }
348} // namespace armarx
constexpr T dt
void setNullspaceTarget(const Eigen::VectorXf &nullspaceTarget)
const Eigen::VectorXf calculate(float dt, VirtualRobot::IKSolver::CartesianSelection mode=VirtualRobot::IKSolver::All)
static Eigen::VectorXf LimitInfNormTo(const Eigen::VectorXf &vec, const std::vector< float > &maxValue)
Eigen::VectorXf actualElbVel(const Eigen::VectorXf &jointVel)
void setConfig(const CartesianNaturalPositionControllerConfig &cfg)
CartesianNaturalPositionController(const VirtualRobot::RobotNodeSetPtr &rns, const VirtualRobot::RobotNodePtr &elbow, float maxPositionAcceleration, float maxOrientationAcceleration, float maxNullspaceAcceleration, const VirtualRobot::RobotNodePtr &tcp=nullptr)
Eigen::VectorXf actualTcpVel(const Eigen::VectorXf &jointVel)
void setFeedForwardVelocity(const Eigen::Vector6f &feedForwardVelocity)
void setTarget(const Eigen::Matrix4f &tcpTarget, const Eigen::Vector3f &elbowTarget)
#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_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Matrix< float, 6, 1 > Vector6f
This file offers overloads of toIce() and fromIce() functions for STL container types.