- 3.0.2 rigid body dynamics module.
RbdLinearizer.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
16 #pragma once
17 
18 #include <memory>
19 
20 #pragma GCC diagnostic push
21 #pragma GCC diagnostic ignored "-Wunused-parameter"
22 #pragma GCC diagnostic ignored "-Wunused-value"
23 #include <kindr/Core>
24 #pragma GCC diagnostic pop
25 
26 template <int N>
28 {
29  char operator()() { return N + 256; } //deliberately causing overflow
30 };
31 
32 namespace ct {
33 namespace rbd {
34 
35 template <class SYSTEM>
36 class RbdLinearizer : public ct::core::SystemLinearizer<SYSTEM::STATE_DIM, SYSTEM::CONTROL_DIM, typename SYSTEM::SCALAR>
37 {
38 public:
39  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
40 
41  static const bool FLOATING_BASE = SYSTEM::Dynamics::FB;
42 
43  typedef std::shared_ptr<RbdLinearizer<SYSTEM>> Ptr;
44  typedef typename SYSTEM::SCALAR SCALAR;
45 
46  static const size_t STATE_DIM = SYSTEM::STATE_DIM;
47  static const size_t CONTROL_DIM = SYSTEM::CONTROL_DIM;
48  static const size_t NJOINTS = SYSTEM::Dynamics::NJOINTS;
49 
50  static_assert(SYSTEM::STATE_DIM == 2 * (SYSTEM::Dynamics::NJOINTS + FLOATING_BASE * 6),
51  "STATE DIMENSION MISMATCH. RBD LINEARIZER ONLY WORKS FOR PURE RIGID BODY DYNAMICS.");
52  static_assert(SYSTEM::CONTROL_DIM == SYSTEM::Dynamics::NJOINTS,
53  "CONTROL DIMENSION MISMATCH. RBD LINEARIZER ONLY WORKS FOR FULL JOINT CONTROLLED SYSTEMS.");
54 
55 
57 
60 
63 
64 
65  RbdLinearizer(std::shared_ptr<SYSTEM> RBDSystem, bool doubleSidedDerivative = false)
66  : Base(RBDSystem, doubleSidedDerivative), RBDSystem_(RBDSystem)
67  {
68  // check if a non-floating base system is a second order system
69  if (!FLOATING_BASE && (this->getType() != ct::core::SYSTEM_TYPE::SECOND_ORDER))
70  {
71  std::cout
72  << "RbdLinearizer.h: Warning, fixed base system not declared as second order system. "
73  << "Normally, fixed base systems are second order systems and RbdLinearizer will treat them like this. "
74  << "To declare system as second order, see ct::core::System" << std::endl;
75  }
76 
77  // fill default
78  this->dFdx_.template topLeftCorner<STATE_DIM / 2, STATE_DIM / 2>().setZero();
79  this->dFdx_.template topRightCorner<STATE_DIM / 2, STATE_DIM / 2>().setIdentity();
80 
81  // fill default
82  this->dFdu_.template topRows<STATE_DIM / 2>().setZero();
83  }
84 
85  RbdLinearizer(const RbdLinearizer& arg) : Base(arg), RBDSystem_(std::shared_ptr<SYSTEM>(arg.RBDSystem_->clone())) {}
86  virtual ~RbdLinearizer() override {}
87  RbdLinearizer<SYSTEM>* clone() const override { return new RbdLinearizer<SYSTEM>(*this); }
88  const state_matrix_t& getDerivativeState(const state_vector_t& x,
89  const control_vector_t& u,
90  const SCALAR t = 0.0) override
91  {
92  if (!FLOATING_BASE)
93  {
94  // call standard ct_core linearizer
95  return Base::getDerivativeState(x, u, t);
96  }
97  else
98  {
99  Base::getDerivativeState(x, u, t);
100 
101  // since we express base pose in world but base twist in body coordinates, we have to modify the top part
102  kindr::EulerAnglesXyz<SCALAR> eulerXyz(x.template topRows<3>());
103  kindr::RotationMatrix<SCALAR> R_WB_kindr(eulerXyz);
104 
105  Eigen::Matrix<SCALAR, 3, 6> jacAngVel =
106  jacobianOfAngularVelocityMapping(x.template topRows<3>(), x.template segment<3>(STATE_DIM / 2))
107  .transpose();
108 
109  //this->dFdx_.template block<3,3>(0,0) = -R_WB_kindr.toImplementation() * JacobianOfRotationMultiplyVector( x.template topRows<3>(), R_WB_kindr.toImplementation()*(x.template segment<3>(STATE_DIM/2) ));
110  this->dFdx_.template block<3, 3>(0, 0) = jacAngVel.template block<3, 3>(0, 0);
111 
112  this->dFdx_.template block<3, 3>(3, 0) =
113  -R_WB_kindr.toImplementation() *
114  JacobianOfRotationMultiplyVector(x.template topRows<3>(),
115  R_WB_kindr.toImplementation() * (x.template segment<3>(STATE_DIM / 2 + 3)));
116 
117 
118  // Derivative Top Row
119  // This is the derivative of the orientation with respect to local angular velocity. This is NOT the rotation matrix
120  this->dFdx_.template block<3, 3>(0, STATE_DIM / 2) = jacAngVel.template block<3, 3>(0, 3);
121  // we prefer to use a combined calculation. The following call would be equivalent but recomputes sines/cosines
122  //this->dFdx_.template block<3, 3>(0, STATE_DIM/2) = eulerXyz.getMappingFromLocalAngularVelocityToDiff();
123 
124  // This is the derivative of the position with respect to linear velocity. This is simply the rotation matrix
125  this->dFdx_.template block<3, 3>(3, STATE_DIM / 2 + 3) = R_WB_kindr.toImplementation();
126 
127  return this->dFdx_;
128  }
129  }
130 
131  const state_control_matrix_t& getDerivativeControl(const state_vector_t& x,
132  const control_vector_t& u,
133  const SCALAR t = 0.0) override
134  {
135  const jsim_t& M = RBDSystem_->dynamics().kinematics().robcogen().jSim().update(
136  x.template segment<NJOINTS>(FLOATING_BASE * 6));
137 
138  llt_.compute(M);
139 
140  const typename jsim_t::MatrixType& M_inv = llt_.solve(jsim_t::Identity());
141 
142 #ifdef DEBUG
143  typename jsim_t::MatrixType Meigen = M;
144  if (!Meigen.inverse().isApprox(M_inv))
145  {
146  Eigen::SelfAdjointEigenSolver<typename jsim_t::MatrixType> eigensolver(M);
147  std::cout << "The eigenvalues of M are:\n" << eigensolver.eigenvalues().transpose() << std::endl;
148  std::cout << "M inverse incorrect" << std::endl;
149  std::cout << "M.inverse: " << std::endl << Meigen.inverse() << std::endl;
150  std::cout << "M_inv: " << std::endl << M_inv << std::endl;
151 
152  // Marco's LLT version
153  jsim_t M_temp = M;
154  M_temp.computeL();
155  M_temp.computeInverse();
156  auto M_inv_robcogen = M_temp.getInverse();
157  std::cout << "M_inv_robcogen: " << std::endl << M_inv_robcogen << std::endl;
158  }
159 #endif //DEBUG
160 
161  auto& S = RBDSystem_->dynamics().S();
162 
163  this->dFdu_.template block<STATE_DIM / 2, CONTROL_DIM>(STATE_DIM / 2, 0) = M_inv * S.transpose();
164 
165  return this->dFdu_;
166  }
167 
168 
169 protected:
171 
172  std::shared_ptr<SYSTEM> RBDSystem_;
173 
174  Eigen::LLT<typename jsim_t::MatrixType> llt_;
175 
176 private:
177  // auto generated code
178  Eigen::Matrix<SCALAR, 3, 3> JacobianOfRotationMultiplyVector(const Eigen::Matrix<SCALAR, 3, 1>& theta,
179  const Eigen::Matrix<SCALAR, 3, 1>& vector)
180  {
181  const SCALAR& theta_1 = theta(0);
182  const SCALAR& theta_2 = theta(1);
183  const SCALAR& theta_3 = theta(2);
184 
185  const SCALAR& vector_1 = vector(0);
186  const SCALAR& vector_2 = vector(1);
187  const SCALAR& vector_3 = vector(2);
188 
189 
190  Eigen::Matrix<SCALAR, 3, 3> A0;
191  A0.setZero();
192 
193 
194  SCALAR t2 = cos(theta_1);
195  SCALAR t3 = sin(theta_3);
196  SCALAR t4 = cos(theta_3);
197  SCALAR t5 = sin(theta_1);
198  SCALAR t6 = sin(theta_2);
199  SCALAR t7 = cos(theta_2);
200  SCALAR t8 = t4 * t5;
201  SCALAR t9 = t2 * t3 * t6;
202  SCALAR t10 = t8 + t9;
203  SCALAR t11 = t2 * t4;
204  SCALAR t12 = t11 - t3 * t5 * t6;
205  SCALAR t13 = t6 * vector_1;
206  SCALAR t14 = t2 * t7 * vector_3;
207  SCALAR t15 = t13 + t14 - t5 * t7 * vector_2;
208  SCALAR t16 = t2 * t3;
209  SCALAR t17 = t4 * t5 * t6;
210  SCALAR t18 = t16 + t17;
211  SCALAR t19 = t3 * t5;
212  SCALAR t20 = t19 - t2 * t4 * t6;
213  A0(0, 0) = t18 * vector_3 - t20 * vector_2;
214  A0(0, 1) = -t4 * t15;
215  A0(0, 2) = t10 * vector_3 + t12 * vector_2 - t3 * t7 * vector_1;
216  A0(1, 0) = -t10 * vector_2 + t12 * vector_3;
217  A0(1, 1) = t3 * t15;
218  A0(1, 2) = -t18 * vector_2 - t20 * vector_3 - t4 * t7 * vector_1;
219  A0(2, 0) = -t7 * (t2 * vector_2 + t5 * vector_3);
220  A0(2, 1) = t7 * vector_1 - t2 * t6 * vector_3 + t5 * t6 * vector_2;
221 
222  return A0;
223  }
224 
236  Eigen::Matrix<SCALAR, 6, 3> jacobianOfAngularVelocityMapping(const Eigen::Matrix<SCALAR, 3, 1>& eulerAnglesXyz,
237  const Eigen::Matrix<SCALAR, 3, 1>& angularVelocity)
238  {
239  using namespace std;
240 
241  Eigen::Matrix<SCALAR, 6, 1> xAD;
242  xAD << eulerAnglesXyz, angularVelocity;
243  const SCALAR* x = xAD.data();
244 
245  std::array<SCALAR, 10> v;
246 
247  Eigen::Matrix<SCALAR, 6, 3> jac;
248  SCALAR* y = jac.data();
249 
250  y[9] = sin(x[2]);
251  y[10] = cos(x[2]);
252  v[0] = cos(x[1]);
253  v[1] = 1 / v[0];
254  y[3] = v[1] * y[10];
255  v[2] = sin(x[1]);
256  y[1] = 0 - (0 - (0 - x[4] * y[9] + x[3] * y[10]) * 1 / v[0] * v[1]) * v[2];
257  v[3] = sin(x[2]);
258  v[4] = 0 - v[1];
259  y[4] = v[4] * y[9];
260  v[5] = y[10];
261  y[2] = 0 - x[3] * v[1] * v[3] + x[4] * v[4] * v[5];
262  y[8] = 0 - x[4] * v[3] + x[3] * v[5];
263  v[6] = v[1] * y[9];
264  v[7] = v[4] * y[10];
265  v[8] = v[2];
266  y[15] = v[7] * v[8];
267  y[16] = v[6] * v[8];
268  v[9] = x[4] * v[8];
269  v[8] = x[3] * v[8];
270  y[13] = (x[4] * v[6] + x[3] * v[7]) * v[0] - (0 - (v[9] * y[9] - v[8] * y[10]) * 1 / v[0] * v[1]) * v[2];
271  y[14] = 0 - v[8] * v[4] * v[3] + v[9] * v[1] * v[5];
272  // dependent variables without operations
273  y[0] = 0;
274  y[5] = 0;
275  y[6] = 0;
276  y[7] = 0;
277  y[11] = 0;
278  y[12] = 0;
279  y[17] = 1;
280 
281 
282  return jac;
283  }
284 };
285 
286 } // namespace rbd
287 } // namespace ct
RbdLinearizer< SYSTEM > * clone() const override
Definition: RbdLinearizer.h:87
const state_control_matrix_t & getDerivativeControl(const state_vector_t &x, const control_vector_t &u, const SCALAR t=0.0) override
Definition: RbdLinearizer.h:131
virtual ~RbdLinearizer() override
Definition: RbdLinearizer.h:86
tpl::JSIM< rbd::DoubleTrait > JSIM
Definition: jsim.h:154
ct::core::SystemLinearizer< STATE_DIM, CONTROL_DIM, SCALAR > Base
Definition: RbdLinearizer.h:51
RbdLinearizer(std::shared_ptr< SYSTEM > RBDSystem, bool doubleSidedDerivative=false)
Definition: RbdLinearizer.h:65
RbdLinearizer(const RbdLinearizer &arg)
Definition: RbdLinearizer.h:85
clear all close all load ct GNMSLog0 mat reformat t
std::shared_ptr< SYSTEM > RBDSystem_
Definition: RbdLinearizer.h:172
Eigen::LLT< typename jsim_t::MatrixType > llt_
Definition: RbdLinearizer.h:174
SYSTEM::SCALAR SCALAR
Definition: RbdLinearizer.h:44
ct::core::StateControlMatrix< STATE_DIM, CONTROL_DIM, SCALAR > state_control_matrix_t
Definition: RbdLinearizer.h:62
This is a common interface class for an RBDSystem.
Definition: RBDSystem.h:15
ct::core::ControlVector< CONTROL_DIM, SCALAR > control_vector_t
Definition: RbdLinearizer.h:59
ct::core::StateVector< state_dim > x
char operator()()
Definition: RbdLinearizer.h:29
const state_matrix_t & getDerivativeState(const state_vector_t &x, const control_vector_t &u, const SCALAR t=0.0) override
Definition: RbdLinearizer.h:88
ct::core::StateVector< STATE_DIM, SCALAR > state_vector_t
Definition: RbdLinearizer.h:58
SYSTEM::Dynamics::ROBCOGEN::JSIM jsim_t
Definition: RbdLinearizer.h:170
ct::core::StateMatrix< STATE_DIM, SCALAR > state_matrix_t
Definition: RbdLinearizer.h:61
std::shared_ptr< RbdLinearizer< SYSTEM > > Ptr
Definition: RbdLinearizer.h:43
Definition: RbdLinearizer.h:36
System Linearizer dedicated to Articulated Rigid Body Model.
Definition: RbdLinearizer.h:27