29 #include <corbo-communication/utilities.h>
39 ReferenceTrajectoryInterface& uref, NlpFunctions& nlp_fun, OptimizationEdgeSet& edges,
40 SystemDynamicsInterface::Ptr dynamics,
bool new_run,
const corbo::Time& t,
41 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());
47 assert(x0.size() >= 3);
62 if (!xref.isCached(
getDt(), n, t)) xref.precompute(
getDt(), n, t);
63 if (!uref.isCached(
getDt(), n, t)) uref.precompute(
getDt(), n, t);
64 if (sref && !sref->isCached(
getDt(), n, t)) sref->precompute(
getDt(), n, t);
65 if (xinit && !xinit->isCached(
getDt(), n, t)) xinit->precompute(
getDt(), n, t);
66 if (uinit && !uinit->isCached(
getDt(), n, t)) uinit->precompute(
getDt(), n, t);
69 if (prev_u && prev_u->size() > 0)
84 if (xref.isStatic() && !xinit)
91 initializeSequences(x0, xref.getReferenceCached(n - 1), xinit ? *xinit : xref, uinit ? *uinit : uref, nlp_fun);
104 _x_seq.front().values() = x0;
106 for (
int i = 0; i <
_xf_fixed.size(); ++i)
115 if (new_run || result.
updated())
137 NlpFunctions& nlp_fun)
139 assert(x0.size() >= 3);
148 nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
155 int num_intervals = n_init - 1;
158 Eigen::VectorXd dir = xf - x0;
159 double dist = dir.norm();
160 if (dist != 0) dir /= dist;
161 double step = dist / num_intervals;
164 double orient_init = std::atan2(dir[1], dir[0]);
166 if (dir.head(2).dot(Eigen::Vector2d(std::cos(x0[2]), std::sin(x0[2]))) < 0) orient_init =
normalize_theta(orient_init + M_PI);
168 for (
int k = 0; k < num_intervals; ++k)
171 Eigen::VectorXd new_x = x0 + (double)k * step * dir;
172 if (k > 0) new_x[2] = orient_init;
173 _x_seq.emplace_back(new_x, nlp_fun.x_lb, nlp_fun.x_ub);
175 _u_seq.emplace_back(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_ub);
181 _x_seq.front().setFixed(
true);
186 assert(
_x_seq.size() > 0);
193 ReferenceTrajectoryInterface& uref, NlpFunctions& nlp_fun)
208 nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
215 int num_intervals = n_init - 1;
217 _x_seq.emplace_back(x0, nlp_fun.x_lb, nlp_fun.x_ub);
218 _u_seq.emplace_back(uref.getReferenceCached(0), nlp_fun.u_lb, nlp_fun.u_ub);
219 for (
int k = 1; k < num_intervals; ++k)
222 _x_seq.emplace_back(xref.getReferenceCached(k), nlp_fun.x_lb, nlp_fun.x_ub);
224 _u_seq.emplace_back(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_ub);
230 _x_seq.front().setFixed(
true);
235 assert(
_x_seq.size() > 1);
245 if (num_shift <= 0)
return;
247 if (num_shift >
getN() - 2)
258 for (
int i = 0; i <
getN() - num_shift; ++i)
260 int idx = i + num_shift;
273 int idx =
getN() - num_shift;
279 for (
int i = 0; i < num_shift; ++i, ++idx)
285 if (i == num_shift - 1)
310 double first_dist = (x0 -
_x_seq.front().values()).norm();
311 if (std::abs(first_dist) < 1e-12)
return 0;
317 int num_interv =
getN() - 1;
319 double dist_cache = first_dist;
321 int num_keep_interv = 1;
322 int lookahead = std::min(num_interv - num_keep_interv, 20);
326 for (
int i = 1; i <= lookahead; ++i)
328 dist = (x0 -
_x_seq[i].values()).norm();
329 if (dist < dist_cache)
346 u0 =
_u_seq.front().values();
366 double min_dist = std::numeric_limits<double>::max();
369 for (
int i = start_idx; i < (
int)
_x_seq.size(); ++i)
400 PRINT_ERROR_NAMED(
"Dimensions mismatch between xf_fixed and xf. Setting xf_fixed to false.");
408 for (VectorVertexSE2& vtx :
_x_seq)
410 if (vtx.getDimension() == nlp_fun.x_lb.size())
411 vtx.setLowerBounds(nlp_fun.x_lb);
413 PRINT_ERROR_NAMED(
"Cannot update lower state bounds due to dimensions mismatch");
415 if (vtx.getDimension() == nlp_fun.x_ub.size())
416 vtx.setUpperBounds(nlp_fun.u_ub);
418 PRINT_ERROR_NAMED(
"Cannot update upper state bounds due to dimensions mismatch");
423 if (vtx.getDimension() == nlp_fun.u_lb.size())
424 vtx.setLowerBounds(nlp_fun.u_lb);
426 PRINT_ERROR_NAMED(
"Cannot update lower control input bounds due to dimensions mismatch");
428 if (vtx.getDimension() == nlp_fun.u_ub.size())
429 vtx.setUpperBounds(nlp_fun.u_ub);
431 PRINT_ERROR_NAMED(
"Cannot update upper control input bounds due to dimensions mismatch");
444 if (n == n_new)
return;
448 PRINT_ERROR_NAMED(
"We currently need _nlp_fun to be valid in order to retrieve bounds");
461 int num_interv =
n - 1;
463 double dt_old =
getDt();
465 double dt_new = dt_old * double(n - 1) / double(n_new - 1);
469 double t_old_p1 = dt_old;
471 for (
int idx_new = 1; idx_new < n_new - 1; ++idx_new)
475 t_new = dt_new * double(idx_new);
476 while (t_new >
double(idx_old) * dt_old && idx_old < n)
480 t_old_p1 = double(idx_old) * dt_old;
482 const Eigen::VectorXd& x_prev = x_seq_old.col(idx_old - 1);
483 const Eigen::VectorXd& x_cur = (idx_old <
n - 1) ? x_seq_old.col(idx_old) :
_xf.
values();
485 if (idx_new < num_interv)
488 _x_seq[idx_new].values() = x_prev + (t_new - (t_old_p1 - dt_old)) / dt_old * (x_cur - x_prev);
496 _u_seq[idx_new].values() = u_seq_old.col(idx_old - 1);
570 for (
int i = 0; i <
n - 1; ++i)
581 if (x_sequence) x_sequence->clear();
582 if (u_sequence) u_sequence->clear();
594 for (int i = 0; i < _x_seq.size(); ++i)
596 x_sequence->add(t, _x_seq[i].values());
598 if (t > t_max) break;
600 if (t <= t_max) x_sequence->add(t, _xf.values());
606 for (int i = 0; i < _u_seq.size(); ++i)
608 u_sequence->add(t, _u_seq[i].values());
610 if (t > t_max) break;
612 // duplicate last u to have the sampe time stamps as x_sequence
613 if (t <= t_max) u_sequence->add(t, _u_seq.back().values());
617 } // namespace mpc_local_planner