TaskspaceImpedanceController.cpp
Go to the documentation of this file.
2#include <Eigen/Core>
3
4#include <SimoxUtility/math/convert/mat4f_to_quat.h>
5#include <VirtualRobot/IK/DifferentialIK.h>
6#include <VirtualRobot/IK/JacobiProvider.h>
7#include <VirtualRobot/MathTools.h>
8#include <VirtualRobot/Nodes/RobotNode.h>
9#include <VirtualRobot/Robot.h>
10#include <VirtualRobot/RobotNodeSet.h>
11
15
17
18#include "../utils.h"
19
21{
22
23 void
24 TaskspaceImpedanceController::initialize(const VirtualRobot::RobotNodeSetPtr& rns,
25 const VirtualRobot::RobotNodeSetPtr& rtRns)
26 {
28 // auto numOfJoints = rns->getSize();
29
30 tcp = rns->getTCP();
31 rtTCP = rtRns->getTCP();
33 ik.reset(new VirtualRobot::DifferentialIK(
34 rtRns, rtRns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
35
36 // I = Eigen::MatrixXf::Identity(numOfJoints, numOfJoints);
37 }
38
39 void
40 TaskspaceImpedanceController::preactivateInit(const VirtualRobot::RobotNodeSetPtr& rns)
41 {
42 }
43
44 void
49
50 // void
51 // TaskspaceImpedanceController::updateFT(const FTConfig& c, RtStatus& rtStatus)
52 // {
53 // /// run in rt thread
54 // ftsensor.updateStatus();
55 // if (c.reCalibrate)
56 // {
57 // ftsensor.calibrated.store(false);
58 // /// TODO how to toggle recalibration?
59 // }
60 // ftsensor.compensateTCPGravity(c);
61 // if (!ftsensor.calibrated.load())
62 // {
63 // if (ftsensor.calibrate(c, rtStatus.deltaT))
64 // {
65 // ftsensor.calibrated.store(true);
66 // }
67 // }
68 // else
69 // {
70 // rtStatus.currentForceTorque = ftsensor.getFilteredForceTorque(c);
71 // }
72 // }
73
74 void
76 {
77 /// run in rt thread
78 rtStatus.currentPose = rtTCP->getPoseInRootFrame();
79
80 /// ---------------------------- safety guard by FT and target pose ------------------------
81 rtStatus.poseDiffMatImp =
82 c.desiredPose.block<3, 3>(0, 0) * rtStatus.currentPose.block<3, 3>(0, 0).transpose();
83 rtStatus.oriDiffAngleAxis.fromRotationMatrix(rtStatus.poseDiffMatImp);
84
85 /// this should not be moved to non rt, just in case non rt thread dies, rt still functions as safely
86 if (not ftsensor.isSafe(c.ftConfig))
87 {
88 ARMARX_INFO << "FTGuard indicates RT not safe";
89 c.desiredPose = rtStatus.desiredPose;
90 rtStatus.rtSafe = false;
91 rtStatus.rtTargetSafe = true;
92 }
93 else if ((c.desiredPose.block<3, 1>(0, 3) - rtStatus.currentPose.block<3, 1>(0, 3)).norm() >
94 c.safeDistanceMMToGoal or
95 std::fminf(rtStatus.oriDiffAngleAxis.angle(),
96 2 * M_PI - rtStatus.oriDiffAngleAxis.angle()) >
97 VirtualRobot::MathTools::deg2rad(c.safeRotAngleDegreeToGoal))
98 {
99 rtStatus.desiredPoseUnsafe = c.desiredPose;
100 c.desiredPose = rtStatus.desiredPose;
101 rtStatus.rtSafe = false;
102 rtStatus.rtTargetSafe = false;
103 }
104 else
105 {
106 rtStatus.desiredPose = c.desiredPose;
107 rtStatus.rtSafe = true;
108 rtStatus.rtTargetSafe = true;
109 }
110
111 auto nDoF = static_cast<Eigen::Index>(rtStatus.nDoF);
112
113 /// ------------------------------ compute jacobi ------------------------------------------
114 rtStatus.jacobi =
115 ik->getJacobianMatrix(rtTCP, VirtualRobot::IKSolver::CartesianSelection::All);
116 rtStatus.jacobi.block(0, 0, 3, nDoF) =
117 0.001 * rtStatus.jacobi.block(0, 0, 3, nDoF);
118 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jacobi.cols());
119 ARMARX_CHECK_EQUAL(6, rtStatus.jacobi.rows());
120
121 rtStatus.jtpinv =
122 ik->computePseudoInverseJacobianMatrix(rtStatus.jacobi.transpose(), rtStatus.lambda);
123 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jtpinv.cols());
124 ARMARX_CHECK_EQUAL(6, rtStatus.jtpinv.rows());
125
126 /// ------------------------------ update velocity/twist -----------------------------------
127 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jointPosition.rows());
128 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jointVelocity.rows());
129 ARMARX_CHECK_EQUAL(nDoF, rtStatus.qvelFiltered.rows());
130
131 rtStatus.qvelFiltered =
132 (1 - c.qvelFilter) * rtStatus.qvelFiltered + c.qvelFilter * rtStatus.jointVelocity;
133 rtStatus.currentTwist = rtStatus.jacobi * rtStatus.qvelFiltered;
134
135 /// ------------------------------------- Impedance control --------------------------------
136 /// calculate pose error between target pose and current pose
137 /// !!! This is very important: you have to keep postion and orientation both
138 /// with UI unit (meter, radian) to calculate impedance force.
139
140 rtStatus.poseDiffMatImp = rtStatus.desiredPose.block<3, 3>(0, 0) *
141 rtStatus.currentPose.block<3, 3>(0, 0).transpose();
142 rtStatus.poseErrorImp.head<3>() = 0.001 * (rtStatus.desiredPose.block<3, 1>(0, 3) -
143 rtStatus.currentPose.block<3, 1>(0, 3));
144 // rtStatus.poseErrorImp.tail<3>() =
145 // VirtualRobot::MathTools::eigen3f2rpy(rtStatus.poseDiffMatImp);
146 rtStatus.oriDiffAngleAxis.fromRotationMatrix(rtStatus.poseDiffMatImp);
147 rtStatus.poseErrorImp.tail<3>() =
148 rtStatus.oriDiffAngleAxis.angle() * rtStatus.oriDiffAngleAxis.axis();
149
150 rtStatus.forceImpedance = c.kpImpedance.cwiseProduct(rtStatus.poseErrorImp) -
151 c.kdImpedance.cwiseProduct(rtStatus.currentTwist);
152
153 /// ----------------------------- Nullspace PD Control -------------------------------------
154 ARMARX_CHECK_EQUAL(nDoF, c.kpNullspaceTorque.rows());
155 ARMARX_CHECK_EQUAL(nDoF, rtStatus.nullspaceTorque.rows());
156 ARMARX_CHECK_EQUAL(nDoF, c.desiredNullspaceJointAngles.value().size());
157 rtStatus.nullspaceTorque =
158 c.kpNullspaceTorque.cwiseProduct(c.desiredNullspaceJointAngles.value() - rtStatus.jointPosition) -
159 c.kdNullspaceTorque.cwiseProduct(rtStatus.qvelFiltered);
160
161 /// ----------------------------- Map TS target force to JS --------------------------------
162 ARMARX_CHECK_EQUAL(nDoF, rtStatus.desiredJointTorque.rows());
163 rtStatus.desiredJointTorque =
164 rtStatus.jacobi.transpose() * rtStatus.forceImpedance +
165 (rtStatus.I - rtStatus.jacobi.transpose() * rtStatus.jtpinv) * rtStatus.nullspaceTorque;
166
167 /// ----------------------------- write torque target -------------------------------------
168 for (int i = 0; i < rtStatus.desiredJointTorque.rows(); ++i)
169 {
170 rtStatus.desiredJointTorque(i) =
171 std::clamp(rtStatus.desiredJointTorque(i), -c.torqueLimit, c.torqueLimit);
172 }
173 }
174
175 // void
176 // TaskspaceImpedanceController::RtStatus::reset(const unsigned int nDoF)
177 // {
178 // /// This function can be called before the RT thread.
179 // /// base
180 // // jointPosition.resize(nDoF, 0.);
181 // // jointVelocity.resize(nDoF, 0.);
182 // // jointTorque.resize(nDoF, 0.);
183 // jointPosition.setZero(nDoF);
184 // jointVelocity.setZero(nDoF);
185 // jointTorque.setZero(nDoF);
186 // deltaT = 0.0;
187 // accumulateTime = 0.0;
188 // numDoF = nDoF;
189 //
190 // /// targets
191 // desiredJointTorque.setZero(nDoF);
192 // nullspaceTorque.setZero(nDoF);
193 //
194 // /// force torque
195 // currentForceTorque.setZero();
196 //
197 // /// task space variables
198 // forceImpedance.setZero();
199 //
200 // /// current status
201 // qvelFiltered.setZero(nDoF);
202 // currentPose.setZero();
203 // currentTwist.setZero();
204 // desiredPose.setZero();
205 // desiredPoseUnsafe.setZero();
206 //
207 // /// intermediate results
208 // poseDiffMatImp.setZero();
209 // poseErrorImp.setZero();
210 // oriDiffAngleAxis = Eigen::AngleAxisf::Identity();
211 //
212 // /// others
213 // jacobi.setZero(6, nDoF);
214 // jtpinv.setZero(6, nDoF);
215 // rtSafe = false;
216 // rtTargetSafe = true;
217 // }
218 //
219 // void
220 // TaskspaceImpedanceController::RtStatus::rtPreActivate(const Eigen::Matrix4f& currentTCPPose)
221 // {
222 // /// !!!! TO BE UPDATED IN PREACTIVATE !!!!
223 // /// only then the up-to-date robot joint information is available
224 // currentPose = currentTCPPose;
225 // desiredPose = currentTCPPose;
226 // accumulateTime = 0.0;
227 // }
228
229} // namespace armarx::control::common::control_law
#define M_PI
Definition MathTools.h:17
constexpr T c
void initialize(const VirtualRobot::RobotNodeSetPtr &rns, const VirtualRobot::RobotNodeSetPtr &rtRns)
common::control_law::arondto::TaskspaceImpedanceControllerConfig Config
#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...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
Eigen::MatrixXf jtpinv
pseudo inverse of the jacobi transpose [6, nDoF], for torque control
Definition common.h:118
Eigen::MatrixXf I
for computing nullspace projection
Definition common.h:124
Eigen::MatrixXf jacobi
others jacobi matrix [6, nDoF]
Definition common.h:116
Eigen::Matrix3f poseDiffMatImp
intermediate results
Definition common.h:85
Eigen::VectorXf qvelFiltered
for velocity control
Definition common.h:78
float lambda
damping term for pseudo inverse of jacobian
Definition common.h:127
Eigen::Vector6f forceImpedance
task space variables (command in operation space)
Definition common.h:74