- 3.0.2 core module.
DynamicsLinearizerADBase.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 
6 #pragma once
7 
8 #ifdef CPPADCG
9 
11 
12 namespace ct {
13 namespace core {
14 namespace internal {
15 
17 
25 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR, typename TIME>
26 class DynamicsLinearizerADBase
27 {
28 public:
29  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
30 
31  //TODO this exclusive list, the following typedef, and getOutScalarType() should be generalized
32  static_assert((std::is_same<SCALAR, CppAD::AD<double>>::value) ||
33  (std::is_same<SCALAR, CppAD::AD<CppAD::cg::CG<double>>>::value) ||
34  (std::is_same<SCALAR, CppAD::AD<float>>::value) ||
35  (std::is_same<SCALAR, CppAD::AD<CppAD::cg::CG<float>>>::value),
36  "SCALAR template parameter in ADLinearizerBase should either be of CppAD::AD<XX> or "
37  "CppAD::AD<CppAD::cg::XX> type with XX being float or double");
38 
39  typedef typename std::conditional<(std::is_same<SCALAR, CppAD::AD<double>>::value) ||
40  (std::is_same<SCALAR, CppAD::AD<CppAD::cg::CG<double>>>::value),
41  double,
42  float>::type OUT_SCALAR;
43 
44  typedef StateVector<STATE_DIM, OUT_SCALAR> state_vector_t;
45  typedef ControlVector<CONTROL_DIM, OUT_SCALAR> control_vector_t;
46 
47  typedef StateVector<STATE_DIM, SCALAR> state_vector_ad_t;
48  typedef ControlVector<CONTROL_DIM, SCALAR> control_vector_ad_t;
49 
50  typedef StateMatrix<STATE_DIM, OUT_SCALAR> state_matrix_t;
51  typedef StateControlMatrix<STATE_DIM, CONTROL_DIM, OUT_SCALAR> state_control_matrix_t;
52 
53  typedef std::function<void(const state_vector_ad_t&, const TIME&, const control_vector_ad_t&, state_vector_ad_t&)>
54  dynamics_fct_t;
55 
57 
60  DynamicsLinearizerADBase(dynamics_fct_t dyn) : dynamics_fct_(dyn) { initialize(); }
62  DynamicsLinearizerADBase(const DynamicsLinearizerADBase& arg) : dynamics_fct_(arg.dynamics_fct_)
63  {
64  setupSparsityA();
65  setupSparsityB();
66  f_ = arg.f_;
67  }
68 
69  template <typename T = std::string> // do not use this template argument
70  typename std::enable_if<std::is_same<OUT_SCALAR, double>::value, T>::type getOutScalarType() const
71  {
72  return "double";
73  }
74 
75  template <typename T = std::string> // do not use this template argument
76  typename std::enable_if<std::is_same<OUT_SCALAR, float>::value, T>::type getOutScalarType() const
77  {
78  return "float";
79  }
80 
81  virtual ~DynamicsLinearizerADBase() = default;
82 
83 protected:
84  const size_t A_entries = STATE_DIM * STATE_DIM;
85  const size_t B_entries = STATE_DIM * CONTROL_DIM;
86  const size_t FullJac_entries =
87  (STATE_DIM + CONTROL_DIM) * STATE_DIM;
88 
90 
93  void initialize()
94  {
95  recordTerms();
96  setupSparsityA();
97  setupSparsityB();
98  }
99 
101  void recordTerms()
102  {
103  // input vector, needs to be dynamic size
104  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> x(STATE_DIM + CONTROL_DIM);
105  // init to rand to avoid floating point problems in user's code
106  x.setRandom();
107 
108  // declare x as independent
109  CppAD::Independent(x);
110 
111  // create fixed size types since CT uses fixed size types
112  state_vector_ad_t xFixed = x.template head<STATE_DIM>();
113  control_vector_ad_t uFixed = x.template tail<CONTROL_DIM>();
114 
115  state_vector_ad_t dxFixed;
116 
117  dynamics_fct_(xFixed, TIME(0.0), uFixed, dxFixed);
118 
119  // output vector, needs to be dynamic size
120  Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> dx(STATE_DIM);
121  dx = dxFixed;
122 
123  // store operation sequence in f: x -> dx and stop recording
124  CppAD::ADFun<typename SCALAR::value_type> f(x, dx);
125 
126  f.optimize();
127 
128  f_ = f;
129  }
130 
132  void setupSparsityA()
133  {
134  // the derivative is a STATE_DIM*STATE_DIM Matrix:
135  // dF/dx = [ A, B ]^T
136  Eigen::Matrix<bool, STATE_DIM + CONTROL_DIM, STATE_DIM> sparsity;
137  sparsity.setZero();
138  sparsity.template topRows<STATE_DIM>().setOnes();
139 
140  sparsityA_.initPattern(sparsity);
141  sparsityA_.clearWork();
142  }
143 
145  void setupSparsityB()
146  {
147  // the derivative is a STATE_DIM*CONTROL_DIM Matrix:
148  // dF/dx = [ A, B ]^T
149  Eigen::Matrix<bool, STATE_DIM + CONTROL_DIM, STATE_DIM> sparsity;
150  sparsity.setZero();
151  sparsity.template bottomRows<CONTROL_DIM>().setOnes();
152 
153  sparsityB_.initPattern(sparsity);
154  sparsityB_.clearWork();
155  }
156 
157  dynamics_fct_t dynamics_fct_;
158  CppAD::ADFun<typename SCALAR::value_type> f_;
159 
160  SparsityPattern sparsityA_;
161  SparsityPattern sparsityB_;
162 };
163 
164 } // namespace internal
165 } // namespace core
166 } // namespace ct
167 
168 #endif
Eigen::Matrix< double, nControls, 1 > control_vector_t
CppAD::AD< CppAD::cg::CG< double > > SCALAR
ct::core::StateVector< state_dim > x
Eigen::Matrix< double, nStates, nStates > state_matrix_t
Eigen::Matrix< double, nStates, 1 > state_vector_t