- 3.0.2 optimal control module.
CostFunctionQuadratic-impl.hpp
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 namespace ct {
9 namespace optcon {
10 
11 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
13 {
14  eps_ = sqrt(Eigen::NumTraits<SCALAR>::epsilon());
15 }
16 
17 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
19  : CostFunction<STATE_DIM, CONTROL_DIM, SCALAR>(arg),
20  eps_(arg.eps_),
21  doubleSidedDerivative_(arg.doubleSidedDerivative_)
22 {
24  finalCostAnalytical_.resize(arg.finalCostAnalytical_.size());
25 
26  for (size_t i = 0; i < arg.intermediateCostAnalytical_.size(); i++)
27  {
29  std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>(arg.intermediateCostAnalytical_[i]->clone());
30  }
31 
32  for (size_t i = 0; i < arg.finalCostAnalytical_.size(); i++)
33  {
35  std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>(arg.finalCostAnalytical_[i]->clone());
36  }
37 }
38 
39 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
41 {
42 }
43 
44 #ifdef CPPADCG
45 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
48  bool verbose)
49 {
50  throw std::runtime_error("not implemented");
51 }
52 
53 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
56  bool verbose)
57 {
58  throw std::runtime_error("not implemented");
59 }
60 #endif
61 
62 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
64  bool verbose)
65 {
66  throw std::runtime_error("not implemented");
67 }
68 
69 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
72 {
73  throw std::runtime_error("controlDerivativeTerminal() not implemented in CostFunctionQuadratic");
74 }
75 
76 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
79 {
80  throw std::runtime_error("controlSecondDerivativeTerminal() not implemented");
81 }
82 
83 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
86 {
87  throw std::runtime_error("stateControlDerivativeTerminal() not implemented");
88 }
89 
90 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
92 {
93  for (auto costIntermediate : intermediateCostAnalytical_)
94  costIntermediate->updateReferenceState(x_ref);
95 }
96 
97 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
99 {
100  for (auto costFinal : finalCostAnalytical_)
101  costFinal->updateReferenceState(x_final);
102 }
103 
104 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
106 {
107  for (auto costIntermediate : intermediateCostAnalytical_)
108  costIntermediate->updateReferenceControl(u_ref);
109 }
110 
111 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
113 {
116 
117  if (verbose)
118  std::cout << "norm error between derivative/numdiff state : " << std::endl
119  << (derivative - derivativeNd).norm() << std::endl;
120 
121  return (derivative.isApprox(derivativeNd, 1e-6));
122 }
123 
124 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
126 {
129 
130  if (verbose)
131  std::cout << "norm error between derivative/numdiff control : " << std::endl
132  << (derivative - derivativeNd).norm() << std::endl;
133 
134  return (derivative.isApprox(derivativeNd, 1e-6));
135 }
136 
137 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
138 std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>
140 {
141  return intermediateCostAnalytical_[id];
142 }
143 
144 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
145 std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>
147 {
148  return finalCostAnalytical_[id];
149 }
150 
151 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
152 std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>
154 {
155  for (auto term : intermediateCostAnalytical_)
156  if (term->getName() == name)
157  return term;
158 
159  throw std::runtime_error("Term " + name + " not found in the CostFunctionQuadratic");
160 }
161 
162 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
163 std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>>
165 {
166  for (auto term : finalCostAnalytical_)
167  if (term->getName() == name)
168  return term;
169 
170  throw std::runtime_error("Term " + name + " not found in the CostFunctionQuadratic");
171 }
172 
173 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
176 {
177  state_vector_t dFdx = state_vector_t::Zero();
178  state_vector_t x_local;
179  control_vector_t u_local;
180  SCALAR t_local;
181  this->getCurrentStateAndControl(x_local, u_local, t_local);
182  SCALAR dxdt_ref = this->evaluateIntermediate();
183 
184  for (size_t i = 0; i < STATE_DIM; ++i)
185  {
186  // inspired from http://en.wikipedia.org/wiki/Numerical_differentiation#Practical_considerations_using_floating_point_arithmetic
187  SCALAR h = eps_ * std::max(std::abs(x_local(i)), 1.0);
188  volatile SCALAR x_ph = x_local(i) + h;
189  SCALAR dxp = x_ph - x_local(i);
190 
191  state_vector_t x_perturbed = x_local;
192  x_perturbed(i) = x_ph;
193 
194  // get evaluation of f(x,u)
195  this->setCurrentStateAndControl(x_perturbed, u_local, t_local);
196  SCALAR dxdt = this->evaluateIntermediate();
197 
199  {
200  SCALAR dxdt_low;
201 
202  volatile SCALAR x_mh = x_local(i) - h;
203  SCALAR dxm = x_local(i) - x_mh;
204 
205  x_perturbed = x_local;
206  x_perturbed(i) = x_mh;
207  this->setCurrentStateAndControl(x_perturbed, u_local, t_local);
208  dxdt_low = this->evaluateIntermediate();
209  dFdx(i, 0) = (dxdt - dxdt_low) / (dxp + dxm);
210  }
211  else
212  {
213  dFdx(i, 0) = (dxdt - dxdt_ref) / dxp;
214  }
215  }
216 
217  return dFdx;
218 }
219 
220 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
223 {
224  control_vector_t dFdu = control_vector_t::Zero();
225  state_vector_t x_local;
226  control_vector_t u_local;
227  SCALAR t_local;
228  this->getCurrentStateAndControl(x_local, u_local, t_local);
229  SCALAR dxdt_ref = this->evaluateIntermediate();
230 
231  for (size_t i = 0; i < CONTROL_DIM; ++i)
232  {
233  // inspired from http://en.wikipedia.org/wiki/Numerical_differentiation#Practical_considerations_using_floating_point_arithmetic
234  SCALAR h = eps_ * std::max(std::abs(u_local(i)), 1.0);
235  volatile SCALAR u_ph = u_local(i) + h;
236  SCALAR dup = u_ph - u_local(i);
237 
238  control_vector_t u_perturbed = u_local;
239  u_perturbed(i) = u_ph;
240 
241  // get evaluation of f(x,u)
242  this->setCurrentStateAndControl(x_local, u_perturbed, t_local);
243  SCALAR dxdt = this->evaluateIntermediate();
244 
246  {
247  SCALAR dxdt_low;
248 
249  volatile SCALAR u_mh = u_local(i) - h;
250  SCALAR dum = u_local(i) - u_mh;
251 
252  u_perturbed = u_local;
253  u_perturbed(i) = u_mh;
254  this->setCurrentStateAndControl(x_local, u_perturbed, t_local);
255  dxdt_low = this->evaluateIntermediate();
256 
257  dFdu(i, 0) = (dxdt - dxdt_low) / (dup + dum);
258  }
259  else
260  {
261  dFdu(i, 0) = (dxdt - dxdt_ref) / dup;
262  }
263  }
264 
265  return dFdu;
266 }
267 
268 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
270 {
274 }
275 
276 
277 // add terms
278 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
280  std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>> term,
281  bool verbose)
282 {
283  intermediateCostAnalytical_.push_back(term);
284  if (verbose)
285  {
286  std::string name = term->getName();
287  std::cout << "Trying to add term as intermediate" << std::endl;
288  }
289 
290  return intermediateCostAnalytical_.size() - 1;
291 }
292 
293 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
295  std::shared_ptr<TermBase<STATE_DIM, CONTROL_DIM, SCALAR>> term,
296  bool verbose)
297 {
298  finalCostAnalytical_.push_back(term);
299  if (verbose)
300  {
301  std::string name = term->getName();
302  std::cout << "Trying to add term as final" << std::endl;
303  }
304 
305  return finalCostAnalytical_.size() - 1;
306 }
307 
308 
309 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
311 {
312  SCALAR y = SCALAR(0.0);
313 
314  for (auto it : this->intermediateCostAnalytical_)
315  {
316  if (!it->isActiveAtTime(this->t_))
317  {
318  continue;
319  }
320  y += it->computeActivation(this->t_) * it->eval(this->x_, this->u_, this->t_);
321  }
322 
323  return y;
324 }
325 
326 
327 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
329 {
330  SCALAR y = SCALAR(0.0);
331 
332  for (auto it : this->finalCostAnalytical_)
333  y += it->evaluate(this->x_, this->u_, this->t_);
334 
335  return y;
336 }
337 
338 
339 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
342 {
343  state_vector_t derivative;
344  derivative.setZero();
345 
346  for (auto it : this->intermediateCostAnalytical_)
347  {
348  if (!it->isActiveAtTime(this->t_))
349  {
350  continue;
351  }
352  derivative += it->computeActivation(this->t_) * it->stateDerivative(this->x_, this->u_, this->t_);
353  }
354 
355  return derivative;
356 }
357 
358 
359 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
362 {
363  state_vector_t derivative;
364  derivative.setZero();
365 
366  for (auto it : this->finalCostAnalytical_)
367  derivative += it->stateDerivative(this->x_, this->u_, this->t_);
368 
369  return derivative;
370 }
371 
372 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
375 {
376  state_matrix_t derivative;
377  derivative.setZero();
378 
379  for (auto it : this->intermediateCostAnalytical_)
380  {
381  if (!it->isActiveAtTime(this->t_))
382  {
383  continue;
384  }
385  derivative += it->computeActivation(this->t_) * it->stateSecondDerivative(this->x_, this->u_, this->t_);
386  }
387 
388  return derivative;
389 }
390 
391 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
394 {
395  state_matrix_t derivative;
396  derivative.setZero();
397 
398  for (auto it : this->finalCostAnalytical_)
399  derivative += it->stateSecondDerivative(this->x_, this->u_, this->t_);
400 
401  return derivative;
402 }
403 
404 
405 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
408 {
409  control_vector_t derivative;
410  derivative.setZero();
411 
412  for (auto it : this->intermediateCostAnalytical_)
413  {
414  if (!it->isActiveAtTime(this->t_))
415  {
416  continue;
417  }
418  derivative += it->computeActivation(this->t_) * it->controlDerivative(this->x_, this->u_, this->t_);
419  }
420 
421  return derivative;
422 }
423 
424 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
427 {
428  control_vector_t derivative;
429  derivative.setZero();
430 
431  for (auto it : this->finalCostAnalytical_)
432  derivative += it->controlDerivative(this->x_, this->u_, this->t_);
433 
434  return derivative;
435 }
436 
437 // get control second derivatives
438 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
441 {
442  control_matrix_t derivative;
443  derivative.setZero();
444 
445  for (auto it : this->intermediateCostAnalytical_)
446  {
447  if (!it->isActiveAtTime(this->t_))
448  {
449  continue;
450  }
451  derivative += it->computeActivation(this->t_) * it->controlSecondDerivative(this->x_, this->u_, this->t_);
452  }
453 
454  return derivative;
455 }
456 
457 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
460 {
461  control_matrix_t derivative;
462  derivative.setZero();
463 
464  for (auto it : this->finalCostAnalytical_)
465  derivative += it->controlSecondDerivative(this->x_, this->u_, this->t_);
466 
467  return derivative;
468 }
469 
470 // get state-control derivatives
471 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
474 {
475  control_state_matrix_t derivative;
476  derivative.setZero();
477 
478  for (auto it : this->intermediateCostAnalytical_)
479  {
480  if (!it->isActiveAtTime(this->t_))
481  {
482  continue;
483  }
484  derivative += it->computeActivation(this->t_) * it->stateControlDerivative(this->x_, this->u_, this->t_);
485  }
486 
487  return derivative;
488 }
489 
490 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
493 {
494  control_state_matrix_t derivative;
495  derivative.setZero();
496 
497  for (auto it : this->finalCostAnalytical_)
498  derivative += it->stateControlDerivative(this->x_, this->u_, this->t_);
499 
500  return derivative;
501 }
502 
503 } // namespace optcon
504 } // namespace ct
std::vector< std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > > intermediateCostAnalytical_
Definition: CostFunctionQuadratic.hpp:238
control_state_matrix_t stateControlDerivativeIntermediateBase()
evaluate intermediate analytical control mixed state control derivatives
Definition: CostFunctionQuadratic-impl.hpp:473
control_matrix_t controlSecondDerivativeIntermediateBase()
evaluate intermediate analytical control second derivatives
Definition: CostFunctionQuadratic-impl.hpp:440
virtual state_vector_t stateDerivativeIntermediate()=0
Computes intermediate-cost first-order derivative with respect to state.
SCALAR eps_
stepsize for numerical differentiation
Definition: CostFunctionQuadratic.hpp:232
state_vector_t x_
Definition: CostFunction.hpp:103
virtual SCALAR evaluateIntermediate()=0
evaluate intermediate costs
A base function for cost functions. All cost functions should derive from this.
Definition: CostFunction.hpp:25
virtual void setCurrentStateAndControl(const state_vector_t &x, const control_vector_t &u, const SCALAR &t=SCALAR(0.0))
Definition: CostFunction-impl.hpp:30
SCALAR evaluateIntermediateBase()
evaluate intermediate analytical cost terms
Definition: CostFunctionQuadratic-impl.hpp:310
virtual void updateReferenceControl(const control_vector_t &u_ref)
update the reference control for intermediate cost terms
Definition: CostFunctionQuadratic-impl.hpp:105
Eigen::Matrix< SCALAR, CONTROL_DIM, STATE_DIM > control_state_matrix_t
Definition: CostFunctionQuadratic.hpp:36
virtual void updateFinalState(const state_vector_t &x_final)
update the reference state for final cost terms
Definition: CostFunctionQuadratic-impl.hpp:98
virtual void updateReferenceState(const state_vector_t &x_ref)
update the reference state for intermediate cost terms
Definition: CostFunctionQuadratic-impl.hpp:91
virtual void initialize()
initialize the cost function (e.g. to be used in CostFunctionAD)
Definition: CostFunctionQuadratic-impl.hpp:269
SCALAR t_
Definition: CostFunction.hpp:105
virtual control_state_matrix_t stateControlDerivativeTerminal()
Computes final-cost derivative with respect to state and control.
Definition: CostFunctionQuadratic-impl.hpp:85
An interface for a term, supporting both analytical and auto-diff terms.
Definition: TermBase.hpp:30
state_vector_t stateDerivativeTerminalBase()
evaluate terminal analytical state derivatives
Definition: CostFunctionQuadratic-impl.hpp:361
Describes a cost function with a quadratic approximation, i.e. one that can compute first and second ...
Definition: CostFunctionQuadratic.hpp:29
virtual void loadFromConfigFile(const std::string &filename, bool verbose=false)
Loads cost function from config file.
Definition: CostFunctionQuadratic-impl.hpp:63
state_matrix_t stateSecondDerivativeIntermediateBase()
evaluate intermediate analytical state second derivatives
Definition: CostFunctionQuadratic-impl.hpp:374
control_vector_t controlDerivativeIntermediateBase()
evaluate intermediate analytical control derivatives
Definition: CostFunctionQuadratic-impl.hpp:407
CppAD::AD< CppAD::cg::CG< double > > SCALAR
control_vector_t controlDerivativeTerminalBase()
evaluate terminal analytical control derivatives
Definition: CostFunctionQuadratic-impl.hpp:426
state_matrix_t stateSecondDerivativeTerminalBase()
evaluate terminal analytical state second derivatives
Definition: CostFunctionQuadratic-impl.hpp:393
state_vector_t stateDerivativeIntermediateBase()
evaluate intermediate analytical state derivatives
Definition: CostFunctionQuadratic-impl.hpp:341
SCALAR evaluateTerminalBase()
evaluate terminal analytical cost terms
Definition: CostFunctionQuadratic-impl.hpp:328
virtual size_t addIntermediateTerm(std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR >> term, bool verbose=false)
Adds an intermediate term.
Definition: CostFunctionQuadratic-impl.hpp:279
for i
Definition: mpc_unittest_plotting.m:14
CostFunctionQuadratic()
Definition: CostFunctionQuadratic-impl.hpp:12
std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > getIntermediateTermByName(const std::string &name)
Definition: CostFunctionQuadratic-impl.hpp:153
virtual size_t addFinalTerm(std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR >> term, bool verbose=false)
Adds a final term.
Definition: CostFunctionQuadratic-impl.hpp:294
std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > getIntermediateTermById(const size_t id)
Definition: CostFunctionQuadratic-impl.hpp:139
bool stateDerivativeIntermediateTest(bool verbose=false)
compare the state derivative against numerical differentiation
Definition: CostFunctionQuadratic-impl.hpp:112
Eigen::Matrix< SCALAR, CONTROL_DIM, CONTROL_DIM > control_matrix_t
Definition: CostFunctionQuadratic.hpp:35
control_vector_t u_
Definition: CostFunction.hpp:104
bool doubleSidedDerivative_
use double sided derivatives in numerical differentiation
Definition: CostFunctionQuadratic.hpp:235
bool controlDerivativeIntermediateTest(bool verbose=false)
compare the control derivative against numerical differentiation
Definition: CostFunctionQuadratic-impl.hpp:125
virtual control_vector_t controlDerivativeIntermediate()=0
Computes intermediate-cost first-order derivative with respect to control.
virtual control_vector_t controlDerivativeTerminal()
Computes terminal-cost first-order derivative with respect to control.
Definition: CostFunctionQuadratic-impl.hpp:71
Eigen::Matrix< double, nStates, nStates > state_matrix_t
const bool verbose
Definition: ConstraintComparison.h:18
control_vector_t controlDerivativeIntermediateNumDiff()
compute the control derivative by numerical differentiation (can be used for testing) ...
Definition: CostFunctionQuadratic-impl.hpp:222
control_matrix_t controlSecondDerivativeTerminalBase()
evaluate terminal analytical control second derivatives
Definition: CostFunctionQuadratic-impl.hpp:459
control_state_matrix_t stateControlDerivativeTerminalBase()
evaluate terminal analytical control mixed state control derivatives
Definition: CostFunctionQuadratic-impl.hpp:492
std::vector< std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > > finalCostAnalytical_
Definition: CostFunctionQuadratic.hpp:241
virtual void getCurrentStateAndControl(Eigen::Matrix< SCALAR, STATE_DIM, 1 > &x, Eigen::Matrix< SCALAR, CONTROL_DIM, 1 > &u, SCALAR &t) const
sets current state, control and time
Definition: CostFunction-impl.hpp:40
virtual control_matrix_t controlSecondDerivativeTerminal()
Computes final-cost second-order derivative with respect to input.
Definition: CostFunctionQuadratic-impl.hpp:78
state_vector_t stateDerivativeIntermediateNumDiff()
compute the state derivative by numerical differentiation (can be used for testing) ...
Definition: CostFunctionQuadratic-impl.hpp:175
virtual ~CostFunctionQuadratic()
Definition: CostFunctionQuadratic-impl.hpp:40
std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > getFinalTermById(const size_t id)
Definition: CostFunctionQuadratic-impl.hpp:146
std::shared_ptr< TermBase< STATE_DIM, CONTROL_DIM, SCALAR > > getFinalTermByName(const std::string &name)
Definition: CostFunctionQuadratic-impl.hpp:164