SetTCPVelocity.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::GraspObjectGroup
19 * @author David ( david dot schiebener 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
25#include "SetTCPVelocity.h"
26
27#include <VirtualRobot/MathTools.h>
28
29#include "VisualServoGroupStatechartContext.generated.h"
30
31using namespace armarx;
32using namespace VisualServoGroup;
33
34
35// DO NOT EDIT NEXT LINE
36SetTCPVelocity::SubClassRegistry SetTCPVelocity::Registry(SetTCPVelocity::GetName(),
38
41 SetTCPVelocityGeneratedBase<SetTCPVelocity>(stateData)
42{
43}
44
45void
47{
48 bool tcpTargetPoseSet = in.isTcpTargetPoseSet();
49 bool tcpTargetPositionSet = in.isTcpTargetPositionSet();
50 bool tcpTargetOrientationSet = in.isTCPTargetOrientationSet();
51 if (!tcpTargetPoseSet && !tcpTargetPositionSet)
52 {
53 ARMARX_ERROR << "Either TcpTargetPose or TcpTargetPosition has to be set for VisualServo, "
54 "but none is set.";
55 emitFailure();
56 return;
57 }
58
59 VisualServoGroupStatechartContext* context = getContext<VisualServoGroupStatechartContext>();
60 VirtualRobot::RobotPtr robot = context->getRobot();
61
62 FramedPosePtr handPose = in.getHandPose();
63 Eigen::Matrix4f handPoseEigen = handPose->toGlobal(robot)->toEigen();
64
65
66 FramedPosePtr tcpTargetPose;
67 Eigen::Matrix4f tcpTargetPoseEigen;
68 if (tcpTargetPoseSet)
69 {
70 tcpTargetPose = in.getTcpTargetPose();
71 tcpTargetPoseEigen = tcpTargetPose->toGlobal(robot)->toEigen();
72 }
73 else if (tcpTargetPositionSet && !tcpTargetOrientationSet)
74 {
75 tcpTargetPoseEigen = handPoseEigen;
76 tcpTargetPoseEigen.block<3, 1>(0, 3) =
77 in.getTcpTargetPosition()->toGlobal(robot)->toEigen();
78 tcpTargetPose = new FramedPose(tcpTargetPoseEigen, GlobalFrame, robot->getName());
79 }
80 else if (tcpTargetPositionSet && tcpTargetOrientationSet)
81 {
82 tcpTargetPoseEigen.block<3, 3>(0, 0) =
83 in.getTCPTargetOrientation()->toGlobal(robot)->toEigen();
84 tcpTargetPoseEigen.block<3, 1>(0, 3) =
85 in.getTcpTargetPosition()->toGlobal(robot)->toEigen();
86 tcpTargetPose = new FramedPose(tcpTargetPoseEigen, GlobalFrame, robot->getName());
87 }
88
89 const float baseSpeedFactor = in.getBaseVelocityFactor(); // 0.8
90 const float maxSpeed = baseSpeedFactor * in.getMaxVelocityTranslation(); // 40
91 const float maxRotationSpeed =
92 baseSpeedFactor * in.getMaxVelocityRotation(); //60.0f*M_PI/180.0f; // 15
93 const float baseAngleRelativeSpeedFactor = 10;
94
95
96 // get translational difference
97 Eigen::Vector3f diffPos =
98 tcpTargetPoseEigen.block<3, 1>(0, 3) - handPoseEigen.block<3, 1>(0, 3);
99 ARMARX_INFO << in.getKinematicChainName() << " : difference to target " << diffPos;
100 const float distanceToTarget = diffPos.norm();
101
102 // float speedFactor = baseSpeedFactor;
103 // if (speedFactor*distanceToTarget > maxSpeed) speedFactor = maxSpeed / distanceToTarget;
104 ARMARX_VERBOSE << "TCP translation: " << diffPos;
105
106 float sig = sigmoid(diffPos.norm(), 1.0);
107 ARMARX_VERBOSE << "Input for sig: " << diffPos.norm() << " " << VAROUT(sig);
108 diffPos = baseSpeedFactor * diffPos * sig;
109 float minSpeedPerc = in.getMinimumSpeedPercentage();
110 // // Dont let it go to slow
111 if (diffPos.norm() < maxSpeed * minSpeedPerc)
112 {
113 diffPos = diffPos.normalized() * (maxSpeed * minSpeedPerc);
114 }
115
116 if (diffPos.norm() > maxSpeed)
117 {
118 diffPos = diffPos.normalized() * (maxSpeed);
119 }
120
121 ARMARX_VERBOSE << "Speed: " << diffPos.norm();
122 FramedDirectionPtr cartesianVelocity = new FramedDirection(diffPos, GlobalFrame, "");
123
124 Eigen::Vector3f angles(0, 0, 0);
125 std::stringstream distanceStr;
126 distanceStr << distanceToTarget << " mm";
127 float axisRot = 0;
128 if (tcpTargetPoseSet || (tcpTargetPositionSet && tcpTargetOrientationSet))
129 {
130 // get rotational difference
131 Eigen::Matrix3f diffRot =
132 tcpTargetPoseEigen.block<3, 3>(0, 0) * handPoseEigen.block<3, 3>(0, 0).inverse();
133 // Eigen::Quaternionf handQuat(handPose->toEigen().block<3,3>(0,0));
134 // Eigen::Quaternionf targetQuat(tcpTargetPose->toEigen().block<3,3>(0,0));
135 // float rotErrorAngle = acos(2 * (handQuat.dot(targetQuat)) -1 );
136 Eigen::Matrix4f diffRot4 = Eigen::Matrix4f::Identity();
137 diffRot4.block<3, 3>(0, 0) = diffRot;
138 VirtualRobot::MathTools::eigen4f2rpy(diffRot4, angles);
139
140 //rotation diff around one axis
141 Eigen::Matrix4f diffPose = Eigen::Matrix4f::Identity();
142 diffPose.block<3, 3>(0, 0) = diffRot;
143 Eigen::Vector3f axis;
144 VirtualRobot::MathTools::eigen4f2axisangle(diffPose, axis, axisRot);
145
146 distanceStr << ", " << axisRot * 180 / M_PI << " deg";
147
148 float angleRelativeSpeedFactor = baseAngleRelativeSpeedFactor;
149 if (distanceToTarget < in.getPositionalAccuracy())
150 {
151 angleRelativeSpeedFactor *= 1.5f;
152 }
153
154 angles = angleRelativeSpeedFactor * baseSpeedFactor * angles;
155 if (angles.norm() > maxRotationSpeed)
156 {
157 ARMARX_IMPORTANT << deactivateSpam(1) << "angle velo to high reducing from "
158 << angles.norm();
159 angles *= maxRotationSpeed / angles.norm();
160 }
161 }
162
163 FramedDirectionPtr angleVelocity = new FramedDirection(angles, GlobalFrame, "");
164
165 std::string kinematicChainName = getInput<std::string>("KinematicChainName");
166
167 ARMARX_VERBOSE << "Angle motion (" << angles(0) << ", " << angles(1) << ", " << angles(2)
168 << ")";
169
170 // // make sure we don't move the hand too low
171 // if (handPoseFromKinematicModelEigen(2,3) < 1000 && cartesianVelocity->z < 0)
172 // {
173 // ARMARX_IMPORTANT << "Hand too low, moving it up a bit";
174 // if (handPoseFromKinematicModelEigen(2,3) < 950) cartesianVelocity->z = 0.1f*maxSpeed;
175 // else cartesianVelocity->z = 0.05f*maxSpeed;
176 // }
177
178
179 setOutput("HandPose", handPose);
180
181 float accuracyFactor = 1.0;
182 float elapsed = in.getStartTimeRef()->getDataField("elapsedMs")->getInt();
183 float timeout = in.getAccuracyIncreaseTimeout();
184
185 if (timeout > 0 && elapsed < timeout)
186 {
187 accuracyFactor = 0.5 + pow(elapsed / timeout, 2);
188 }
189
190 accuracyFactor = std::min(1.0f, accuracyFactor);
191 ARMARX_IMPORTANT << "Distance to target: " << distanceStr.str() << ", Elapsed time: " << elapsed
192 << "\nCurrent Thresholds: " << in.getPositionalAccuracy() * accuracyFactor
193 << "mm, "
194 << (in.getOrientationalAccuracyRad() * accuracyFactor) * 180.0f / M_PI
195 << "deg";
196
197
198 // visualize TCP target
199 if (context->getWorkingMemory()
200 ->getAgentInstancesSegment() /*&& elapsed/100 - (int)(elapsed/100) % 3 == 0*/)
201 {
202 // visualize Poses
203 auto globalHandPose = handPose->toGlobal(robot);
204 auto globalTargetPose = tcpTargetPose->toGlobal(robot);
205 //robot->print();
206 auto chainName = in.getKinematicChainName();
207 context->getEntityDrawerTopic()->updateObjectPose(
208 "VisualServoHandVisu", "tcpTarget_" + chainName, globalTargetPose);
209 // context->getDebugDrawerTopic()->setPoseVisu("VisualServo", "tcpTargetPose_" + chainName, globalTargetPose);
210 context->getDebugDrawerTopic()->setSphereVisu("VisualServo",
211 "tcpTargetPoseAccuracy_" + chainName,
212 globalTargetPose->position,
213 DrawColor{1, 1, 0, 0.5},
214 in.getPositionalAccuracy() * accuracyFactor);
215 context->getDebugDrawerTopic()->setLineVisu("VisualServo",
216 "Distance to target_" + chainName,
217 globalHandPose->position,
218 globalTargetPose->position,
219 5,
220 DrawColor{1, 1, 1, 1});
221 context->getDebugDrawerTopic()->setTextVisu("VisualServo",
222 "Distance_" + chainName,
223 distanceStr.str(),
224 globalTargetPose->position,
225 DrawColor{1, 0, 0, 1},
226 15);
227 }
228
229
230 // stop when target reached
231 if ((distanceToTarget < in.getPositionalAccuracy() * accuracyFactor &&
232 axisRot < in.getOrientationalAccuracyRad() * accuracyFactor) ||
233 (elapsed > in.getTimeout() && distanceToTarget < in.getPositionalAccuracy() * 3 &&
234 axisRot < in.getOrientationalAccuracyRad() * 3))
235 {
236 ARMARX_IMPORTANT << "Target reached";
237
238 stopMovement();
239 emitTargetReached();
240 }
241 else if (elapsed > in.getTimeout())
242 {
243 ARMARX_ERROR << "Could not reach object in time " << in.getTimeout()
244 << "ms - Remaining error: " << distanceToTarget << "mm and "
245 << axisRot * 180 / M_PI << "deg";
246 stopMovement();
247 emitTimeout();
248 }
249 else
250 {
251 IceUtil::Time start = IceUtil::Time::now();
252 context->getTCPControlUnit()->setTCPVelocity(
253 kinematicChainName, "", cartesianVelocity, angleVelocity);
254 ARMARX_VERBOSE << "Time for SetHandVelocity - hand IK: "
255 << (IceUtil::Time::now() - start).toMilliSeconds() << " ms";
256
257 emitTCPVelocitySet();
258 }
259}
260
261void
263{
264 // put your user code for the breaking point here
265 // execution time should be short (<100ms)
266}
267
268void
270{
271 // put your user code for the exit point here
272 // execution time should be short (<100ms)
273}
274
275float
276SetTCPVelocity::sigmoid(float t, float offset) const
277{
278 return 1 / (1 + pow(M_E, -t / 5.f + offset));
279}
280
281void
283{
284 VisualServoGroupStatechartContext* context = getContext<VisualServoGroupStatechartContext>();
285 FramedDirectionPtr cartesianVelocity =
286 new FramedDirection(Eigen::Vector3f::Zero(),
287 context->getRobot()->getRootNode()->getName(),
288 context->getRobot()->getName());
289 FramedDirectionPtr angleVelocity =
290 new FramedDirection(Eigen::Vector3f::Zero(),
291 context->getRobot()->getRootNode()->getName(),
292 context->getRobot()->getName());
293
294 std::string kinematicChainName = getInput<std::string>("KinematicChainName");
295
296 context->getTCPControlUnit()->setTCPVelocity(
297 kinematicChainName, "", cartesianVelocity, angleVelocity);
298
300}
301
302// DO NOT EDIT NEXT FUNCTION
303std::string
305{
306 return "SetTCPVelocity";
307}
308
309// DO NOT EDIT NEXT FUNCTION
315
316void
318{
319 VisualServoGroupStatechartContext* context = getContext<VisualServoGroupStatechartContext>();
320 context->getDebugDrawerTopic()->removeTextDebugLayerVisu("Distance");
321 context->getDebugDrawerTopic()->removeLineDebugLayerVisu("Distance to target");
322 context->getDebugDrawerTopic()->removePoseDebugLayerVisu("tcpTargetPose");
323 context->getDebugDrawerTopic()->removeSphereDebugLayerVisu("tcpTargetPoseAccuracy");
324}
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define M_PI
Definition MathTools.h:17
#define VAROUT(x)
FramedDirection is a 3 dimensional direction vector with a reference frame.
Definition FramedPose.h:87
The FramedPose class.
Definition FramedPose.h:281
SetTCPVelocity(XMLStateConstructorParams stateData)
float sigmoid(float t, float offset) const
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#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< FramedDirection > FramedDirectionPtr
Definition FramedPose.h:84
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition XMLState.h:64
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272