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