control_limited_feasibility_driven_ddp_solver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2019-2020, University of Edinburgh, University of Oxford
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
33 
34 REGISTER_MOTIONSOLVER_TYPE("ControlLimitedFeasibilityDrivenDDPSolver", exotica::ControlLimitedFeasibilityDrivenDDPSolver)
35 
36 namespace exotica
37 {
38 void ControlLimitedFeasibilityDrivenDDPSolver::Instantiate(const ControlLimitedFeasibilityDrivenDDPSolverInitializer& init)
39 {
41  base_parameters_ = AbstractDDPSolverInitializer(ControlLimitedFeasibilityDrivenDDPSolverInitializer(exotica::Instantiable<exotica::ControlLimitedFeasibilityDrivenDDPSolverInitializer>::parameters_));
42 
43  clamp_to_control_limits_in_forward_pass_ = base_parameters_.ClampControlsInForwardPass;
44  initial_regularization_rate_ = base_parameters_.RegularizationRate;
45  th_stepinc_ = base_parameters_.ThresholdRegularizationIncrease;
46  th_stepdec_ = base_parameters_.ThresholdRegularizationDecrease;
47 
48  th_stop_ = parameters_.GradientToleranceConvergenceThreshold;
49  th_gradient_tolerance_ = parameters_.GradientTolerance;
50  th_acceptstep_ = parameters_.DescentStepAcceptanceThreshold;
51  th_acceptnegstep_ = parameters_.AscentStepAcceptanceThreshold;
52 }
53 
54 void ControlLimitedFeasibilityDrivenDDPSolver::AllocateData()
55 {
56  AbstractFeasibilityDrivenDDPSolver::AllocateData();
57 
58  Quu_inv_.resize(T_ - 1);
59  for (int t = 0; t < T_ - 1; ++t)
60  {
61  Quu_inv_[t] = Eigen::MatrixXd::Zero(NU_, NU_);
62  }
63 
64  du_lb_.resize(NU_);
65  du_ub_.resize(NU_);
66 }
67 
68 void ControlLimitedFeasibilityDrivenDDPSolver::ComputeGains(const int t)
69 {
70  if (!is_feasible_) // and assuming that we have control limits
71  {
72  // No control limits on this model: Use vanilla DDP
73  AbstractFeasibilityDrivenDDPSolver::ComputeGains(t);
74  return;
75  }
76 
77  du_lb_ = control_limits_.col(0) - us_[t];
78  du_ub_ = control_limits_.col(1) - us_[t];
79 
80  // TODO: Use pre-allocated BoxQP
81  BoxQPSolution boxqp_sol;
82  if (parameters_.UseNewBoxQP)
83  {
84  boxqp_sol = BoxQP(Quu_[t], Qu_[t], du_lb_, du_ub_, k_[t], 0.1, 100, 1e-5, ureg_, parameters_.BoxQPUsePolynomialLinesearch, parameters_.BoxQPUseCholeskyFactorization);
85  }
86  else
87  {
88  boxqp_sol = ExoticaBoxQP(Quu_[t], Qu_[t], du_lb_, du_ub_, k_[t], 0.1, 100, 1e-5, ureg_, parameters_.BoxQPUsePolynomialLinesearch, parameters_.BoxQPUseCholeskyFactorization);
89  }
90 
91  // Compute controls
92  Quu_inv_[t].setZero();
93  if (boxqp_sol.free_idx.size() > 0)
94  {
95  for (std::size_t i = 0; i < boxqp_sol.free_idx.size(); ++i)
96  {
97  for (std::size_t j = 0; j < boxqp_sol.free_idx.size(); ++j)
98  {
99  Quu_inv_[t](boxqp_sol.free_idx[i], boxqp_sol.free_idx[j]) = boxqp_sol.Hff_inv(i, j); // 8,8
100  }
101  }
102  }
103  K_[t].noalias() = Quu_inv_[t] * Qxu_[t].transpose();
104  k_[t].noalias() = -boxqp_sol.x;
105 
106  // The box-QP clamped the gradient direction; this is important for accounting
107  // the algorithm advancement (i.e. stopping criteria)
108  if (boxqp_sol.clamped_idx.size() > 0)
109  {
110  for (std::size_t i = 0; i < boxqp_sol.clamped_idx.size(); ++i)
111  {
112  Qu_[t](boxqp_sol.clamped_idx[i]) = 0.;
113  }
114  }
115 }
116 
117 } // namespace exotica
Eigen::MatrixXd Hff_inv
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
std::vector< size_t > clamped_idx
Eigen::VectorXd x
std::vector< size_t > free_idx
BoxQPSolution ExoticaBoxQP(const Eigen::MatrixXd &H, const Eigen::VectorXd &q, const Eigen::VectorXd &b_low, const Eigen::VectorXd &b_high, const Eigen::VectorXd &x_init, const double gamma, const int max_iterations, const double epsilon, const double lambda, bool use_polynomial_linesearch=false, bool use_cholesky_factorization=false)
BoxQPSolution BoxQP(const Eigen::MatrixXd &H, const Eigen::VectorXd &q, const Eigen::VectorXd &b_low, const Eigen::VectorXd &b_high, const Eigen::VectorXd &x_init, const double th_acceptstep, const int max_iterations, const double th_gradient_tolerance, const double lambda, bool use_polynomial_linesearch=true, bool use_cholesky_factorization=true)


exotica_ddp_solver
Author(s): Traiko Dinev
autogenerated on Sat Apr 10 2021 02:36:21