10 #ifdef CROCODDYL_WITH_MULTITHREADING
14 #include "crocoddyl/core/solvers/fddp.hpp"
19 : SolverDDP(problem), dg_(0), dq_(0), dv_(0), th_acceptnegstep_(2) {}
21 SolverFDDP::~SolverFDDP() {}
23 bool SolverFDDP::solve(
const std::vector<Eigen::VectorXd>& init_xs,
24 const std::vector<Eigen::VectorXd>& init_us,
25 const std::size_t maxiter,
const bool is_feasible,
26 const double init_reg) {
27 START_PROFILER(
"SolverFDDP::solve");
28 if (problem_->is_updated()) {
33 setCandidate(init_xs, init_us, is_feasible);
35 if (std::isnan(init_reg)) {
42 was_feasible_ =
false;
44 bool recalcDiff =
true;
45 for (iter_ = 0; iter_ < maxiter; ++iter_) {
48 computeDirection(recalcDiff);
49 }
catch (std::exception& e) {
51 increaseRegularization();
52 if (preg_ == reg_max_) {
64 for (std::vector<double>::const_iterator it = alphas_.begin();
65 it != alphas_.end(); ++it) {
69 dV_ = tryStep(steplength_);
70 }
catch (std::exception& e) {
74 dVexp_ = steplength_ * (d_[0] + 0.5 * steplength_ * d_[1]);
77 if (std::abs(d_[0]) < th_grad_ || dV_ > th_acceptstep_ * dVexp_) {
78 was_feasible_ = is_feasible_;
79 setCandidate(xs_try_, us_try_, (was_feasible_) || (steplength_ == 1));
87 was_feasible_ = is_feasible_;
88 setCandidate(xs_try_, us_try_, (was_feasible_) || (steplength_ == 1));
96 if (steplength_ > th_stepdec_) {
97 decreaseRegularization();
99 if (steplength_ <= th_stepinc_) {
100 increaseRegularization();
101 if (preg_ == reg_max_) {
102 STOP_PROFILER(
"SolverFDDP::solve");
108 const std::size_t n_callbacks = callbacks_.size();
109 for (std::size_t c = 0; c < n_callbacks; ++c) {
110 CallbackAbstract& callback = *callbacks_[c];
114 if (was_feasible_ && stop_ < th_stop_) {
115 STOP_PROFILER(
"SolverFDDP::solve");
119 STOP_PROFILER(
"SolverFDDP::solve");
125 const std::size_t T = this->problem_->get_T();
132 problem_->get_terminalModel()->get_state()->diff(xs_try_.back(), xs_.back(),
134 fTVxx_p_.noalias() = Vxx_.back() * dx_.back();
135 dv_ -= fs_.back().dot(fTVxx_p_);
136 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
137 problem_->get_runningModels();
139 for (std::size_t t = 0; t < T; ++t) {
140 models[t]->get_state()->diff(xs_try_[t], xs_[t], dx_[t]);
141 fTVxx_p_.noalias() = Vxx_[t] * dx_[t];
142 dv_ -= fs_[t].dot(fTVxx_p_);
153 const std::size_t T = this->problem_->get_T();
155 dg_ -= Vx_.back().dot(fs_.back());
156 fTVxx_p_.noalias() = Vxx_.back() * fs_.back();
157 dq_ += fs_.back().dot(fTVxx_p_);
159 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
160 problem_->get_runningModels();
161 for (std::size_t t = 0; t < T; ++t) {
162 const std::size_t nu = models[t]->get_nu();
164 dg_ += Qu_[t].dot(k_[t]);
165 dq_ -= k_[t].dot(Quuk_[t]);
168 dg_ -= Vx_[t].dot(fs_[t]);
169 fTVxx_p_.noalias() = Vxx_[t] * fs_[t];
170 dq_ += fs_[t].dot(fTVxx_p_);
175 void SolverFDDP::forwardPass(
const double steplength) {
176 if (steplength > 1. || steplength < 0.) {
177 throw_pretty(
"Invalid argument: "
178 <<
"invalid step length, value is between 0. to 1.");
180 START_PROFILER(
"SolverFDDP::forwardPass");
182 xnext_ = problem_->get_x0();
183 const std::size_t T = problem_->get_T();
184 const std::vector<std::shared_ptr<ActionModelAbstract> >& models =
185 problem_->get_runningModels();
186 const std::vector<std::shared_ptr<ActionDataAbstract> >& datas =
187 problem_->get_runningDatas();
188 if ((is_feasible_) || (steplength == 1)) {
189 for (std::size_t t = 0; t < T; ++t) {
190 const std::shared_ptr<ActionModelAbstract>& m = models[t];
191 const std::shared_ptr<ActionDataAbstract>& d = datas[t];
192 const std::size_t nu = m->get_nu();
195 m->get_state()->diff(xs_[t], xs_try_[t], dx_[t]);
197 us_try_[t].noalias() = us_[t] - k_[t] * steplength - K_[t] * dx_[t];
198 m->calc(d, xs_try_[t], us_try_[t]);
200 m->calc(d, xs_try_[t]);
203 cost_try_ += d->cost;
205 if (raiseIfNaN(cost_try_)) {
206 STOP_PROFILER(
"SolverFDDP::forwardPass");
207 throw_pretty(
"forward_error");
209 if (raiseIfNaN(xnext_.lpNorm<Eigen::Infinity>())) {
210 STOP_PROFILER(
"SolverFDDP::forwardPass");
211 throw_pretty(
"forward_error");
215 const std::shared_ptr<ActionModelAbstract>& m =
216 problem_->get_terminalModel();
217 const std::shared_ptr<ActionDataAbstract>& d = problem_->get_terminalData();
218 xs_try_.back() = xnext_;
219 m->calc(d, xs_try_.back());
220 cost_try_ += d->cost;
222 if (raiseIfNaN(cost_try_)) {
223 STOP_PROFILER(
"SolverFDDP::forwardPass");
224 throw_pretty(
"forward_error");
227 for (std::size_t t = 0; t < T; ++t) {
228 const std::shared_ptr<ActionModelAbstract>& m = models[t];
229 const std::shared_ptr<ActionDataAbstract>& d = datas[t];
230 const std::size_t nu = m->get_nu();
231 m->get_state()->integrate(xnext_, fs_[t] * (steplength - 1), xs_try_[t]);
232 m->get_state()->diff(xs_[t], xs_try_[t], dx_[t]);
234 us_try_[t].noalias() = us_[t] - k_[t] * steplength - K_[t] * dx_[t];
235 m->calc(d, xs_try_[t], us_try_[t]);
237 m->calc(d, xs_try_[t]);
240 cost_try_ += d->cost;
242 if (raiseIfNaN(cost_try_)) {
243 STOP_PROFILER(
"SolverFDDP::forwardPass");
244 throw_pretty(
"forward_error");
246 if (raiseIfNaN(xnext_.lpNorm<Eigen::Infinity>())) {
247 STOP_PROFILER(
"SolverFDDP::forwardPass");
248 throw_pretty(
"forward_error");
252 const std::shared_ptr<ActionModelAbstract>& m =
253 problem_->get_terminalModel();
254 const std::shared_ptr<ActionDataAbstract>& d = problem_->get_terminalData();
255 m->get_state()->integrate(xnext_, fs_.back() * (steplength - 1),
257 m->calc(d, xs_try_.back());
258 cost_try_ += d->cost;
260 if (raiseIfNaN(cost_try_)) {
261 STOP_PROFILER(
"SolverFDDP::forwardPass");
262 throw_pretty(
"forward_error");
265 STOP_PROFILER(
"SolverFDDP::forwardPass");
271 if (0. > th_acceptnegstep) {
273 "Invalid argument: " <<
"th_acceptnegstep value has to be positive.");
void set_th_acceptnegstep(const double th_acceptnegstep)
Modify the threshold used for accepting step along ascent direction.
double dg_
Internal data for computing the expected improvement.
double dv_
Internal data for computing the expected improvement.
virtual const Eigen::Vector2d & expectedImprovement()
Return the expected improvement from a given current search direction .
double dq_
Internal data for computing the expected improvement.
double get_th_acceptnegstep() const
Return the threshold used for accepting step along ascent direction.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW SolverFDDP(std::shared_ptr< ShootingProblem > problem)
Initialize the FDDP solver.
void updateExpectedImprovement()
Update internal values for computing the expected improvement.