TaskspaceImpedanceController.cpp
Go to the documentation of this file.
2 
3 #include <fstream>
4 
5 #include <SimoxUtility/json.h>
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/MathTools.h>
12 
13 #include "../utils.h"
14 
15 
17 {
18 
19  void
20  TaskspaceImpedanceController::initialize(const VirtualRobot::RobotNodeSetPtr& rns)
21  {
23  tcp = rns->getTCP();
25  ik.reset(new VirtualRobot::DifferentialIK(
26  rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
27 
28  numOfJoints = rns->getSize();
29  I = Eigen::MatrixXf::Identity(numOfJoints, numOfJoints);
30  }
31 
32 
33  void
34  TaskspaceImpedanceController::preactivateInit(const VirtualRobot::RobotNodeSetPtr& rns)
35  {
36  ARMARX_INFO << "preactivate control law TaskspaceImpedanceController";
37  Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
38  {
39  NonRtStatus s;
40 
41  s.qpos = rns->getJointValuesEigen();
42  s.qvel.setZero(numOfJoints);
43 
44  s.currentPose = currentPose;
45  s.currentTwist.setZero();
46 
47  s.desiredPose = currentPose;
48  s.desiredTwist.setZero();
49 
50  s.jacobi.setZero(6, numOfJoints);
51  s.jtpinv.setZero(6, numOfJoints);
52 
53  bufferNonRtToRt.reinitAllBuffers(s);
54  bufferNonRtToOnPublish.reinitAllBuffers(s);
55  bufferNonRtToUser.reinitAllBuffers(s);
56  }
57 
58  {
59  RtStatus s;
60  s.desiredJointTorques.setZero(numOfJoints);
61  s.desiredPose = currentPose;
62  s.forceImpedance.setZero();
63  bufferRtToOnPublish.reinitAllBuffers(s);
64  }
65  ARMARX_INFO << "preactivation done";
66  }
67 
69  {
70  auto& sRt = bufferRtToOnPublish.getWriteBuffer();
71  auto& sNoneRt = bufferNonRtToRt.getUpToDateReadBuffer();
72  sRt.desiredPose = sNoneRt.currentPose;
73  sRt.forceImpedance.setZero();
74  sRt.desiredJointTorques.setZero();
75  bufferRtToOnPublish.commitWrite();
76  }
77 
78 
79  bool
81  const Config& cfg,
82  const RobotStatus& robotStatus)
83  {
84  auto& s = bufferNonRtToRt.getWriteBuffer();
85 
86  /// check size and value
87  {
88  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, robotStatus.jointPosition.size());
89  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, robotStatus.jointVelocity.size());
90  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, robotStatus.jointTorque.size());
91  }
92 
93  /// ----------------------------- get current status of robot ---------------------------------------------
94  /// original data in ArmarX use the following units:
95  /// position in mm,
96  /// joint angles and orientation in radian,
97  /// velocity in mm/s and radian/s, etc.
98  /// here we convert mm to m, if you use MP from outside, make sure to convert it back to mm
99 
100  s.currentPose = tcp->getPoseInRootFrame();
101  s.jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
102  s.jacobi.block(0, 0, 3, numOfJoints) = 0.001 * s.jacobi.block(0, 0, 3, numOfJoints);
103  ARMARX_CHECK_EQUAL(numOfJoints, s.jacobi.cols());
104  ARMARX_CHECK_EQUAL(6, s.jacobi.rows());
105 
106  s.jtpinv = ik->computePseudoInverseJacobianMatrix(s.jacobi.transpose(), lambda);
107  ARMARX_CHECK_EQUAL(numOfJoints, s.jtpinv.cols());
108  ARMARX_CHECK_EQUAL(6, s.jtpinv.rows());
109 
110  Eigen::VectorXf qvelRaw(numOfJoints);
111  for (size_t i = 0; i < robotStatus.jointVelocity.size(); ++i)
112  {
113  s.qpos(i) = robotStatus.jointPosition[i];
114  qvelRaw(i) = robotStatus.jointVelocity[i];
115  }
116  ARMARX_CHECK_EQUAL(s.qvel.rows(), qvelRaw.rows());
117 
118  s.qvel = (1 - cfg.qvelFilter) * s.qvel + cfg.qvelFilter * qvelRaw;
119  s.currentTwist = s.jacobi * s.qvel;
120 
121  s.desiredPose = cfg.desiredPose;
122  s.desiredTwist = cfg.desiredTwist;
123 
124  bufferNonRtToOnPublish.getWriteBuffer() = s;
125  bufferNonRtToOnPublish.commitWrite();
126  bufferNonRtToUser.getWriteBuffer() = s;
127  bufferNonRtToUser.commitWrite();
128  bufferNonRtToRt.commitWrite();
129 
130  isInitialized.store(true);
131  return true;
132  }
133 
134  void
136  const Config& c,
137  ControlTarget& targets)
138  {
139  /// run in rt thread
140 
141  auto& sRt = bufferRtToOnPublish.getWriteBuffer();
142  const auto& s = bufferNonRtToRt.getUpToDateReadBuffer();
143 
144  if (isInitialized.load())
145  {
146  if ((sRt.desiredPose.block<3, 1>(0, 3) - s.desiredPose.block<3, 1>(0, 3)).norm() > 100.0f)
147  {
148  ARMARX_RT_LOGF_WARN("new target is too far away from the current target");
149 // ARMARX_RT_LOGF_WARN("new target \n\n [%f, %f, %f]\n\nis too far away from the current target\n\n [%f, %, %s]",
150 // c.desiredPose(0, 3), c.desiredPose(1, 3), c.desiredPose(2, 3),
151 // sRt.desiredPose(0, 3), sRt.desiredPose(1, 3), sRt.desiredPose(2, 3));
152  }
153  else
154  {
155  sRt.desiredPose = s.desiredPose;
156  }
157  }
158 
159  /// ----------------------------- Impedance control ---------------------------------------------
160  /// calculate pose error between target pose and current pose
161  /// !!! This is very important: you have to keep postion and orientation both
162  /// with UI unit (meter, radian) to calculate impedance force.
163 
164  Eigen::Matrix3f diffMat =
165  sRt.desiredPose.block<3, 3>(0, 0) * s.currentPose.block<3, 3>(0, 0).transpose();
166  Eigen::Vector6f poseErrorImp;
167  poseErrorImp.head(3) = 0.001 * (sRt.desiredPose.block<3, 1>(0, 3) - s.currentPose.block<3, 1>(0, 3));
168  poseErrorImp.tail(3) = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
169  sRt.forceImpedance =
170  c.kpImpedance.cwiseProduct(poseErrorImp) -
171  c.kdImpedance.cwiseProduct(s.currentTwist);
172 
173  /// ----------------------------- Nullspace PD Control --------------------------------------------------
174  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, c.kpNullspace.rows());
175  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, s.qpos.rows());
176  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, s.qvel.rows());
177 
178  Eigen::VectorXf nullspaceTorque =
179  c.kpNullspace.cwiseProduct(c.desiredNullspaceJointAngles.value() - s.qpos) -
180  c.kdNullspace.cwiseProduct(s.qvel);
181 
182  /// ----------------------------- Map TS target force to JS --------------------------------------------------
183  ARMARX_CHECK_EQUAL((unsigned)6, s.jacobi.rows());
184  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, s.jacobi.cols());
185 
186  ARMARX_CHECK_EQUAL((unsigned)6, s.jtpinv.rows());
187  ARMARX_CHECK_EQUAL((unsigned)numOfJoints, s.jtpinv.cols());
188 
189  sRt.desiredJointTorques =
190  s.jacobi.transpose() * sRt.forceImpedance +
191  (I - s.jacobi.transpose() * s.jtpinv) * nullspaceTorque;
192 
193  /// ----------------------------- write torque target --------------------------------------------------
194  for (size_t i = 0; i < (unsigned)sRt.desiredJointTorques.rows(); ++i)
195  {
196  sRt.desiredJointTorques(i) = std::clamp(sRt.desiredJointTorques(i), -c.torqueLimit, c.torqueLimit);
197  targets.targets.at(i) = sRt.desiredJointTorques(i);
198  }
199 
200  bufferRtToOnPublish.commitWrite();
201  }
202 } /// namespace armarx::control::common::control_law
armarx::control::common::control_law::TaskspaceImpedanceController::Config::desiredPose
Eigen::Matrix4f desiredPose
Definition: TaskspaceImpedanceController.h:50
armarx::control::common::control_law::ControlTarget::targets
std::vector< float > targets
Definition: common.h:46
armarx::control::common::control_law::TaskspaceImpedanceController::isInitialized
std::atomic< bool > isInitialized
Definition: TaskspaceImpedanceController.h:116
TaskspaceImpedanceController.h
armarx::control::common::control_law::RobotStatus::jointTorque
std::vector< float > jointTorque
Definition: common.h:34
ARMARX_CHECK_NOT_NULL
#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...
Definition: ExpressionException.h:206
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::control::common::control_law::TaskspaceImpedanceController::NonRtStatus
Definition: TaskspaceImpedanceController.h:69
armarx::control::common::control_law::TaskspaceImpedanceController::Config::qvelFilter
float qvelFilter
Definition: TaskspaceImpedanceController.h:55
armarx::control::common::control_law::RobotStatus::jointVelocity
std::vector< float > jointVelocity
Definition: common.h:33
armarx::control::common::control_law::TaskspaceImpedanceController::preactivateInit
void preactivateInit(const VirtualRobot::RobotNodeSetPtr &rns)
Definition: TaskspaceImpedanceController.cpp:34
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:125
armarx::control::common::control_law::TaskspaceImpedanceController::bufferNonRtToUser
TripleBuffer< NonRtStatus > bufferNonRtToUser
Definition: TaskspaceImpedanceController.h:103
armarx::control::common::control_law::TaskspaceImpedanceController::updateControlStatus
bool updateControlStatus(const Config &cfg, const RobotStatus &robotStatus)
Definition: TaskspaceImpedanceController.cpp:80
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::control::common::control_law::RobotStatus
Definition: common.h:30
armarx::control::common::control_law
namespace armarx::control::common::ft
Definition: aron_conversions.cpp:62
armarx::control::common::control_law::TaskspaceImpedanceController::bufferRtToOnPublish
TripleBuffer< RtStatus > bufferRtToOnPublish
Definition: TaskspaceImpedanceController.h:99
armarx::control::common::control_law::TaskspaceImpedanceController::bufferNonRtToRt
TripleBuffer< NonRtStatus > bufferNonRtToRt
Definition: TaskspaceImpedanceController.h:101
armarx::control::common::control_law::RobotStatus::jointPosition
std::vector< float > jointPosition
Definition: common.h:32
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::control::common::control_law::TaskspaceImpedanceController::run
void run(const Config &cfg, ControlTarget &targets)
Definition: TaskspaceImpedanceController.cpp:135
armarx::control::common::control_law::TaskspaceImpedanceController::tcp
VirtualRobot::RobotNodePtr tcp
Definition: TaskspaceImpedanceController.h:105
armarx::control::common::control_law::TaskspaceImpedanceController::Config::desiredTwist
Eigen::Vector6f desiredTwist
Definition: TaskspaceImpedanceController.h:51
armarx::control::common::control_law::TaskspaceImpedanceController::bufferNonRtToOnPublish
TripleBuffer< NonRtStatus > bufferNonRtToOnPublish
Definition: TaskspaceImpedanceController.h:102
Eigen::Matrix< float, 6, 1 >
ControlThreadOutputBuffer.h
armarx::control::common::control_law::TaskspaceImpedanceController::firstRun
void firstRun()
Definition: TaskspaceImpedanceController.cpp:68
ARMARX_CHECK_EQUAL
#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...
Definition: ExpressionException.h:130
armarx::control::common::control_law::TaskspaceImpedanceController::RtStatus
internal status of the controller, containing intermediate variables, mutable targets
Definition: TaskspaceImpedanceController.h:59
ARMARX_RT_LOGF_WARN
#define ARMARX_RT_LOGF_WARN(...)
Definition: ControlThreadOutputBuffer.h:345
ArmarXDataPath.h
armarx::control::common::control_law::ControlTarget
Definition: common.h:44
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::control::common::control_law::TaskspaceImpedanceController::Config
you can set the following values from outside of the rt controller via Ice interfaces
Definition: TaskspaceImpedanceController.h:42
armarx::control::common::control_law::TaskspaceImpedanceController::initialize
void initialize(const VirtualRobot::RobotNodeSetPtr &rns)
Definition: TaskspaceImpedanceController.cpp:20