10 #ifdef CROCODDYL_WITH_MULTITHREADING
14 #include "crocoddyl/core/solvers/fddp.hpp"
15 #include "crocoddyl/core/utils/exception.hpp"
20 : SolverDDP(problem), dg_(0), dq_(0), dv_(0), th_acceptnegstep_(2) {}
22 SolverFDDP::~SolverFDDP() {}
24 bool SolverFDDP::solve(
const std::vector<Eigen::VectorXd>& init_xs,
25 const std::vector<Eigen::VectorXd>& init_us,
26 const std::size_t maxiter,
const bool is_feasible,
27 const double init_reg) {
28 START_PROFILER(
"SolverFDDP::solve");
29 if (problem_->is_updated()) {
34 setCandidate(init_xs, init_us, is_feasible);
36 if (std::isnan(init_reg)) {
43 was_feasible_ =
false;
45 bool recalcDiff =
true;
46 for (iter_ = 0; iter_ < maxiter; ++iter_) {
49 computeDirection(recalcDiff);
50 }
catch (std::exception& e) {
52 increaseRegularization();
53 if (preg_ == reg_max_) {
65 for (std::vector<double>::const_iterator it = alphas_.begin();
66 it != alphas_.end(); ++it) {
70 dV_ = tryStep(steplength_);
71 }
catch (std::exception& e) {
75 dVexp_ = steplength_ * (d_[0] + 0.5 * steplength_ * d_[1]);
78 if (std::abs(d_[0]) < th_grad_ || dV_ > th_acceptstep_ * dVexp_) {
79 was_feasible_ = is_feasible_;
80 setCandidate(xs_try_, us_try_, (was_feasible_) || (steplength_ == 1));
88 was_feasible_ = is_feasible_;
89 setCandidate(xs_try_, us_try_, (was_feasible_) || (steplength_ == 1));
97 if (steplength_ > th_stepdec_) {
98 decreaseRegularization();
100 if (steplength_ <= th_stepinc_) {
101 increaseRegularization();
102 if (preg_ == reg_max_) {
103 STOP_PROFILER(
"SolverFDDP::solve");
109 const std::size_t n_callbacks = callbacks_.size();
110 for (std::size_t c = 0; c < n_callbacks; ++c) {
111 CallbackAbstract& callback = *callbacks_[c];
115 if (was_feasible_ && stop_ < th_stop_) {
116 STOP_PROFILER(
"SolverFDDP::solve");
120 STOP_PROFILER(
"SolverFDDP::solve");
126 const std::size_t T = this->problem_->get_T();
133 problem_->get_terminalModel()->get_state()->diff(xs_try_.back(), xs_.back(),
135 fTVxx_p_.noalias() = Vxx_.back() * dx_.back();
136 dv_ -= fs_.back().dot(fTVxx_p_);
137 const std::vector<boost::shared_ptr<ActionModelAbstract> >& models =
138 problem_->get_runningModels();
140 for (std::size_t t = 0; t < T; ++t) {
141 models[t]->get_state()->diff(xs_try_[t], xs_[t], dx_[t]);
142 fTVxx_p_.noalias() = Vxx_[t] * dx_[t];
143 dv_ -= fs_[t].dot(fTVxx_p_);
154 const std::size_t T = this->problem_->get_T();
156 dg_ -= Vx_.back().dot(fs_.back());
157 fTVxx_p_.noalias() = Vxx_.back() * fs_.back();
158 dq_ += fs_.back().dot(fTVxx_p_);
160 const std::vector<boost::shared_ptr<ActionModelAbstract> >& models =
161 problem_->get_runningModels();
162 for (std::size_t t = 0; t < T; ++t) {
163 const std::size_t nu = models[t]->get_nu();
165 dg_ += Qu_[t].dot(k_[t]);
166 dq_ -= k_[t].dot(Quuk_[t]);
169 dg_ -= Vx_[t].dot(fs_[t]);
170 fTVxx_p_.noalias() = Vxx_[t] * fs_[t];
171 dq_ += fs_[t].dot(fTVxx_p_);
176 void SolverFDDP::forwardPass(
const double steplength) {
177 if (steplength > 1. || steplength < 0.) {
178 throw_pretty(
"Invalid argument: "
179 <<
"invalid step length, value is between 0. to 1.");
181 START_PROFILER(
"SolverFDDP::forwardPass");
183 xnext_ = problem_->get_x0();
184 const std::size_t T = problem_->get_T();
185 const std::vector<boost::shared_ptr<ActionModelAbstract> >& models =
186 problem_->get_runningModels();
187 const std::vector<boost::shared_ptr<ActionDataAbstract> >& datas =
188 problem_->get_runningDatas();
189 if ((is_feasible_) || (steplength == 1)) {
190 for (std::size_t t = 0; t < T; ++t) {
191 const boost::shared_ptr<ActionModelAbstract>& m = models[t];
192 const boost::shared_ptr<ActionDataAbstract>& d = datas[t];
193 const std::size_t nu = m->get_nu();
196 m->get_state()->diff(xs_[t], xs_try_[t], dx_[t]);
198 us_try_[t].noalias() = us_[t] - k_[t] * steplength - K_[t] * dx_[t];
199 m->calc(d, xs_try_[t], us_try_[t]);
201 m->calc(d, xs_try_[t]);
204 cost_try_ += d->cost;
206 if (raiseIfNaN(cost_try_)) {
207 STOP_PROFILER(
"SolverFDDP::forwardPass");
208 throw_pretty(
"forward_error");
210 if (raiseIfNaN(xnext_.lpNorm<Eigen::Infinity>())) {
211 STOP_PROFILER(
"SolverFDDP::forwardPass");
212 throw_pretty(
"forward_error");
216 const boost::shared_ptr<ActionModelAbstract>& m =
217 problem_->get_terminalModel();
218 const boost::shared_ptr<ActionDataAbstract>& d =
219 problem_->get_terminalData();
220 xs_try_.back() = xnext_;
221 m->calc(d, xs_try_.back());
222 cost_try_ += d->cost;
224 if (raiseIfNaN(cost_try_)) {
225 STOP_PROFILER(
"SolverFDDP::forwardPass");
226 throw_pretty(
"forward_error");
229 for (std::size_t t = 0; t < T; ++t) {
230 const boost::shared_ptr<ActionModelAbstract>& m = models[t];
231 const boost::shared_ptr<ActionDataAbstract>& d = datas[t];
232 const std::size_t nu = m->get_nu();
233 m->get_state()->integrate(xnext_, fs_[t] * (steplength - 1), xs_try_[t]);
234 m->get_state()->diff(xs_[t], xs_try_[t], dx_[t]);
236 us_try_[t].noalias() = us_[t] - k_[t] * steplength - K_[t] * dx_[t];
237 m->calc(d, xs_try_[t], us_try_[t]);
239 m->calc(d, xs_try_[t]);
242 cost_try_ += d->cost;
244 if (raiseIfNaN(cost_try_)) {
245 STOP_PROFILER(
"SolverFDDP::forwardPass");
246 throw_pretty(
"forward_error");
248 if (raiseIfNaN(xnext_.lpNorm<Eigen::Infinity>())) {
249 STOP_PROFILER(
"SolverFDDP::forwardPass");
250 throw_pretty(
"forward_error");
254 const boost::shared_ptr<ActionModelAbstract>& m =
255 problem_->get_terminalModel();
256 const boost::shared_ptr<ActionDataAbstract>& d =
257 problem_->get_terminalData();
258 m->get_state()->integrate(xnext_, fs_.back() * (steplength - 1),
260 m->calc(d, xs_try_.back());
261 cost_try_ += d->cost;
263 if (raiseIfNaN(cost_try_)) {
264 STOP_PROFILER(
"SolverFDDP::forwardPass");
265 throw_pretty(
"forward_error");
268 STOP_PROFILER(
"SolverFDDP::forwardPass");
274 if (0. > th_acceptnegstep) {
275 throw_pretty(
"Invalid argument: "
276 <<
"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.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW SolverFDDP(boost::shared_ptr< ShootingProblem > problem)
Initialize the FDDP solver.
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.
void updateExpectedImprovement()
Update internal values for computing the expected improvement.