- 3.0.2 optimal control module.
RKnDerivatives.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 #include <cmath>
9 
13 
14 namespace ct {
15 namespace optcon {
16 
17 
27 template <size_t STATE_DIM, size_t CONTROL_DIM>
29 {
30 public:
31  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
32 
34 
35  typedef typename DIMENSIONS::state_vector_t state_vector_t;
36  typedef typename DIMENSIONS::state_vector_array_t state_vector_array_t;
37  typedef typename DIMENSIONS::control_vector_t control_vector_t;
38  typedef typename DIMENSIONS::control_vector_array_t control_vector_array_t;
39  typedef typename DIMENSIONS::time_array_t time_array_t;
40  typedef typename DIMENSIONS::state_matrix_t state_matrix_t;
41  typedef typename DIMENSIONS::control_matrix_t control_matrix_t;
42  typedef typename DIMENSIONS::state_control_matrix_t state_control_matrix_t;
43  typedef typename DIMENSIONS::state_matrix_array_t state_matrix_array_t;
44  typedef typename DIMENSIONS::state_control_matrix_array_t state_control_matrix_array_t;
45 
46  RKnDerivatives() = delete;
47 
55  RKnDerivatives(std::shared_ptr<SplinerBase<control_vector_t>> controlSpliner,
56  size_t shotIdx,
57  const DmsSettings& settings)
58  : shotIdx_(shotIdx),
59  settings_(settings),
60  controlSpliner_(controlSpliner),
61  x_log_(nullptr),
62  u_log_(nullptr),
63  t_log_(nullptr),
64  A_log_(nullptr),
65  B_log_(nullptr),
66  dXdSi_history_(state_matrix_array_t(0)),
67  dXdQi_history_(state_control_matrix_array_t(0)),
68  dXdQip1_history_(state_control_matrix_array_t(0)),
69  dXdHi_history_(state_vector_array_t(0))
70  {
71  }
72 
73  void setLogs(std::shared_ptr<state_vector_array_t> x_log,
74  std::shared_ptr<control_vector_array_t> u_log,
75  std::shared_ptr<time_array_t> t_log,
76  std::shared_ptr<state_matrix_array_t> A_log,
77  std::shared_ptr<state_control_matrix_array_t> B_log)
78  {
79  x_log_ = x_log;
80  u_log_ = u_log;
81  t_log_ = t_log;
82  A_log_ = A_log;
83  B_log_ = B_log;
84  }
85 
86 
87  // compute sensitivity of all X in the trajectory w.r.t. s_i
89  {
90  dXdSi_history_.clear();
91  dXdSi_history_.push_back(Eigen::MatrixXd::Identity(STATE_DIM, STATE_DIM));
92 
93  switch (settings_.integrationType_)
94  {
95  case DmsSettings::EULER:
96  {
97  size_t nSteps = A_log_->size() / 1;
98  for (size_t i = 0; i < nSteps; i++)
99  {
100  double dt_sim = (*t_log_)[i + 1] - (*t_log_)[i];
101 
102  state_matrix_t temp = Eigen::MatrixXd::Identity(STATE_DIM, STATE_DIM) + dt_sim * (*A_log_)[i];
103 
104  dXdSi_history_.push_back(temp * dXdSi_history_.back());
105  }
106  break;
107  }
108  case DmsSettings::RK4:
109  {
110  size_t m = 4;
111  size_t nCycles = A_log_->size() / m;
112 
113  double a_21 = 0.5;
114  double a_32 = 0.5;
115  double a_43 = 1.0;
116 
117  double b1 = 1.0 / 6.0;
118  double b2 = 1.0 / 3.0;
119  double b3 = 1.0 / 3.0;
120  double b4 = 1.0 / 6.0;
121 
122  for (size_t i = 0; i < nCycles; i++)
123  {
124  double h = (*t_log_)[(i + 1) * m] - (*t_log_)[i * m];
125 
126  // step 1:
127  state_matrix_t dK1dSi = (*A_log_)[i * m] * dXdSi_history_.back();
128 
129  // step 2:
130  state_matrix_t dK2dSi = (*A_log_)[i * m + 1] * (dXdSi_history_.back() + h * a_21 * dK1dSi);
131 
132  // step 3:
133  state_matrix_t dK3dSi = (*A_log_)[i * m + 2] * (dXdSi_history_.back() + h * a_32 * dK2dSi);
134 
135  // step 4:
136  state_matrix_t dK4dSi = (*A_log_)[i * m + 3] * (dXdSi_history_.back() + h * a_43 * dK3dSi);
137 
138 
139  // summation:
140  state_matrix_t temp =
141  dXdSi_history_.back() + h * (b1 * dK1dSi + b2 * dK2dSi + b3 * dK3dSi + b4 * dK4dSi);
142 
143  dXdSi_history_.push_back(temp);
144  }
145  break;
146  }
147  default:
148  {
149  std::cerr << "... ERROR: sensitivity calculation not implemented for this integration type. Exiting"
150  << std::endl;
151  exit(0);
152  }
153  }
154  }
155 
156 
157  // compute sensitivity of all X in the trajectory w.r.t. q_i
159  {
160  dXdQi_history_.clear();
161  dXdQi_history_.push_back(state_control_matrix_t::Zero());
162 
163  switch (settings_.integrationType_)
164  {
165  case DmsSettings::EULER:
166  {
167  for (size_t i = 0; i < A_log_->size(); ++i)
168  {
169  control_matrix_t dSpldQ0 = controlSpliner_->splineDerivative_q_i((*t_log_)[i], shotIdx_);
170 
171  double dt_sim = (*t_log_)[i + 1] - (*t_log_)[i];
172 
173  dXdQi_history_.push_back(dXdQi_history_.back() +
174  dt_sim * ((*A_log_)[i] * dXdQi_history_.back() + (*B_log_)[i] * dSpldQ0));
175  }
176  break;
177  }
178  case DmsSettings::RK4:
179  {
180  size_t m = 4;
181  size_t nCycles = A_log_->size() / m;
182 
183  double a_21 = 0.5;
184  double a_32 = 0.5;
185  double a_43 = 1;
186 
187  double b1 = 1.0 / 6.0;
188  double b2 = 1.0 / 3.0;
189  double b3 = 1.0 / 3.0;
190  double b4 = 1.0 / 6.0;
191 
192  for (size_t i = 0; i < nCycles; i++)
193  {
194  assert(i * m < A_log_->size());
195 
196  double h = (*t_log_)[(i + 1) * m] - (*t_log_)[i * m];
197 
198  // TODO: write these steps as computationally more efficient loop if they are correct.
199  // step 1:
200  state_control_matrix_t dK1dQi =
201  (*A_log_)[i * m] * dXdQi_history_.back() +
202  (*B_log_)[i * m] * controlSpliner_->splineDerivative_q_i((*t_log_)[i * m], shotIdx_);
203 
204  // step 2:
205  state_control_matrix_t dK2dQi =
206  (*A_log_)[i * m + 1] * (dXdQi_history_.back() + h * a_21 * dK1dQi) +
207  (*B_log_)[i * m + 1] * controlSpliner_->splineDerivative_q_i((*t_log_)[i * m + 1], shotIdx_);
208 
209  // step 3:
210  state_control_matrix_t dK3dQi =
211  (*A_log_)[i * m + 2] * (dXdQi_history_.back() + h * a_32 * dK2dQi) +
212  (*B_log_)[i * m + 2] * controlSpliner_->splineDerivative_q_i((*t_log_)[i * m + 2], shotIdx_);
213 
214  // step 4:
215  state_control_matrix_t dK4dQi =
216  (*A_log_)[i * m + 3] * (dXdQi_history_.back() + h * a_43 * dK3dQi) +
217  (*B_log_)[i * m + 3] * controlSpliner_->splineDerivative_q_i((*t_log_)[i * m + 3], shotIdx_);
218 
219 
220  // summation
221  state_control_matrix_t temp =
222  dXdQi_history_.back() + h * (b1 * dK1dQi + b2 * dK2dQi + b3 * dK3dQi + b4 * dK4dQi);
223 
224  dXdQi_history_.push_back(temp);
225  }
226  break;
227  }
228  default:
229  {
230  std::cerr << "... ERROR: sensitivity calculation not implemented for this integration type. Exiting"
231  << std::endl;
232  exit(0);
233  }
234  }
235  }
236 
237 
238  // compute sensitivity of all X in the trajectory w.r.t. q_(i+1)
240  {
241  dXdQip1_history_.clear();
242  dXdQip1_history_.push_back(state_control_matrix_t::Zero());
243 
244  assert(t_log_->size() == A_log_->size() + 1);
245 
246  switch (settings_.integrationType_)
247  {
248  case DmsSettings::EULER:
249  {
250  for (size_t i = 0; i < A_log_->size(); ++i)
251  {
252  control_matrix_t dSpldQ1 = controlSpliner_->splineDerivative_q_iplus1((*t_log_)[i], shotIdx_);
253 
254  assert(dSpldQ1 == dSpldQ1);
255 
256  double dt_sim = (*t_log_)[i + 1] - (*t_log_)[i];
257 
258  dXdQip1_history_.push_back(
259  dXdQip1_history_.back() +
260  dt_sim * ((*A_log_)[i] * dXdQip1_history_.back() + (*B_log_)[i] * dSpldQ1));
261  }
262  break;
263  }
264  case DmsSettings::RK4:
265  {
266  size_t m = 4;
267  size_t nCycles = A_log_->size() / m;
268 
269  double a_21 = 0.5;
270  double a_32 = 0.5;
271  double a_43 = 1;
272 
273  double b1 = 1 / 6.0;
274  double b2 = 1 / 3.0;
275  double b3 = 1 / 3.0;
276  double b4 = 1 / 6.0;
277 
278  for (size_t i = 0; i < nCycles; i++)
279  {
280  double h = (*t_log_)[(i + 1) * m] - (*t_log_)[i * m];
281 
282  // TODO: write these steps as computationally more efficient loop if they are correct.
283  // step 1:
284  state_control_matrix_t dK1dQip1 =
285  (*A_log_)[i * m] * dXdQip1_history_.back() +
286  (*B_log_)[i * m] * controlSpliner_->splineDerivative_q_iplus1((*t_log_)[i * m], shotIdx_);
287 
288  // step 2:
289  state_control_matrix_t dK2dQip1 =
290  (*A_log_)[i * m + 1] * (dXdQip1_history_.back() + h * a_21 * dK1dQip1) +
291  (*B_log_)[i * m + 1] *
292  controlSpliner_->splineDerivative_q_iplus1((*t_log_)[i * m + 1], shotIdx_);
293 
294  // step 3:
295  state_control_matrix_t dK3dQip1 =
296  (*A_log_)[i * m + 2] * (dXdQip1_history_.back() + h * a_32 * dK2dQip1) +
297  (*B_log_)[i * m + 2] *
298  controlSpliner_->splineDerivative_q_iplus1((*t_log_)[i * m + 2], shotIdx_);
299 
300  // step 4:
301  state_control_matrix_t dK4dQip1 =
302  (*A_log_)[i * m + 3] * (dXdQip1_history_.back() + h * a_43 * dK3dQip1) +
303  (*B_log_)[i * m + 3] *
304  controlSpliner_->splineDerivative_q_iplus1((*t_log_)[i * m + 3], shotIdx_);
305 
306 
307  // summation
308  state_control_matrix_t temp =
309  dXdQip1_history_.back() + h * (b1 * dK1dQip1 + b2 * dK2dQip1 + b3 * dK3dQip1 + b4 * dK4dQip1);
310 
311  dXdQip1_history_.push_back(temp);
312  }
313  break;
314  }
315  default:
316  {
317  throw(std::runtime_error(
318  "... ERROR: sensitivity calculation not implemented for this integration type."));
319  }
320  }
321  }
322 
323  void getdXdSiTraj(state_matrix_array_t& dXdSiTraj) { dXdSiTraj = dXdSi_history_; }
324  void getdXdQiTraj(state_control_matrix_array_t& dXdQiTraj) { dXdQiTraj = dXdQi_history_; }
325  void getdXdQip1Traj(state_control_matrix_array_t& dXdQip1Traj) { dXdQip1Traj = dXdQip1_history_; }
326  void getdXdHiTraj(state_vector_array_t& dXdHiTraj) { dXdHiTraj = dXdHi_history_; }
327 private:
328  std::shared_ptr<SplinerBase<control_vector_t>> controlSpliner_;
329  const size_t shotIdx_;
330  const DmsSettings settings_;
331 
332  std::shared_ptr<state_vector_array_t> x_log_;
333  std::shared_ptr<control_vector_array_t> u_log_;
334  std::shared_ptr<time_array_t> t_log_;
335  std::shared_ptr<state_matrix_array_t> A_log_;
336  std::shared_ptr<state_control_matrix_array_t> B_log_;
337 
338  state_matrix_array_t dXdSi_history_;
339  state_control_matrix_array_t dXdQi_history_;
340  state_control_matrix_array_t dXdQip1_history_;
341  state_vector_array_t dXdHi_history_;
342 };
343 
344 } // namespace optcon
345 } // namespace ct
DIMENSIONS::state_matrix_t state_matrix_t
Definition: RKnDerivatives.h:40
void setLogs(std::shared_ptr< state_vector_array_t > x_log, std::shared_ptr< control_vector_array_t > u_log, std::shared_ptr< time_array_t > t_log, std::shared_ptr< state_matrix_array_t > A_log, std::shared_ptr< state_control_matrix_array_t > B_log)
Definition: RKnDerivatives.h:73
EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef DmsDimensions< STATE_DIM, CONTROL_DIM > DIMENSIONS
Definition: RKnDerivatives.h:33
This class implements analytical sensitivity generation for the euler and rk4 integration scheme...
Definition: RKnDerivatives.h:28
void getdXdSiTraj(state_matrix_array_t &dXdSiTraj)
Definition: RKnDerivatives.h:323
DIMENSIONS::state_control_matrix_t state_control_matrix_t
Definition: RKnDerivatives.h:42
Abstract base class for the control input splining between the DMS shots.
Definition: SplinerBase.h:20
Definition: DmsSettings.h:28
void compute_dXdQi()
Definition: RKnDerivatives.h:158
RKnDerivatives(std::shared_ptr< SplinerBase< control_vector_t >> controlSpliner, size_t shotIdx, const DmsSettings &settings)
Custom constructor.
Definition: RKnDerivatives.h:55
DIMENSIONS::control_vector_t control_vector_t
Definition: RKnDerivatives.h:37
void getdXdHiTraj(state_vector_array_t &dXdHiTraj)
Definition: RKnDerivatives.h:326
DIMENSIONS::state_vector_array_t state_vector_array_t
Definition: RKnDerivatives.h:36
DIMENSIONS::time_array_t time_array_t
Definition: RKnDerivatives.h:39
DIMENSIONS::control_matrix_t control_matrix_t
Definition: RKnDerivatives.h:41
DIMENSIONS::state_vector_t state_vector_t
Definition: RKnDerivatives.h:35
for i
Definition: mpc_unittest_plotting.m:14
void compute_dXdQip1()
Definition: RKnDerivatives.h:239
Defines the DMS settings.
Definition: DmsSettings.h:23
DIMENSIONS::control_vector_array_t control_vector_array_t
Definition: RKnDerivatives.h:38
void getdXdQip1Traj(state_control_matrix_array_t &dXdQip1Traj)
Definition: RKnDerivatives.h:325
void getdXdQiTraj(state_control_matrix_array_t &dXdQiTraj)
Definition: RKnDerivatives.h:324
DIMENSIONS::state_control_matrix_array_t state_control_matrix_array_t
Definition: RKnDerivatives.h:44
void compute_dXdSi()
Definition: RKnDerivatives.h:88
IntegrationType_t integrationType_
Definition: DmsSettings.h:58
DIMENSIONS::state_matrix_array_t state_matrix_array_t
Definition: RKnDerivatives.h:43
Definition: DmsSettings.h:28