CartesianImpedanceController.cpp
Go to the documentation of this file.
1
3
4#include <algorithm>
5
6#include <SimoxUtility/math/compare/is_equal.h>
7#include <SimoxUtility/math/convert/mat4f_to_pos.h>
8#include <SimoxUtility/math/convert/mat4f_to_quat.h>
9#include <VirtualRobot/IK/DifferentialIK.h>
10#include <VirtualRobot/IK/IKSolver.h>
11#include <VirtualRobot/MathTools.h>
12#include <VirtualRobot/Nodes/RobotNode.h>
13#include <VirtualRobot/Robot.h>
14#include <VirtualRobot/RobotNodeSet.h>
15
18
19using namespace armarx;
20
21int
23{
24 return targetJointTorques.size();
25}
26
27void
28CartesianImpedanceController::initialize(const VirtualRobot::RobotNodeSetPtr& rns)
29{
31 tcp = rns->getTCP();
33 ik.reset(new VirtualRobot::DifferentialIK(
34 rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
35
36 const auto size = rns->getSize();
37 qpos.resize(size);
38 qvel.resize(size);
39 tcptwist.resize(size);
40 nullqerror.resize(size);
41 nullspaceTorque.resize(size);
42 targetJointTorques.resize(size);
43
44 I = Eigen::MatrixXf::Identity(size, size);
45}
46
47const Eigen::VectorXf&
49 const Config& cfg,
50 std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors,
51 std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors,
52 std::vector<const SensorValue1DoFActuatorPosition*> positionSensors)
53{
55 simox::math::is_equal(bufferSize(), cfg.Knull.size())); ///TODO move this to core
56 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), cfg.Dnull.size()));
57 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), cfg.desiredJointPosition.size()));
59
60 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), torqueSensors.size()));
61 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), velocitySensors.size()));
62 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), positionSensors.size()));
63
64 const Eigen::MatrixXf jacobi = ik->getJacobianMatrix(
65 tcp, VirtualRobot::IKSolver::CartesianSelection::All); ///TODO output param version
66 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), jacobi.cols()));
67 ARMARX_CHECK_EXPRESSION(simox::math::is_equal(6, jacobi.rows()));
68 const Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(
69 jacobi.transpose(), lambda); ///TODO output param version
70
71 for (size_t i = 0; i < velocitySensors.size(); ++i)
72 {
73 qpos(i) = positionSensors[i]->position;
74 qvel(i) = velocitySensors[i]->velocity;
75 }
76
77 const Eigen::Vector6f tcptwist = jacobi * qvel;
78
79 const Eigen::Vector3f currentTCPLinearVelocity{
80 0.001f * tcptwist(0), 0.001f * tcptwist(1), 0.001f * tcptwist(2)};
81 const Eigen::Vector3f currentTCPAngularVelocity{tcptwist(3), tcptwist(4), tcptwist(5)};
82
83 const Eigen::Vector3f currentTCPPosition = tcp->getPositionInRootFrame();
84 const Eigen::Vector3f tcpForces =
85 0.001 * cfg.Kpos.cwiseProduct(cfg.desiredPosition - currentTCPPosition);
86 const Eigen::Vector3f tcpDesiredForce =
87 tcpForces - cfg.Dpos.cwiseProduct(currentTCPLinearVelocity);
88
89 const Eigen::Matrix4f currentTCPPose = tcp->getPoseInRootFrame();
90 const Eigen::Matrix3f currentRotMat = currentTCPPose.block<3, 3>(0, 0);
91 const Eigen::Matrix3f desiredMat(cfg.desiredOrientation);
92 const Eigen::Matrix3f diffMat = desiredMat * currentRotMat.inverse();
93 // const Eigen::Quaternionf cquat(currentRotMat);
94 // const Eigen::Quaternionf diffQuaternion = desiredQuaternion * cquat.conjugate();
95 // const Eigen::AngleAxisf angleAxis(diffQuaternion);
96
97 const Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
98 const Eigen::Vector3f tcpDesiredTorque =
99 cfg.Kori.cwiseProduct(rpy) - cfg.Dori.cwiseProduct(currentTCPAngularVelocity);
100 Eigen::Vector6f tcpDesiredWrench;
101 tcpDesiredWrench << 0.001 * tcpDesiredForce, tcpDesiredTorque;
102
103 // calculate desired joint torque
104 nullqerror = cfg.desiredJointPosition - qpos;
105
106 for (int i = 0; i < nullqerror.rows(); ++i)
107 {
108 if (fabs(nullqerror(i)) < 0.09)
109 {
110 nullqerror(i) = 0;
111 }
112 }
113 nullspaceTorque = cfg.Knull.cwiseProduct(nullqerror) - cfg.Dnull.cwiseProduct(qvel);
114
115 targetJointTorques =
116 jacobi.transpose() * tcpDesiredWrench + (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
117 for (int i = 0; i < targetJointTorques.size(); ++i)
118 {
119 targetJointTorques(i) =
120 std::clamp(targetJointTorques(i), -cfg.torqueLimit, cfg.torqueLimit);
121 }
122 //write debug data
123 {
124 const Eigen::Quaternionf cquat(currentRotMat);
125 dbg.errorAngle = cquat.angularDistance(cfg.desiredOrientation);
126 dbg.posiError = (cfg.desiredPosition - currentTCPPosition).norm();
127 dbg.tcpDesiredForce = tcpDesiredForce;
128 dbg.tcpDesiredTorque = tcpDesiredTorque;
129 }
130
131 return targetJointTorques;
132}
void initialize(const VirtualRobot::RobotNodeSetPtr &rns)
const Eigen::VectorXf & run(const Config &cfg, std::vector< const SensorValue1DoFActuatorTorque * > torqueSensors, std::vector< const SensorValue1DoFActuatorVelocity * > velocitySensors, std::vector< const SensorValue1DoFActuatorPosition * > positionSensors)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#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...
Quaternion< float, 0 > Quaternionf
Matrix< float, 6, 1 > Vector6f
This file offers overloads of toIce() and fromIce() functions for STL container types.
double norm(const Point &a)
Definition point.hpp:102