39 GridUpdateResult
ShootingGridBase::update(
const Eigen::VectorXd& x0, ReferenceTrajectoryInterface& xref, ReferenceTrajectoryInterface& uref,
41 const Time& t, ReferenceTrajectoryInterface* sref,
const Eigen::VectorXd* prev_u,
double prev_u_dt,
42 ReferenceTrajectoryInterface* xinit, ReferenceTrajectoryInterface* uinit)
44 assert(x0.size() == dynamics->getStateDimension());
45 assert(xref.getDimension() == x0.size());
46 assert(uref.getDimension() == dynamics->getInputDimension());
48 GridUpdateResult result;
60 if (!xref.isCached(
getDt(),
n, t)) xref.precompute(
getDt(),
n, t);
62 if (sref && !sref->isCached(
getDt(),
n, t)) sref->precompute(
getDt(),
n, t);
63 if (xinit && !xinit->isCached(
getDt(),
n, t)) xinit->precompute(
getDt(),
n, t);
64 if (uinit && !uinit->isCached(
getDt(),
n, t)) uinit->precompute(
getDt(),
n, t);
67 if (prev_u && prev_u->size() > 0)
88 if (xref.isStatic() && !xinit)
94 initializeSequences(x0, xref.getReferenceCached(
n - 1), xinit ? *xinit : xref, uinit ? *uinit : uref, nlp_fun);
109 for (
int i = 0; i <
_xf_fixed.size(); ++i)
118 if (new_run || result.updated())
121 result.edges_updated =
128 if (result.updated())
134 result.edges_updated =
true;
142 NlpFunctions& nlp_fun)
151 nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
158 int num_normal_intervals;
159 int add_controls_last_interval;
163 num_normal_intervals = n_init - 1;
164 add_controls_last_interval = 0;
169 num_normal_intervals = interv_div.quot;
170 add_controls_last_interval = interv_div.rem;
174 Eigen::VectorXd dir = xf - x0;
175 double dist = dir.norm();
176 if (dist != 0) dir /= dist;
177 double step = dist / (n_init - 1);
180 for (
int i = 0; i < num_normal_intervals; ++i)
184 _intervals.back().s.set(x0 + (
double)k * step * dir, nlp_fun.x_lb, nlp_fun.x_ub);
192 if (add_controls_last_interval > 0)
195 _intervals.back().s.set(x0 + (
double)k * step * dir, nlp_fun.x_lb, nlp_fun.x_ub);
197 for (
int j = 0; j < add_controls_last_interval; ++j)
198 _intervals.back().u_seq.emplace_back(uref.getReferenceCached(k + j), nlp_fun.u_lb, nlp_fun.u_ub);
217 ReferenceTrajectoryInterface& uref, NlpFunctions& nlp_fun)
232 nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
239 int num_normal_intervals;
240 int add_controls_last_interval;
244 num_normal_intervals = n_init - 1;
245 add_controls_last_interval = 0;
250 num_normal_intervals = interv_div.quot;
251 add_controls_last_interval = interv_div.rem;
255 for (
int i = 0; i < num_normal_intervals; ++i)
259 _intervals.back().s.set(xref.getReferenceCached(k), nlp_fun.x_lb, nlp_fun.x_ub);
262 _intervals.back().u_seq.emplace_back(uref.getReferenceCached(k + j), nlp_fun.u_lb, nlp_fun.u_ub);
268 if (add_controls_last_interval > 0)
271 _intervals.back().s.set(xref.getReferenceCached(k), nlp_fun.x_lb, nlp_fun.x_ub);
273 for (
int j = 0; j < add_controls_last_interval; ++j)
274 _intervals.back().u_seq.emplace_back(uref.getReferenceCached(k + j), nlp_fun.u_lb, nlp_fun.u_ub);
296 if (num_shift <= 0)
return;
300 if (num_shift >
getN() - 2)
311 for (
int i = 0; i <
getN() - num_shift; ++i)
313 int idx = i + num_shift;
326 int idx =
getN() - num_shift;
332 for (
int i = 0; i < num_shift; ++i, ++idx)
338 if (i == num_shift - 1)
352 PRINT_WARNING_ONCE(
"Shifting for shooting grids with more than 1 control per interval not yet implemented.");
362 double first_dist = (x0 -
_intervals.front().s.values()).norm();
363 if (
std::abs(first_dist) < 1e-12)
return 0;
371 double dist_cache = first_dist;
373 int num_keep_interv = 1;
374 int lookahead =
std::min(num_interv - num_keep_interv, 20);
378 for (
int i = 1; i <= lookahead; ++i)
380 dist = (x0 -
_intervals[i].s.values()).norm();
381 if (dist < dist_cache)
397 u0 =
_intervals.front().u_seq.front().values();
405 for (
const ShootingInterval& interv :
_intervals)
407 n += interv.u_seq.size();
436 PRINT_ERROR_NAMED(
"Dimensions mismatch between xf_fixed and xf. Setting xf_fixed to false.");
446 if (interv.s.getDimension() == nlp_fun.
x_lb.size())
447 interv.s.setLowerBounds(nlp_fun.
x_lb);
449 PRINT_ERROR_NAMED(
"Cannot update lower state bounds due to dimensions mismatch");
451 if (interv.s.getDimension() == nlp_fun.
x_ub.size())
452 interv.s.setUpperBounds(nlp_fun.
u_ub);
454 PRINT_ERROR_NAMED(
"Cannot update upper state bounds due to dimensions mismatch");
461 PRINT_ERROR_NAMED(
"Cannot update lower control input bounds due to dimensions mismatch");
466 PRINT_ERROR_NAMED(
"Cannot update upper control input bounds due to dimensions mismatch");
479 if (
n == n_new)
return;
491 int num_interv =
n - 1;
493 double dt_old =
getDt();
495 double dt_new = dt_old * double(
n - 1) / double(n_new - 1);
499 double t_old_p1 = dt_old;
501 for (
int idx_new = 1; idx_new < n_new - 1; ++idx_new)
505 t_new = dt_new * double(idx_new);
506 while (t_new >
double(idx_old) * dt_old && idx_old <
n)
510 t_old_p1 = double(idx_old) * dt_old;
512 const Eigen::VectorXd& x_prev = x_seq_old.col(idx_old - 1);
513 const Eigen::VectorXd& x_cur = (idx_old <
n - 1) ? x_seq_old.col(idx_old) :
_xf.
values();
515 if (idx_new < num_interv)
518 _intervals[idx_new].s.values() = x_prev + (t_new - (t_old_p1 - dt_old)) / dt_old * (x_cur - x_prev);
522 _intervals[idx_new].u_seq.front().values() = u_seq_old.col(idx_old - 1);
528 _intervals.back().s.set(x_prev + (t_new - (t_old_p1 - dt_old)) / dt_old * (x_cur - x_prev), nlp_fun.x_lb, nlp_fun.x_ub);
529 _intervals.back().u_seq.emplace_back(u_seq_old.col(idx_old - 1), nlp_fun.u_lb, nlp_fun.u_ub);
550 PRINT_WARNING_ONCE(
"Resampling for shooting grids with more than 1 control per interval not yet implemented.");
573 vertices.push_back(&interv.s);
574 for (VectorVertex& u_vtx : interv.u_seq) vertices.push_back(&u_vtx);
577 vertices.push_back(&
_dt);
579 vertices.push_back(&
_u_ref);
602 if (x_sequence) x_sequence->clear();
603 if (u_sequence) u_sequence->clear();
613 for (const ShootingInterval& interv : _intervals)
615 if (x_sequence) x_sequence->add(t, interv.s.values());
618 for (const VectorVertex& u_vtx : interv.u_seq)
620 u_sequence->add(t, u_vtx.values());
622 if (t > t_max) break;
627 t += dt * (double)interv.u_seq.size();
628 if (t > t_max) break;
631 if (t <= t_max && isXfShootingNode())
633 if (x_sequence && t <= t_max) x_sequence->add(t, _xf.values());
634 // duplicate last u to have the sampe time stamps as x_sequence
635 if (u_sequence) u_sequence->add(t, _intervals.back().u_seq.back().values());