- 3.0.2 optimal control module.
FHDTLQR-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  std::shared_ptr<CostFunctionQuadratic<STATE_DIM, CONTROL_DIM, SCALAR>> costFunction)
14  : costFunction_(costFunction)
15 {
16 }
17 
18 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
20 {
21 }
22 
23 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
25  const control_vector_array_t& u_trajectory,
26  const state_matrix_array_t& A,
28  SCALAR dt,
30  bool performNumericalChecks)
31 {
32  size_t N = x_trajectory.size() - 1;
33  solve(x_trajectory, u_trajectory, A, B, N, dt, K, performNumericalChecks);
34 }
35 
36 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
38  const control_vector_array_t& u_trajectory,
39  std::shared_ptr<core::LinearSystem<STATE_DIM, CONTROL_DIM, SCALAR>> derivatives,
40  SCALAR dt,
42  bool performNumericalChecks)
43 {
44  size_t N = x_trajectory.size() - 1;
45 
48 
49  linearizeModel(x_trajectory, u_trajectory, N, dt, derivatives, A, B);
50 
51  solve(x_trajectory, u_trajectory, A, B, N, dt, K, performNumericalChecks);
52 }
53 
54 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
56  const control_vector_array_t& u_trajectory,
57  size_t N,
58  SCALAR dt,
59  std::shared_ptr<core::LinearSystem<STATE_DIM, CONTROL_DIM, SCALAR>>& derivatives,
62 {
63  A.resize(N);
64  B.resize(N);
65 
66  for (int i = 0; i < N; i++)
67  {
68  A[i] = state_matrix_t::Identity() + dt * derivatives->getDerivativeState(x_trajectory[i], u_trajectory[i]);
69  B[i] = dt * derivatives->getDerivativeControl(x_trajectory[i], u_trajectory[i]);
70  }
71 }
72 
73 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR>
75  const control_vector_array_t& u_trajectory,
76  const state_matrix_array_t& A,
78  size_t N,
79  SCALAR dt,
81  bool performNumericalChecks)
82 {
83  if (x_trajectory.size() != N + 1)
84  {
85  throw std::runtime_error("State trajectory does not have correct length. State trajectory length: " +
86  std::to_string(x_trajectory.size()) + ", should be: " + std::to_string(N + 1));
87  }
88  if (u_trajectory.size() != N)
89  {
90  throw std::runtime_error("Input trajectory does not have correct length. Input trajectory length: " +
91  std::to_string(u_trajectory.size()) + ", should be: " + std::to_string(N));
92  }
93  if (A.size() != N)
94  {
95  throw std::runtime_error("Linearization A does not have correct length. Linearization length: " +
96  std::to_string(A.size()) + ", should be: " + std::to_string(N));
97  }
98  if (B.size() != N)
99  {
100  throw std::runtime_error("Linearization B does not have correct length. Linearization length: " +
101  std::to_string(B.size()) + ", should be: " + std::to_string(N));
102  }
103 
104  K.resize(N);
105 
106  // initialize cost-to-go
107  costFunction_->setCurrentStateAndControl(x_trajectory[N], control_vector_t::Zero(), dt * N);
108  state_matrix_t P = costFunction_->stateSecondDerivativeTerminal();
109 
110  if (performNumericalChecks)
111  {
112  Eigen::Matrix<SCALAR, -1, 1> realEigVals = P.eigenvalues().real();
113  if (realEigVals.minCoeff() < 0.0)
114  {
115  std::cout << "P: " << std::endl << P;
116  throw std::runtime_error("[LQR] Q is not positive semi-definite.");
117  }
118  }
119 
120  for (int i = N - 1; i >= 0; i--)
121  {
122  costFunction_->setCurrentStateAndControl(x_trajectory[i], u_trajectory[i], i * dt);
123 
124  state_matrix_t Q = costFunction_->stateSecondDerivativeIntermediate() * dt;
125 
126  control_matrix_t R = costFunction_->controlSecondDerivativeIntermediate() * dt;
127 
128  if (performNumericalChecks)
129  {
130  if (Q.minCoeff() < 0.0)
131  {
132  std::cout << "Q: " << std::endl << Q;
133  throw std::runtime_error("[LQR] Q contains negative entries.");
134  }
135  if (R.minCoeff() < 0.0)
136  {
137  std::cout << "R: " << std::endl << R;
138  throw std::runtime_error("[LQR] R contains negative entries.");
139  }
140  if (R.diagonal().minCoeff() <= 0.0)
141  {
142  std::cout << "R: " << std::endl << R;
143  throw std::runtime_error("[LQR] R contains zero entries on the diagonal.");
144  }
145  if (!Q.isDiagonal())
146  {
147  std::cout << "[LQR] Warning: Q is not diagonal." << std::endl;
148  }
149  if (!R.isDiagonal())
150  {
151  std::cout << "[LQR] Warning: R is not diagonal." << std::endl;
152  }
153  }
154 
155  //ricattiEq_.iterateNaive(Q, R, A, B, P, K[i]);
156  ricattiEq_.iterateRobust(Q, R, A[i], B[i], P, K[i]);
157  }
158 }
159 
160 } // namespace optcon
161 } // namespace ct
Eigen::Matrix< SCALAR, STATE_DIM, STATE_DIM > state_matrix_t
Definition: FHDTLQR.hpp:44
const double dt
Definition: LQOCSolverTiming.cpp:18
Describes a cost function with a quadratic approximation, i.e. one that can compute first and second ...
Definition: CostFunctionQuadratic.hpp:29
Finite-Horizon Discrete Time LQR.
Definition: FHDTLQR.hpp:38
CppAD::AD< CppAD::cg::CG< double > > SCALAR
for i
Definition: mpc_unittest_plotting.m:14
FHDTLQR(std::shared_ptr< CostFunctionQuadratic< STATE_DIM, CONTROL_DIM, SCALAR >> costFunction)
Constructor.
Definition: FHDTLQR-impl.hpp:12
void designController(const state_vector_array_t &x_trajectory, const control_vector_array_t &u_trajectory, const state_matrix_array_t &A, const control_gain_matrix_array_t &B, SCALAR dt, control_feedback_array_t &K, bool performNumericalChecks=true)
design a time-varying feedback trajectory using user-provided matrices A and B
Definition: FHDTLQR-impl.hpp:24
~FHDTLQR()
Definition: FHDTLQR-impl.hpp:19
Eigen::Matrix< SCALAR, CONTROL_DIM, CONTROL_DIM > control_matrix_t
Definition: FHDTLQR.hpp:45