TaskspaceAdmittanceController.cpp
Go to the documentation of this file.
2
3#include <SimoxUtility/math/convert/mat4f_to_quat.h>
4#include <VirtualRobot/IK/DifferentialIK.h>
5#include <VirtualRobot/IK/JacobiProvider.h>
6#include <VirtualRobot/MathTools.h>
7#include <VirtualRobot/Nodes/RobotNode.h>
8#include <VirtualRobot/Robot.h>
9#include <VirtualRobot/RobotNodeSet.h>
10
14
16
17#include "../utils.h"
18
20{
21
22 void
23 TaskspaceAdmittanceController::initialize(const VirtualRobot::RobotNodeSetPtr& rns,
24 const VirtualRobot::RobotNodeSetPtr& rtRns)
25 {
27 tcp = rns->getTCP();
28 rtTCP = rtRns->getTCP();
30 ik.reset(new VirtualRobot::DifferentialIK(
31 rtRns, rtRns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
32
33 // auto numOfJoints = rns->getSize();
34 // I = Eigen::MatrixXf::Identity(numOfJoints, numOfJoints);
35 }
36
37 void
38 TaskspaceAdmittanceController::preactivateInit(const VirtualRobot::RobotNodeSetPtr& rns)
39 {
40 }
41
42 void
47
48 // void
49 // TaskspaceAdmittanceController::updateFT(const FTConfig& c, RtStatus& rtStatus)
50 // {
51 // /// run in rt thread
52 // ftsensor.updateStatus();
53 // if (c.reCalibrate)
54 // {
55 // ftsensor.calibrated.store(false);
56 // /// TODO how to toggle recalibration?
57 // }
58 // ftsensor.compensateTCPGravity(c);
59 // if (!ftsensor.calibrated.load())
60 // {
61 // if (ftsensor.calibrate(c, rtStatus.deltaT))
62 // {
63 // ftsensor.calibrated.store(true);
64 // }
65 // }
66 // else
67 // {
68 // rtStatus.currentForceTorque = ftsensor.getFilteredForceTorque(c);
69 // }
70 // }
71
72 void
74 {
75 /// run in rt thread
76 rtStatus.currentPose = rtTCP->getPoseInRootFrame();
77
78 /// ---------------------------- safety guard by FT and target pose ------------------------
79 rtStatus.poseDiffMatImp =
80 c.desiredPose.block<3, 3>(0, 0) * rtStatus.currentPose.block<3, 3>(0, 0).transpose();
81 rtStatus.oriDiffAngleAxis.fromRotationMatrix(rtStatus.poseDiffMatImp);
82
83 /// this should not be moved to non rt, just in case non rt thread dies, rt still functions as safely
84 if (not ftsensor.isSafe(c.ftConfig))
85 {
86 ARMARX_INFO << "FTGuard indicates RT not safe";
87 c.desiredPose = rtStatus.desiredPose;
88 rtStatus.rtSafe = false;
89 rtStatus.rtTargetSafe = true;
90 }
91 else if (ftsensor.calibrated.load())
92 {
93 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 c.desiredPose = rtStatus.desiredPose;
100 rtStatus.rtSafe = false;
101 rtStatus.rtTargetSafe = false;
102 }
103 else
104 {
105 rtStatus.desiredPose = c.desiredPose;
106 rtStatus.rtSafe = true;
107 rtStatus.rtTargetSafe = true;
108 }
109 }
110 else
111 {
112 ARMARX_RT_LOGF_WARN("not initialized or ft sensor not calibrated!");
113 c.desiredTwist.setZero();
114 c.kmAdmittance.setZero();
115 }
116
117 auto nDoF = static_cast<Eigen::Index>(rtStatus.nDoF);
118
119 /// ------------------------------ compute jacobi ------------------------------------------
120 rtStatus.jacobi =
121 ik->getJacobianMatrix(rtTCP, VirtualRobot::IKSolver::CartesianSelection::All);
122 rtStatus.jacobi.block(0, 0, 3, rtStatus.nDoF) =
123 0.001 * rtStatus.jacobi.block(0, 0, 3, rtStatus.nDoF);
124 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jacobi.cols());
125 ARMARX_CHECK_EQUAL(6, rtStatus.jacobi.rows());
126
127 rtStatus.jtpinv =
128 ik->computePseudoInverseJacobianMatrix(rtStatus.jacobi.transpose(), rtStatus.lambda);
129 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jtpinv.cols());
130 ARMARX_CHECK_EQUAL(6, rtStatus.jtpinv.rows());
131
132 /// ------------------------------ update velocity/twist -----------------------------------
133 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jointPosition.rows());
134 ARMARX_CHECK_EQUAL(nDoF, rtStatus.jointVelocity.rows());
135 ARMARX_CHECK_EQUAL(nDoF, rtStatus.qvelFiltered.rows());
136
137 rtStatus.qvelFiltered =
138 (1 - c.qvelFilter) * rtStatus.qvelFiltered + c.qvelFilter * rtStatus.jointVelocity;
139 rtStatus.currentTwist = rtStatus.jacobi * rtStatus.qvelFiltered;
140
141 /// ---------------------------- admittance control ---------------------------------------------
142 /// calculate pose error between the virtual pose and the target pose
143 rtStatus.poseDiffMatAdm = rtStatus.virtualPose.block<3, 3>(0, 0) *
144 rtStatus.desiredPose.block<3, 3>(0, 0).transpose();
145 rtStatus.poseErrorAdm.head<3>() =
146 rtStatus.virtualPose.block<3, 1>(0, 3) - rtStatus.desiredPose.block<3, 1>(0, 3);
147 rtStatus.poseErrorAdm.tail<3>() =
148 VirtualRobot::MathTools::eigen3f2rpy(rtStatus.poseDiffMatAdm);
149
150 /// admittance control law and Euler Integration -> virtual pose
151 rtStatus.acc = c.kmAdmittance.cwiseProduct(rtStatus.currentForceTorque) -
152 c.kpAdmittance.cwiseProduct(rtStatus.poseErrorAdm) -
153 c.kdAdmittance.cwiseProduct(rtStatus.virtualVel);
154
155 rtStatus.vel =
156 rtStatus.virtualVel + 0.5 * rtStatus.deltaT * (rtStatus.acc + rtStatus.virtualAcc);
157 rtStatus.pos = 0.5 * rtStatus.deltaT * (rtStatus.vel + rtStatus.virtualVel);
158 rtStatus.virtualAcc = rtStatus.acc;
159 rtStatus.virtualVel = rtStatus.vel;
160
161 rtStatus.virtualPose.block<3, 1>(0, 3) += rtStatus.pos.head<3>();
162 rtStatus.virtualPose.block<3, 3>(0, 0) =
163 VirtualRobot::MathTools::rpy2eigen3f(
164 rtStatus.pos(3), rtStatus.pos(4), rtStatus.pos(5)) *
165 rtStatus.virtualPose.block<3, 3>(0, 0);
166
167 /// ------------------------------------- Impedance control --------------------------------
168 /// calculate pose error between target pose and current pose
169 /// !!! This is very important: you have to keep postion and orientation both
170 /// with UI unit (meter, radian) to calculate impedance force.
171
172 rtStatus.poseDiffMatImp = rtStatus.desiredPose.block<3, 3>(0, 0) *
173 rtStatus.currentPose.block<3, 3>(0, 0).transpose();
174 rtStatus.poseErrorImp.head<3>() = 0.001 * (rtStatus.desiredPose.block<3, 1>(0, 3) -
175 rtStatus.currentPose.block<3, 1>(0, 3));
176 rtStatus.poseErrorImp.tail<3>() =
177 VirtualRobot::MathTools::eigen3f2rpy(rtStatus.poseDiffMatImp);
178
179 rtStatus.forceImpedance = c.kpImpedance.cwiseProduct(rtStatus.poseErrorImp) -
180 c.kdImpedance.cwiseProduct(rtStatus.currentTwist);
181
182 /// ----------------------------- Nullspace PD Control -------------------------------------
183 ARMARX_CHECK_EQUAL(nDoF, c.kpNullspaceTorque.rows());
184 ARMARX_CHECK_EQUAL(nDoF, rtStatus.nullspaceTorque.rows());
185 ARMARX_CHECK_EQUAL(nDoF, c.desiredNullspaceJointAngles.value().size());
186 rtStatus.nullspaceTorque =
187 c.kpNullspaceTorque.cwiseProduct(c.desiredNullspaceJointAngles.value() - rtStatus.jointPosition) -
188 c.kdNullspaceTorque.cwiseProduct(rtStatus.qvelFiltered);
189
190 /// ----------------------------- Map TS target force to JS --------------------------------
191 ARMARX_CHECK_EQUAL(nDoF, rtStatus.desiredJointTorque.rows());
192 rtStatus.desiredJointTorque =
193 rtStatus.jacobi.transpose() * rtStatus.forceImpedance +
194 (rtStatus.I - rtStatus.jacobi.transpose() * rtStatus.jtpinv) * rtStatus.nullspaceTorque;
195
196 /// ----------------------------- write torque target -------------------------------------
197 for (int i = 0; i < rtStatus.desiredJointTorque.rows(); ++i)
198 {
199 rtStatus.desiredJointTorque(i) =
200 std::clamp(rtStatus.desiredJointTorque(i), -c.torqueLimit, c.torqueLimit);
201 }
202 }
203
204 // void
205 // TaskspaceAdmittanceController::RtStatus::reset(const unsigned int nDoF)
206 // {
207 // /// This function can be called before the RT thread.
208 // /// base
209 // jointPosition.setZero(nDoF);
210 // jointVelocity.setZero(nDoF);
211 // jointTorque.setZero(nDoF);
212 // deltaT = 0.0;
213 // accumulateTime = 0.0;
214 // nDoF = nDoF;
215 //
216 // /// targets
217 // desiredJointTorque.setZero(nDoF);
218 // nullspaceTorque.setZero(nDoF);
219 //
220 // /// force torque
221 // currentForceTorque.setZero();
222 //
223 // /// task space variables
224 // forceImpedance.setZero();
225 //
226 // /// current status
227 // qvelFiltered.setZero(nDoF);
228 // currentPose.setZero();
229 // currentTwist.setZero();
230 // desiredPose.setZero();
231 //
232 // /// virtual status
233 // virtualPose.setZero();
234 // virtualVel.setZero();
235 // virtualAcc.setZero();
236 //
237 // /// intermediate results
238 // poseDiffMatImp.setZero();
239 // poseDiffMatAdm.setZero();
240 // poseErrorImp.setZero();
241 // poseErrorAdm.setZero();
242 // oriDiffAngleAxis = Eigen::AngleAxisf::Identity();
243 // ARMARX_INFO << "------ " << VAROUT(oriDiffAngleAxis.angle());
244 //
245 // /// others
246 // jacobi.setZero(6, nDoF);
247 // jtpinv.setZero(6, nDoF);
248 // rtSafe = false;
249 // rtTargetSafe = true;
250 // }
251 //
252 // void
253 // TaskspaceAdmittanceController::RtStatus::rtPreActivate(const Eigen::Matrix4f& currentTCPPose)
254 // {
255 // /// !!!! TO BE UPDATED IN PREACTIVATE !!!!
256 // /// only then the up-to-date robot joint information is available
257 // currentPose = currentTCPPose;
258 // desiredPose = currentTCPPose;
259 // accumulateTime = 0.0;
260 // }
261
262} // namespace armarx::control::common::control_law
#define ARMARX_RT_LOGF_WARN(...)
#define M_PI
Definition MathTools.h:17
constexpr T c
void initialize(const VirtualRobot::RobotNodeSetPtr &rns, const VirtualRobot::RobotNodeSetPtr &rtRns)
common::control_law::arondto::TaskspaceAdmittanceControllerConfig 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::Matrix3f poseDiffMatAdm
intermediate results for admittance controller
Definition common.h:90
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
Eigen::Vector6f currentForceTorque
force torque
Definition common.h:70