orocos_kdl
chainexternalwrenchestimator.cpp
Go to the documentation of this file.
1 // Copyright (C) 2021 Djordje Vukcevic <djordje dot vukcevic at h-brs dot de>
2 
3 // Version: 1.0
4 // Author: Djordje Vukcevic <djordje dot vukcevic at h-brs dot de>
5 // URL: http://www.orocos.org/kdl
6 
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 
22 
23 namespace KDL {
24 
25 ChainExternalWrenchEstimator::ChainExternalWrenchEstimator(const Chain &chain, const Vector &gravity, const double sample_frequency, const double estimation_gain, const double filter_constant, const double eps, const int maxiter) :
26  CHAIN(chain),
27  DT_SEC(1.0 / sample_frequency), FILTER_CONST(filter_constant),
28  svd_eps(eps),
29  svd_maxiter(maxiter),
30  nj(CHAIN.getNrOfJoints()), ns(CHAIN.getNrOfSegments()),
31  jnt_mass_matrix(nj), previous_jnt_mass_matrix(nj), jnt_mass_matrix_dot(nj),
32  initial_jnt_momentum(nj), estimated_momentum_integral(nj), filtered_estimated_ext_torque(nj),
33  gravity_torque(nj), coriolis_torque(nj), total_torque(nj), estimated_ext_torque(nj),
34  jacobian_end_eff(nj),
35  jacobian_end_eff_transpose(Eigen::MatrixXd::Zero(nj, 6)), jacobian_end_eff_transpose_inv(Eigen::MatrixXd::Zero(6, nj)),
36  U(Eigen::MatrixXd::Zero(nj, 6)), V(Eigen::MatrixXd::Zero(6, 6)),
37  S(Eigen::VectorXd::Zero(6)), S_inv(Eigen::VectorXd::Zero(6)), tmp(Eigen::VectorXd::Zero(6)),
38  ESTIMATION_GAIN(Eigen::VectorXd::Constant(nj, estimation_gain)),
39  dynparam_solver(CHAIN, gravity),
40  jacobian_solver(CHAIN),
41  fk_pos_solver(CHAIN)
42 {
43 }
44 
46 {
49  jnt_mass_matrix.resize(nj);
51  jnt_mass_matrix_dot.resize(nj);
60  jacobian_end_eff_transpose.conservativeResizeLike(Eigen::MatrixXd::Zero(nj, 6));
61  jacobian_end_eff_transpose_inv.conservativeResizeLike(Eigen::MatrixXd::Zero(6, nj));
62  U.conservativeResizeLike(Eigen::MatrixXd::Zero(nj, 6));
63  V.conservativeResizeLike(Eigen::MatrixXd::Zero(6, 6));
64  S.conservativeResizeLike(Eigen::VectorXd::Zero(6));
65  S_inv.conservativeResizeLike(Eigen::VectorXd::Zero(6));
66  tmp.conservativeResizeLike(Eigen::VectorXd::Zero(6));
67  ESTIMATION_GAIN.conservativeResizeLike(Eigen::VectorXd::Constant(nj, ESTIMATION_GAIN(0)));
71 }
72 
73 // Calculates robot's initial momentum in the joint space. If this method is not called by the user, zero values will be taken for the initial momentum.
74 int ChainExternalWrenchEstimator::setInitialMomentum(const JntArray &joint_position, const JntArray &joint_velocity)
75 {
76  // Check sizes first
77  if (joint_position.rows() != nj || joint_velocity.rows() != nj)
78  return (error = E_SIZE_MISMATCH);
79 
80  // Calculate robot's inertia and momentum in the joint space
81  if (E_NOERROR != dynparam_solver.JntToMass(joint_position, jnt_mass_matrix))
83 
84  initial_jnt_momentum.data = jnt_mass_matrix.data * joint_velocity.data;
85 
86  // Reset data because of the new momentum offset
89 
90  return (error = E_NOERROR);
91 }
92 
93 // Sets singular-value eps parameter for the SVD calculation
94 void ChainExternalWrenchEstimator::setSVDEps(const double eps_in)
95 {
96  svd_eps = eps_in;
97 }
98 
99 // Sets maximum iteration parameter for the SVD calculation
101 {
102  svd_maxiter = maxiter_in;
103 }
104 
105 // This method calculates the external wrench that is applied on the robot's end-effector.
106 int ChainExternalWrenchEstimator::JntToExtWrench(const JntArray &joint_position, const JntArray &joint_velocity, const JntArray &joint_torque, Wrench &external_wrench)
107 {
117  // Check sizes first
118  if (nj != CHAIN.getNrOfJoints() || ns != CHAIN.getNrOfSegments())
119  return (error = E_NOT_UP_TO_DATE);
120  if (joint_position.rows() != nj || joint_velocity.rows() != nj || joint_torque.rows() != nj)
121  return (error = E_SIZE_MISMATCH);
122 
129  // Calculate decomposed robot's dynamics
130  if (E_NOERROR != dynparam_solver.JntToMass(joint_position, jnt_mass_matrix))
132 
133  if (E_NOERROR != dynparam_solver.JntToCoriolis(joint_position, joint_velocity, coriolis_torque))
135 
136  if (E_NOERROR != dynparam_solver.JntToGravity(joint_position, gravity_torque))
138 
139  // Calculate the change of robot's inertia in the joint space
141 
142  // Save data for the next iteration
144 
145  // Calculate total torque exerted on the joint
146  total_torque.data = joint_torque.data - gravity_torque.data - coriolis_torque.data + jnt_mass_matrix_dot.data * joint_velocity.data;
147 
148  // Accumulate main integral
150 
151  // Estimate external joint torque
153 
154  // First order low-pass filter: filter out the noise from the estimated signal
155  // This filter can be turned off by setting FILTER_CONST value to 0
157 
164  // Compute robot's end-effector frame, expressed in the base frame
165  Frame end_eff_frame;
166  if (E_NOERROR != fk_pos_solver.JntToCart(joint_position, end_eff_frame))
167  return (error = E_FKSOLVERPOS_FAILED);
168 
169  // Compute robot's jacobian for the end-effector frame, expressed in the base frame
170  if (E_NOERROR != jacobian_solver.JntToJac(joint_position, jacobian_end_eff))
171  return (error = E_JACSOLVER_FAILED);
172 
173  // Transform the jacobian from the base frame to the end-effector frame.
174  // This part can be commented out if the user wants estimated wrench to be expressed w.r.t. base frame
175  jacobian_end_eff.changeBase(end_eff_frame.M.Inverse()); // Jacobian is now expressed w.r.t. end-effector frame
176 
177  // SVD of "Jac^T" with maximum iterations "maxiter": Jac^T = U * S^-1 * V^T
180  return (error = E_SVD_FAILED);
181 
182  // Invert singular values: S^-1
183  for (int i = 0; i < S.size(); ++i)
184  S_inv(i) = (std::fabs(S(i)) < svd_eps) ? 0.0 : 1.0 / S(i);
185 
186  // Compose the inverse: (Jac^T)^-1 = V * S^-1 * U^T
187  jacobian_end_eff_transpose_inv = V * S_inv.asDiagonal() * U.adjoint();
188 
189  // Compute end-effector's Cartesian wrench from the estimated joint torques: (Jac^T)^-1 * ext_tau
191  for (int i = 0; i < 6; i++)
192  external_wrench(i) = estimated_wrench(i);
193 
194  return (error = E_NOERROR);
195 }
196 
197 // Getter for the torques felt in the robot's joints due to the external wrench being applied on the robot
199 {
200  assert(external_joint_torque.rows() == filtered_estimated_ext_torque.rows());
201  external_joint_torque = filtered_estimated_ext_torque;
202 }
203 
204 const char* ChainExternalWrenchEstimator::strError(const int error) const
205 {
206  if (E_FKSOLVERPOS_FAILED == error) return "Internally-used Forward Position Kinematics (Recursive) solver failed";
207  else if (E_JACSOLVER_FAILED == error) return "Internally-used Jacobian solver failed";
208  else if (E_DYNPARAMSOLVERMASS_FAILED == error) return "Internally-used Dynamics Parameters (Mass) solver failed";
209  else if (E_DYNPARAMSOLVERCORIOLIS_FAILED == error) return "Internally-used Dynamics Parameters (Coriolis) solver failed";
210  else if (E_DYNPARAMSOLVERGRAVITY_FAILED == error) return "Internally-used Dynamics Parameters (Gravity) solver failed";
211  else return SolverI::strError(error);
212 }
213 
214 } // namespace
chainexternalwrenchestimator.hpp
KDL::ChainExternalWrenchEstimator::E_DYNPARAMSOLVERCORIOLIS_FAILED
static const int E_DYNPARAMSOLVERCORIOLIS_FAILED
Internally-used Dynamics Parameters (Mass) solver failed.
Definition: chainexternalwrenchestimator.hpp:52
KDL::SolverI::strError
virtual const char * strError(const int error) const
Definition: solveri.hpp:125
KDL::ChainExternalWrenchEstimator::coriolis_torque
JntArray coriolis_torque
Definition: chainexternalwrenchestimator.hpp:118
KDL::ChainExternalWrenchEstimator::E_JACSOLVER_FAILED
static const int E_JACSOLVER_FAILED
Internally-used Forward Position Kinematics (Recursive) solver failed.
Definition: chainexternalwrenchestimator.hpp:50
KDL::JntArray
Definition: jntarray.hpp:69
std::fabs
T fabs(T... args)
KDL::Jacobian::changeBase
friend bool changeBase(const Jacobian &src1, const Rotation &rot, Jacobian &dest)
Definition: jacobian.cpp:103
KDL::ChainExternalWrenchEstimator::svd_eps
double svd_eps
Definition: chainexternalwrenchestimator.hpp:113
KDL::ChainDynParam::updateInternalDataStructures
virtual void updateInternalDataStructures()
Definition: chaindynparam.cpp:46
KDL::ChainExternalWrenchEstimator::V
Eigen::MatrixXd V
Definition: chainexternalwrenchestimator.hpp:120
KDL::JntArray::resize
void resize(unsigned int newSize)
Definition: jntarray.cpp:53
KDL::svd_eigen_HH
int svd_eigen_HH(const Eigen::MatrixXd &A, Eigen::MatrixXd &U, Eigen::VectorXd &S, Eigen::MatrixXd &V, Eigen::VectorXd &tmp, int maxiter, double epsilon)
Definition: svd_eigen_HH.cpp:26
KDL::ChainExternalWrenchEstimator::CHAIN
const Chain & CHAIN
Definition: chainexternalwrenchestimator.hpp:111
KDL::ChainExternalWrenchEstimator::initial_jnt_momentum
JntArray initial_jnt_momentum
Definition: chainexternalwrenchestimator.hpp:117
KDL::ChainExternalWrenchEstimator::estimated_ext_torque
JntArray estimated_ext_torque
Definition: chainexternalwrenchestimator.hpp:118
KDL::SolverI::E_NOT_UP_TO_DATE
@ E_NOT_UP_TO_DATE
Chain size changed.
Definition: solveri.hpp:97
KDL::ChainExternalWrenchEstimator::jacobian_end_eff
Jacobian jacobian_end_eff
Definition: chainexternalwrenchestimator.hpp:119
KDL::ChainExternalWrenchEstimator::gravity_torque
JntArray gravity_torque
Definition: chainexternalwrenchestimator.hpp:118
KDL::ChainExternalWrenchEstimator::jacobian_solver
ChainJntToJacSolver jacobian_solver
Definition: chainexternalwrenchestimator.hpp:123
KDL::ChainExternalWrenchEstimator::JntToExtWrench
int JntToExtWrench(const JntArray &joint_position, const JntArray &joint_velocity, const JntArray &joint_torque, Wrench &external_wrench)
Definition: chainexternalwrenchestimator.cpp:106
KDL::ChainJntToJacSolver::JntToJac
virtual int JntToJac(const JntArray &q_in, Jacobian &jac, int seg_nr=-1)
Definition: chainjnttojacsolver.cpp:48
KDL
Definition: kukaLWR_DHnew.cpp:25
KDL::Chain::getNrOfSegments
unsigned int getNrOfSegments() const
Definition: chain.hpp:76
KDL::ChainExternalWrenchEstimator::jacobian_end_eff_transpose_inv
Eigen::MatrixXd jacobian_end_eff_transpose_inv
Definition: chainexternalwrenchestimator.hpp:120
KDL::ChainExternalWrenchEstimator::fk_pos_solver
ChainFkSolverPos_recursive fk_pos_solver
Definition: chainexternalwrenchestimator.hpp:124
KDL::Vector
A concrete implementation of a 3 dimensional vector class.
Definition: frames.hpp:162
KDL::ChainExternalWrenchEstimator::S
Eigen::VectorXd S
Definition: chainexternalwrenchestimator.hpp:121
KDL::Jacobian::resize
void resize(unsigned int newNrOfColumns)
Allocates memory for new size (can break realtime behavior)
Definition: jacobian.cpp:54
KDL::ChainExternalWrenchEstimator::setSVDEps
void setSVDEps(const double eps_in)
Definition: chainexternalwrenchestimator.cpp:94
KDL::JntArray::rows
unsigned int rows() const
Definition: jntarray.cpp:70
KDL::SolverI::E_SIZE_MISMATCH
@ E_SIZE_MISMATCH
Input size does not match internal state.
Definition: solveri.hpp:99
KDL::SolverI::E_SVD_FAILED
@ E_SVD_FAILED
Internal svd calculation failed.
Definition: solveri.hpp:107
KDL::Wrench
represents both translational and rotational acceleration.
Definition: frames.hpp:881
KDL::ChainExternalWrenchEstimator::svd_maxiter
int svd_maxiter
Definition: chainexternalwrenchestimator.hpp:114
KDL::ChainExternalWrenchEstimator::E_DYNPARAMSOLVERMASS_FAILED
static const int E_DYNPARAMSOLVERMASS_FAILED
Internally-used Jacobian solver failed.
Definition: chainexternalwrenchestimator.hpp:51
KDL::ChainExternalWrenchEstimator::total_torque
JntArray total_torque
Definition: chainexternalwrenchestimator.hpp:118
KDL::Frame
represents a frame transformation in 3D space (rotation + translation)
Definition: frames.hpp:572
KDL::ChainDynParam::JntToMass
virtual int JntToMass(const JntArray &q, JntSpaceInertiaMatrix &H)
Definition: chaindynparam.cpp:60
KDL::ChainExternalWrenchEstimator::filtered_estimated_ext_torque
JntArray filtered_estimated_ext_torque
Definition: chainexternalwrenchestimator.hpp:117
KDL::ChainExternalWrenchEstimator::FILTER_CONST
const double FILTER_CONST
Definition: chainexternalwrenchestimator.hpp:112
KDL::ChainFkSolverPos_recursive::JntToCart
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr=-1)
Definition: chainfksolverpos_recursive.cpp:34
KDL::ChainExternalWrenchEstimator::updateInternalDataStructures
virtual void updateInternalDataStructures()
Definition: chainexternalwrenchestimator.cpp:45
KDL::ChainExternalWrenchEstimator::dynparam_solver
ChainDynParam dynparam_solver
Definition: chainexternalwrenchestimator.hpp:122
KDL::ChainExternalWrenchEstimator::strError
virtual const char * strError(const int error) const
Definition: chainexternalwrenchestimator.cpp:204
KDL::ChainExternalWrenchEstimator::ns
unsigned int ns
Definition: chainexternalwrenchestimator.hpp:115
KDL::JntArray::data
Eigen::VectorXd data
Definition: jntarray.hpp:72
KDL::ChainExternalWrenchEstimator::jnt_mass_matrix
JntSpaceInertiaMatrix jnt_mass_matrix
Definition: chainexternalwrenchestimator.hpp:116
KDL::ChainExternalWrenchEstimator::E_DYNPARAMSOLVERGRAVITY_FAILED
static const int E_DYNPARAMSOLVERGRAVITY_FAILED
Internally-used Dynamics Parameters (Coriolis) solver failed.
Definition: chainexternalwrenchestimator.hpp:53
KDL::ChainJntToJacSolver::updateInternalDataStructures
virtual void updateInternalDataStructures()
Definition: chainjnttojacsolver.cpp:31
KDL::ChainExternalWrenchEstimator::previous_jnt_mass_matrix
JntSpaceInertiaMatrix previous_jnt_mass_matrix
Definition: chainexternalwrenchestimator.hpp:116
KDL::ChainExternalWrenchEstimator::tmp
Eigen::VectorXd tmp
Definition: chainexternalwrenchestimator.hpp:121
KDL::ChainExternalWrenchEstimator::setInitialMomentum
int setInitialMomentum(const JntArray &joint_position, const JntArray &joint_velocity)
Definition: chainexternalwrenchestimator.cpp:74
KDL::ChainExternalWrenchEstimator::jnt_mass_matrix_dot
JntSpaceInertiaMatrix jnt_mass_matrix_dot
Definition: chainexternalwrenchestimator.hpp:116
KDL::ChainExternalWrenchEstimator::ChainExternalWrenchEstimator
ChainExternalWrenchEstimator(const Chain &chain, const Vector &gravity, const double sample_frequency, const double estimation_gain, const double filter_constant, const double eps=0.00001, const int maxiter=150)
Internally-used Dynamics Parameters (Gravity) solver failed.
Definition: chainexternalwrenchestimator.cpp:25
KDL::Jacobian::data
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::Matrix< double, 6, Eigen::Dynamic > data
Definition: jacobian.hpp:41
KDL::ChainExternalWrenchEstimator::S_inv
Eigen::VectorXd S_inv
Definition: chainexternalwrenchestimator.hpp:121
KDL::ChainExternalWrenchEstimator::DT_SEC
const double DT_SEC
Definition: chainexternalwrenchestimator.hpp:112
KDL::ChainExternalWrenchEstimator::U
Eigen::MatrixXd U
Definition: chainexternalwrenchestimator.hpp:120
KDL::ChainExternalWrenchEstimator::getEstimatedJntTorque
void getEstimatedJntTorque(JntArray &external_joint_torque)
Definition: chainexternalwrenchestimator.cpp:198
KDL::ChainDynParam::JntToGravity
virtual int JntToGravity(const JntArray &q, JntArray &gravity)
Definition: chaindynparam.cpp:139
KDL::ChainFkSolverPos_recursive::updateInternalDataStructures
virtual void updateInternalDataStructures()
Definition: chainfksolverpos_recursive.hpp:45
KDL::ChainExternalWrenchEstimator::Vector6d
Eigen::Matrix< double, 6, 1 > Vector6d
Definition: chainexternalwrenchestimator.hpp:45
KDL::ChainExternalWrenchEstimator::nj
unsigned int nj
Definition: chainexternalwrenchestimator.hpp:115
KDL::ChainExternalWrenchEstimator::estimated_momentum_integral
JntArray estimated_momentum_integral
Definition: chainexternalwrenchestimator.hpp:117
KDL::SetToZero
void SetToZero(Jacobian &jac)
Definition: jacobian.cpp:79
KDL::SolverI::E_NOERROR
@ E_NOERROR
No error.
Definition: solveri.hpp:91
KDL::ChainDynParam::JntToCoriolis
virtual int JntToCoriolis(const JntArray &q, const JntArray &q_dot, JntArray &coriolis)
Definition: chaindynparam.cpp:127
KDL::ChainExternalWrenchEstimator::E_FKSOLVERPOS_FAILED
static const int E_FKSOLVERPOS_FAILED
Definition: chainexternalwrenchestimator.hpp:49
KDL::Chain
This class encapsulates a serial kinematic interconnection structure. It is built out of segments.
Definition: chain.hpp:35
KDL::ChainExternalWrenchEstimator::ESTIMATION_GAIN
Eigen::VectorXd ESTIMATION_GAIN
Definition: chainexternalwrenchestimator.hpp:121
KDL::Chain::getNrOfJoints
unsigned int getNrOfJoints() const
Definition: chain.hpp:71
KDL::ChainExternalWrenchEstimator::jacobian_end_eff_transpose
Eigen::MatrixXd jacobian_end_eff_transpose
Definition: chainexternalwrenchestimator.hpp:120
KDL::SolverI::error
int error
Latest error, initialized to E_NOERROR in constructor.
Definition: solveri.hpp:149
KDL::ChainExternalWrenchEstimator::setSVDMaxIter
void setSVDMaxIter(const int maxiter_in)
Definition: chainexternalwrenchestimator.cpp:100