11#include "crocoddyl/core/solvers/kkt.hpp" 15SolverKKT::SolverKKT(std::shared_ptr<ShootingProblem> problem)
23 was_feasible_(false) {
25 const std::size_t n_alphas = 10;
28 alphas_.resize(n_alphas);
29 for (std::size_t n = 0; n < n_alphas; ++n) {
30 alphas_[n] = 1. / pow(2., (
double)n);
34SolverKKT::~SolverKKT() {}
37 const std::vector<Eigen::VectorXd>& init_us,
38 const std::size_t maxiter,
const bool is_feasible,
46 }
catch (std::exception& e) {
48 if (
preg_ == reg_max_) {
58 for (std::vector<double>::const_iterator it = alphas_.begin();
59 it != alphas_.end(); ++it) {
63 }
catch (std::exception& e) {
75 const std::size_t n_callbacks =
callbacks_.size();
76 if (n_callbacks != 0) {
77 for (std::size_t c = 0; c < n_callbacks; ++c) {
90 const std::size_t T =
problem_->get_T();
95 const Eigen::VectorBlock<Eigen::VectorXd, Eigen::Dynamic> p_x =
96 primal_.segment(0, ndx_);
97 const Eigen::VectorBlock<Eigen::VectorXd, Eigen::Dynamic> p_u =
98 primal_.segment(ndx_, nu_);
102 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
104 for (std::size_t t = 0; t < T; ++t) {
105 const std::size_t ndxi = models[t]->get_state()->get_ndx();
106 const std::size_t nui = models[t]->get_nu();
107 dxs_[t] = p_x.segment(ix, ndxi);
108 dus_[t] = p_u.segment(iu, nui);
109 lambdas_[t] = dual_.segment(ix, ndxi);
113 const std::size_t ndxi =
114 problem_->get_terminalModel()->get_state()->get_ndx();
115 dxs_.back() = p_x.segment(ix, ndxi);
116 lambdas_.back() = dual_.segment(ix, ndxi);
120 const std::size_t T =
problem_->get_T();
121 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
123 for (std::size_t t = 0; t < T; ++t) {
124 const std::shared_ptr<ActionModelAbstract>& m = models[t];
126 m->get_state()->integrate(
xs_[t], steplength * dxs_[t], xs_try_[t]);
127 if (m->get_nu() != 0) {
129 us_try_[t] += steplength * dus_[t];
132 const std::shared_ptr<ActionModelAbstract> m =
problem_->get_terminalModel();
133 m->get_state()->integrate(
xs_[T], steplength * dxs_[T], xs_try_[T]);
134 cost_try_ =
problem_->calc(xs_try_, us_try_);
135 return cost_ - cost_try_;
139 const std::size_t T =
problem_->get_T();
142 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
144 const std::vector<std::shared_ptr<ActionDataAbstract> >& datas =
146 for (std::size_t t = 0; t < T; ++t) {
147 const std::shared_ptr<ActionDataAbstract>& d = datas[t];
148 const std::size_t ndxi = models[t]->get_state()->get_ndx();
149 const std::size_t nui = models[t]->get_nu();
151 dF.segment(ix, ndxi) = lambdas_[t];
152 dF.segment(ix, ndxi).noalias() -= d->Fx.transpose() * lambdas_[t + 1];
153 dF.segment(ndx_ + iu, nui).noalias() = -lambdas_[t + 1].transpose() * d->Fu;
157 const std::size_t ndxi =
158 problem_->get_terminalModel()->get_state()->get_ndx();
159 dF.segment(ix, ndxi) = lambdas_.back();
160 stop_ = (kktref_.segment(0, ndx_ + nu_) + dF).squaredNorm() +
161 kktref_.segment(ndx_ + nu_, ndx_).squaredNorm();
166 d_ = Eigen::Vector2d::Zero();
168 d_(0) = -kktref_.segment(0, ndx_ + nu_).dot(primal_);
170 kkt_primal_.noalias() = kkt_.block(0, 0, ndx_ + nu_, ndx_ + nu_) * primal_;
171 d_(1) = -kkt_primal_.dot(primal_);
175const Eigen::MatrixXd& SolverKKT::get_kkt()
const {
return kkt_; }
177const Eigen::VectorXd& SolverKKT::get_kktref()
const {
return kktref_; }
179const Eigen::VectorXd& SolverKKT::get_primaldual()
const {
return primaldual_; }
181const std::vector<Eigen::VectorXd>& SolverKKT::get_dxs()
const {
return dxs_; }
183const std::vector<Eigen::VectorXd>& SolverKKT::get_dus()
const {
return dus_; }
185const std::vector<Eigen::VectorXd>& SolverKKT::get_lambdas()
const {
189std::size_t SolverKKT::get_nx()
const {
return nx_; }
191std::size_t SolverKKT::get_ndx()
const {
return ndx_; }
193std::size_t SolverKKT::get_nu()
const {
return nu_; }
195double SolverKKT::calcDiff() {
196 cost_ = problem_->calc(xs_, us_);
197 cost_ = problem_->calcDiff(xs_, us_);
200 const std::size_t cx0 =
201 problem_->get_runningModels()[0]->get_state()->get_ndx();
205 const std::size_t T = problem_->get_T();
206 kkt_.block(ndx_ + nu_, 0, ndx_, ndx_).setIdentity();
207 for (std::size_t t = 0; t < T; ++t) {
208 const std::shared_ptr<ActionModelAbstract>& m =
209 problem_->get_runningModels()[t];
210 const std::shared_ptr<ActionDataAbstract>& d =
211 problem_->get_runningDatas()[t];
212 const std::size_t ndxi = m->get_state()->get_ndx();
213 const std::size_t nui = m->get_nu();
217 m->get_state()->diff(problem_->get_x0(), xs_[0],
218 kktref_.segment(ndx_ + nu_, ndxi));
222 kkt_.block(ix, ix, ndxi, ndxi) = d->Lxx;
223 kkt_.block(ix, ndx_ + iu, ndxi, nui) = d->Lxu;
224 kkt_.block(ndx_ + iu, ix, nui, ndxi) = d->Lxu.transpose();
225 kkt_.block(ndx_ + iu, ndx_ + iu, nui, nui) = d->Luu;
226 kkt_.block(ndx_ + nu_ + cx0 + ix, ix, ndxi, ndxi) = -d->Fx;
227 kkt_.block(ndx_ + nu_ + cx0 + ix, ndx_ + iu, ndxi, nui) = -d->Fu;
230 kktref_.segment(ix, ndxi) = d->Lx;
231 kktref_.segment(ndx_ + iu, nui) = d->Lu;
232 m->get_state()->diff(d->xnext, xs_[t + 1],
233 kktref_.segment(ndx_ + nu_ + cx0 + ix, ndxi));
238 const std::shared_ptr<ActionDataAbstract>& df = problem_->get_terminalData();
239 const std::size_t ndxf =
240 problem_->get_terminalModel()->get_state()->get_ndx();
241 kkt_.block(ix, ix, ndxf, ndxf) = df->Lxx;
242 kktref_.segment(ix, ndxf) = df->Lx;
243 kkt_.block(0, ndx_ + nu_, ndx_ + nu_, ndx_) =
244 kkt_.block(ndx_ + nu_, 0, ndx_, ndx_ + nu_).transpose();
248void SolverKKT::computePrimalDual() {
249 primaldual_ = kkt_.lu().solve(-kktref_);
250 primal_ = primaldual_.segment(0, ndx_ + nu_);
251 dual_ = primaldual_.segment(ndx_ + nu_, ndx_);
254void SolverKKT::increaseRegularization() {
255 preg_ *= reg_incfactor_;
256 if (preg_ > reg_max_) {
262void SolverKKT::decreaseRegularization() {
263 preg_ /= reg_decfactor_;
264 if (preg_ < reg_min_) {
270void SolverKKT::allocateData() {
271 const std::size_t T = problem_->get_T();
274 lambdas_.resize(T + 1);
275 xs_try_.resize(T + 1);
281 const std::size_t nx = problem_->get_nx();
282 const std::size_t ndx = problem_->get_ndx();
283 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
284 problem_->get_runningModels();
285 for (std::size_t t = 0; t < T; ++t) {
286 const std::shared_ptr<ActionModelAbstract>& model = models[t];
288 xs_try_[t] = problem_->get_x0();
290 xs_try_[t] = Eigen::VectorXd::Constant(nx, NAN);
292 const std::size_t nu = model->get_nu();
293 us_try_[t] = Eigen::VectorXd::Constant(nu, NAN);
294 dxs_[t] = Eigen::VectorXd::Zero(ndx);
295 dus_[t] = Eigen::VectorXd::Zero(nu);
296 lambdas_[t] = Eigen::VectorXd::Zero(ndx);
303 xs_try_.back() = problem_->get_terminalModel()->get_state()->zero();
304 dxs_.back() = Eigen::VectorXd::Zero(ndx);
305 lambdas_.back() = Eigen::VectorXd::Zero(ndx);
308 kkt_.resize(2 * ndx_ + nu_, 2 * ndx_ + nu_);
310 kktref_.resize(2 * ndx_ + nu_);
312 primaldual_.resize(2 * ndx_ + nu_);
313 primaldual_.setZero();
314 primal_.resize(ndx_ + nu_);
316 kkt_primal_.resize(ndx_ + nu_);
317 kkt_primal_.setZero();
320 dF.resize(ndx_ + nu_);
Abstract class for solver callbacks.
Abstract class for optimal control solvers.
double dVexp_
Expected reduction in the cost function.
std::vector< Eigen::VectorXd > xs_
State trajectory.
double stop_
Value computed by stoppingCriteria()
bool is_feasible_
Label that indicates is the iteration is feasible.
std::shared_ptr< ShootingProblem > problem_
optimal control problem
std::vector< Eigen::VectorXd > us_
Control trajectory.
double th_acceptstep_
Threshold used for accepting step.
double th_stop_
Tolerance for stopping the algorithm.
void setCandidate(const std::vector< Eigen::VectorXd > &xs_warm=DEFAULT_VECTOR, const std::vector< Eigen::VectorXd > &us_warm=DEFAULT_VECTOR, const bool is_feasible=false)
Set the solver candidate trajectories .
double cost_
Cost for the current guess.
std::vector< std::shared_ptr< CallbackAbstract > > callbacks_
Callback functions.
double steplength_
< Current control regularization values
std::size_t iter_
Number of iteration performed by the solver.
double dV_
Reduction in the cost function computed by tryStep()
Eigen::Vector2d d_
LQ approximation of the expected improvement.
double preg_
Current primal-variable regularization value.
virtual bool solve(const std::vector< Eigen::VectorXd > &init_xs=DEFAULT_VECTOR, const std::vector< Eigen::VectorXd > &init_us=DEFAULT_VECTOR, const std::size_t maxiter=100, const bool is_feasible=false, const double regInit=1e-9)
Compute the optimal trajectory as lists of and terms.
virtual double tryStep(const double steplength=1)
Try a predefined step length and compute its cost improvement .
virtual const Eigen::Vector2d & expectedImprovement()
Return the expected improvement from a given current search direction .
virtual double stoppingCriteria()
Return a positive value that quantifies the algorithm termination.
virtual void computeDirection(const bool recalc=true)
Compute the search direction for the current guess .