MoveTCPToTarget.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotSkillTemplates::MotionControlGroup
17 * @author Mirko Waechter ( mirko dot waechter at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "MoveTCPToTarget.h"
24#include <VirtualRobot/MathTools.h>
25#include <VirtualRobot/RobotNodeSet.h>
26
27//#include <ArmarXCore/core/time/TimeUtil.h>
28//#include <ArmarXCore/observers/variant/DatafieldRef.h>
30
32
33using namespace armarx;
34using namespace MotionControlGroup;
35
36// DO NOT EDIT NEXT LINE
37MoveTCPToTarget::SubClassRegistry MoveTCPToTarget::Registry(MoveTCPToTarget::GetName(),
39
40Eigen::Vector3f
41GetClosestPoint(const Eigen::Vector3f& p1, const Eigen::Vector3f& p2, const Eigen::Vector3f& p)
42{
43 Eigen::Vector3f dir = p2 - p1;
44 return p1 - (p1 - p).dot(dir) * dir / dir.squaredNorm();
45}
46
47float
48GetT(const Eigen::Vector3f& p1, const Eigen::Vector3f& p2, const Eigen::Vector3f& p)
49{
50 Eigen::Vector3f dir = p2 - p1;
51 return (p - p1).dot(dir) / dir.squaredNorm();
52}
53
54Eigen::Vector3f
55Get(const Eigen::Vector3f& p1, const Eigen::Vector3f& p2, float t)
56{
57 Eigen::Vector3f dir = p2 - p1;
58 return p1 + t * dir;
59}
60
61void
63{
64 // put your user code for the enter-point here
65 // execution time should be short (<100ms)
66}
67
68void
70{
71 // put your user code for the execution-phase here
72 // runs in seperate thread, thus can do complex operations
73 // should check constantly whether isRunningTaskStopped() returns true
74 MotionControlGroupStatechartContext* c = getContext<MotionControlGroupStatechartContext>();
75 bool wasAlreadyRequested = c->getTCPControlUnit()->isRequested();
76 if (!wasAlreadyRequested)
77 {
78 c->getTCPControlUnit()->request();
79 }
80 std::string tcpName;
81 if (in.isTCPNameSet())
82 {
83 tcpName = in.getTCPName();
84 }
85 else
86 {
87 tcpName = c->getRobot()->getRobotNodeSet(in.getKinematicChainName())->getTCP()->getName();
88 }
89 std::string kinematicChainName = in.getKinematicChainName();
90 FramedPosePtr startPose =
91 new FramedPose(c->getRobot()->getRobotNode(tcpName)->getPoseInRootFrame(),
92 c->getRobot()->getRootNode()->getName(),
93 c->getRobot()->getName());
94 FramedPosePtr targetPose = in.getTargetPose();
95 auto robot = c->getLocalRobot();
96
97 FramedPosePtr globalTargetPose = targetPose->toGlobal(robot);
98
99 Eigen::Vector3f startPositionInRootFrame = startPose->toEigen().block<3, 1>(0, 3);
100 Eigen::Vector3f targetPositionInRootFrame =
101 targetPose->toRootEigen(c->getRobot()->clone()).block<3, 1>(0, 3);
102 // out.setStartPose(FramedPosePtr::dynamicCast(startPose->clone()));
103 auto sharedRobot = c->getRobotStateComponent()->getSynchronizedRobot();
104 auto tcp = robot->getRobotNode(tcpName);
105 float tcpVelocity = in.getTCPVelocity();
106 // Eigen::Vector3f tcpDirectionInRootFrame = in.getMoveDirection()->toRootEigen(robot).normalized();
107 // int sleepTimeMilliSec = int(1.0f / in.getControlFrequency() * 1000.0f);
108 // ARMARX_INFO << "Keeping orientation: " << keepOrientation;
109 // Eigen::Quaternionf deltaOri((startPose->toEigen().inverse() * in.getTargetPose()->toEigen()).block<3,3>(0,0));
110 Eigen::Quaternionf startOri(startPose->toEigen().block<3, 3>(0, 0));
111 Eigen::Quaternionf targetOri(in.getTargetPose()->toRootEigen(robot).block<3, 3>(0, 0));
112 float tOffset = in.getTOffset();
113 float ignoreOrientation = in.getIgnoreOrientationBeforeT();
114 armarx::CycleUtil cycle(1000.f / in.getControlFrequency());
115 auto toleratedAngleError = in.getToleratedOrientationDifference();
116
117 float pOri = in.getKpOrientation();
118 // uncomment this if you need a continous run function. Make sure to use sleep or use blocking wait to reduce cpu load.
119 while (!isRunningTaskStopped()) // stop run function if returning true
120 {
121 RemoteRobot::synchronizeLocalClone(robot, sharedRobot);
122
123 float t = GetT(
124 startPositionInRootFrame, targetPositionInRootFrame, tcp->getPositionInRootFrame());
125 float tPos = t + tOffset;
126 Eigen::Quaternionf currentTargetOri = startOri.slerp(t, targetOri);
127
128
129 FramedDirectionPtr orientationVel, positionVel;
130
131 Eigen::Vector3f orientationDelta;
132 FramedOrientationPtr TCPDeltaToCurrentTarget = new FramedOrientation(
133 currentTargetOri.toRotationMatrix(), robot->getRootNode()->getName(), robot->getName());
134 TCPDeltaToCurrentTarget->changeFrame(robot, tcpName);
135 Eigen::Matrix4f orientationDelta4x4 = Eigen::Matrix4f::Identity();
136 orientationDelta4x4.block<3, 3>(0, 0) = TCPDeltaToCurrentTarget->toEigen();
137 VirtualRobot::MathTools::eigen4f2rpy(orientationDelta4x4, orientationDelta);
138 orientationVel = new FramedDirection(orientationDelta * pOri, tcpName, robot->getName());
139 orientationVel->changeFrame(robot, robot->getRootNode()->getName());
140 Eigen::Vector3f axis;
141 float angleError = 0;
142 orientationDelta4x4.block<3, 3>(0, 0) = TCPDeltaToCurrentTarget->toEigen();
143 VirtualRobot::MathTools::eigen4f2axisangle(orientationDelta4x4, axis, angleError);
144
145
146 Eigen::Vector3f currentTargetPosition =
147 Get(startPositionInRootFrame, targetPositionInRootFrame, tPos);
148 float positionError = (currentTargetPosition - tcp->getPositionInRootFrame()).norm();
149 c->getDebugDrawerTopicProxy()->setPoseVisu(
150 "MoveTCPToTarget", "CurrentPose", new Pose(tcp->getGlobalPose()));
151 c->getDebugDrawerTopicProxy()->setPoseVisu(
152 "MoveTCPToTarget", "TargetPose", globalTargetPose);
153 c->getDebugDrawerTopicProxy()->setSphereVisu(
154 "MoveTCPToTarget",
155 "CurrentTargetPose",
156 FramedPosition(currentTargetPosition, robot->getRootNode()->getName(), robot->getName())
157 .toGlobal(robot),
158 DrawColor{1.0, 0, 0, 1},
159 10);
160
161 Eigen::Vector3f positionVelEigen =
162 (currentTargetPosition - tcp->getPositionInRootFrame()).normalized() * tcpVelocity;
163 positionVel = new FramedDirection(
164 positionVelEigen, robot->getRootNode()->getName(), robot->getName());
165
166 if (t >= 1)
167 {
168 emitSuccess();
169 break;
170 }
172 << deactivateSpam(1) << VAROUT(t) << VAROUT(positionError) << VAROUT(angleError)
173 << VAROUT(
174 positionVel
175 ->output()); // << VAROUT(startPositionInRootFrame) << VAROUT(tcp->getPositionInRootFrame());
176 orientationVel = t < ignoreOrientation ? FramedDirectionPtr() : orientationVel;
177 if (angleError < toleratedAngleError)
178 {
179 orientationVel = nullptr;
180 }
181 c->getTCPControlUnit()->setTCPVelocity(
182 kinematicChainName, tcpName, positionVel, orientationVel);
183 cycle.waitForCycleDuration();
184 }
185 c->getDebugDrawerTopicProxy()->clearLayer("MoveTCPToTarget");
186
187 FramedDirectionPtr zeroVelocity(new FramedDirection(0, 0, 0, tcpName, robot->getName()));
188 c->getTCPControlUnit()->setTCPVelocity(kinematicChainName, tcpName, zeroVelocity, zeroVelocity);
190 if (!wasAlreadyRequested)
191 {
192 c->getTCPControlUnit()->release();
193 }
194}
195
196//void MoveTCPToTarget::onBreak()
197//{
198// // put your user code for the breaking point here
199// // execution time should be short (<100ms)
200//}
201
202void
204{
205 // put your user code for the exit point here
206 // execution time should be short (<100ms)
207}
208
209// DO NOT EDIT NEXT FUNCTION
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
Eigen::Vector3f GetClosestPoint(const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p)
Eigen::Vector3f Get(const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, float t)
float GetT(const Eigen::Vector3f &p1, const Eigen::Vector3f &p2, const Eigen::Vector3f &p)
#define VAROUT(x)
constexpr T c
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
IceUtil::Time waitForCycleDuration()
This function will wait (virtual or system time) until the cycle time is reached.
Definition CycleUtil.cpp:53
FramedDirection is a 3 dimensional direction vector with a reference frame.
Definition FramedPose.h:87
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPose class.
Definition FramedPose.h:281
The FramedPosition class.
Definition FramedPose.h:158
FramedPositionPtr toGlobal(const SharedRobotInterfacePrx &referenceRobot) const
custom implementation of the StatechartContext for a statechart
MoveTCPToTarget(const XMLStateConstructorParams &stateData)
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
The Pose class.
Definition Pose.h:243
Eigen::Matrix3f slerp(float, const Eigen::Matrix3f &)
Definition Pose.cpp:233
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
static void MSSleep(int durationMS)
lock the calling thread for a given duration (like usleep(...) but using Timeserver time)
Definition TimeUtil.cpp:100
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
Quaternion< float, 0 > Quaternionf
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< FramedDirection > FramedDirectionPtr
Definition FramedPose.h:84
IceInternal::Handle< FramedOrientation > FramedOrientationPtr
Definition FramedPose.h:207
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition XMLState.h:64
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
double dot(const Point &x, const Point &y)
Definition point.hpp:57