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 
31 using namespace armarx;
32 using namespace VisualServoGroup;
33 
34 
35 // DO NOT EDIT NEXT LINE
36 SetTCPVelocity::SubClassRegistry SetTCPVelocity::Registry(SetTCPVelocity::GetName(),
38 
40  XMLStateTemplate<SetTCPVelocity>(stateData),
41  SetTCPVelocityGeneratedBase<SetTCPVelocity>(stateData)
42 {
43 }
44 
45 void
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 );
137  diffRot4.block<3, 3>(0, 0) = diffRot;
138  VirtualRobot::MathTools::eigen4f2rpy(diffRot4, angles);
139 
140  //rotation diff around one axis
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 
261 void
262 SetTCPVelocity::onBreak()
263 {
264  // put your user code for the breaking point here
265  // execution time should be short (<100ms)
266 }
267 
268 void
270 {
271  // put your user code for the exit point here
272  // execution time should be short (<100ms)
273 }
274 
275 float
276 SetTCPVelocity::sigmoid(float t, float offset) const
277 {
278  return 1 / (1 + pow(M_E, -t / 5.f + offset));
279 }
280 
281 void
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 
299  removeDebugVisu();
300 }
301 
302 // DO NOT EDIT NEXT FUNCTION
303 std::string
305 {
306  return "SetTCPVelocity";
307 }
308 
309 // DO NOT EDIT NEXT FUNCTION
312 {
313  return XMLStateFactoryBasePtr(new SetTCPVelocity(stateData));
314 }
315 
316 void
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 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::VisualServoGroup::SetTCPVelocity::SetTCPVelocity
SetTCPVelocity(XMLStateConstructorParams stateData)
Definition: SetTCPVelocity.cpp:39
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:36
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
armarx::XMLStateConstructorParams
Definition: XMLState.h:49
armarx::VisualServoGroup::SetTCPVelocity::Registry
static SubClassRegistry Registry
Definition: SetTCPVelocity.h:53
armarx::VisualServoGroup::SetTCPVelocity::onEnter
void onEnter() override
Definition: SetTCPVelocity.cpp:46
armarx::XMLStateFactoryBasePtr
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition: XMLState.h:64
IceInternal::Handle< FramedPose >
armarx::VisualServoGroup::SetTCPVelocity::GetName
static std::string GetName()
Definition: SetTCPVelocity.cpp:304
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
SetTCPVelocity.h
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
armarx::XMLStateTemplate
Class for legacy to stay compatible with old statecharts.
Definition: XMLState.h:146
M_PI
#define M_PI
Definition: MathTools.h:17
armarx::VisualServoGroup::SetTCPVelocity
Definition: SetTCPVelocity.h:36
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::VariantType::FramedDirection
const VariantTypeId FramedDirection
Definition: FramedPose.h:37
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::VisualServoGroup::SetTCPVelocity::removeDebugVisu
void removeDebugVisu()
Definition: SetTCPVelocity.cpp:317
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:649
min
T min(T t1, T t2)
Definition: gdiam.h:44
armarx::VisualServoGroup::SetTCPVelocity::onExit
void onExit() override
Definition: SetTCPVelocity.cpp:269
armarx::VisualServoGroup::SetTCPVelocity::sigmoid
float sigmoid(float t, float offset) const
Definition: SetTCPVelocity.cpp:276
armarx::VisualServoGroup::SetTCPVelocity::CreateInstance
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
Definition: SetTCPVelocity.cpp:311
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::VisualServoGroup::SetTCPVelocity::stopMovement
void stopMovement()
Definition: SetTCPVelocity.cpp:282
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19