shooting_grid_base.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
26 
28 
30 #include <corbo-core/console.h>
31 
32 #include <algorithm>
33 #include <cmath>
34 #include <cstdlib>
35 #include <memory>
36 
37 namespace corbo {
38 
40  NlpFunctions& nlp_fun, OptimizationEdgeSet& edges, SystemDynamicsInterface::Ptr dynamics, bool new_run,
41  const Time& t, ReferenceTrajectoryInterface* sref, const Eigen::VectorXd* prev_u, double prev_u_dt,
43 {
44  assert(x0.size() == dynamics->getStateDimension());
45  assert(xref.getDimension() == x0.size());
46  assert(uref.getDimension() == dynamics->getInputDimension());
47 
48  GridUpdateResult result;
49 
50  if (isGridAdaptActive() && !_first_run && !isEmpty()) // TODO(roesmann): this might not be efficient in case warm start is deactivated
51  {
52  // adapt grid if implemented by subclass
53  adaptGrid(new_run, nlp_fun); // note, isModified() should return true if something was changed!, we could also use the return value...
54  }
55 
56  // check if we need to cache the reference trajectory values // TODO(roesmann): we could restrict this to new_run==true only as long as we do not
57  // have a grid resize...
58  int n = std::max(std::max(getNRef(), getN()), _n_adapt);
59  if (_dt.value() <= 0) _dt.value() = _dt_ref; // initialize _dt to _dt_ref in case it has not been optimized before
60  if (!xref.isCached(getDt(), n, t)) xref.precompute(getDt(), n, t);
61  if (!uref.isCached(getDt(), n, t)) uref.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);
65 
66  // set previous control which might be utilized by some edges
67  if (prev_u && prev_u->size() > 0)
68  setPreviousControl(*prev_u, prev_u_dt);
69  else
70  setPreviousControl(Eigen::VectorXd::Zero(dynamics->getInputDimension()), prev_u_dt);
71 
72  // set last control to uref
74 
75  if (_num_u_per_interv_ref <= 1)
76  _full_discretization = true;
77  else
78  _full_discretization = false;
79 
80  // TODO(roesmann) we do not check if bounds in nlp_fun are updated
81  // updateBounds(); // calling this everytime is not efficient
82 
83  // initialize trajectories if empty or if the goal differs from the last one
84  // reinit if goal is far away
85  if (isEmpty() ||
86  !_warm_start) // TODO(roesmann): threshold?: if (_cached_xf.rows() > 0 && (xf - _cached_xf).norm() > _warm_start_goal_dist_reinit)
87  {
88  if (xref.isStatic() && !xinit)
89  {
90  initializeSequences(x0, xref.getReferenceCached(n - 1), uinit ? *uinit : uref, nlp_fun);
91  }
92  else
93  {
94  initializeSequences(x0, xref.getReferenceCached(n - 1), xinit ? *xinit : xref, uinit ? *uinit : uref, nlp_fun);
95  }
96  }
97  else
98  {
99  if (new_run && isMovingHorizonWarmStartActive())
100  {
101  // warm_start
102  warmStartShifting(x0);
103  }
104  if (new_run)
105  {
106  // make sure to always overwrite the start with the actual (measured) values
107  _intervals.front().s.values() = x0;
108  // update fixed goal states
109  for (int i = 0; i < _xf_fixed.size(); ++i)
110  {
111  if (_xf_fixed[i]) _xf.values()[i] = xref.getReferenceCached(getN() - 1)[i];
112  }
113  }
114  }
115 
116  result.vertices_updated = isModified(); // isModified() returns if the underlying vertex set is updated
117 
118  if (new_run || result.updated()) // new run -> new t
119  {
120  // update NLP functions w.r.t. the current discretization
121  result.edges_updated =
122  nlp_fun.update(getN(), t.toSec(), xref, uref, sref, hasSingleDt(), x0, {getDt()}, this); // returns true if edge dimensions changed
123  // TODO(roesmann): sref is not yet implemented for testing, add this later...
124  // TODO(roesmann): we do not yet check if dt was updated, this might affect nlp update
125  // TODO(roesmann): maybe, for non-uniform grids, we need a better nlp update method which gets all correct reference time stamps
126  }
127 
128  if (result.updated()) // vertices or eges updated
129  {
130  // create grid specific edges
131  // TODO(roesmann): for now, we assume that we are the only maintainer of the edge set (which might be not true generally!)
132  // so we clear the edge set whenever we want
133  createEdges(nlp_fun, edges, dynamics);
134  result.edges_updated = true; // now we definitely updated the edgeset
135  }
136 
137  _first_run = false;
138  return result;
139 }
140 
141 void ShootingGridBase::initializeSequences(const Eigen::VectorXd& x0, const Eigen::VectorXd& xf, ReferenceTrajectoryInterface& uref,
142  NlpFunctions& nlp_fun)
143 {
144  // clear(); // make sure everything is cleared
145  _intervals.clear();
146  _xf.clear();
147  _dt.clear();
148  _active_vertices.clear();
149 
150  // check or initalize bounds if empty
151  nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
152 
153  // check x_fixed
155 
156  int n_init = _n_adapt > 0 ? _n_adapt : _n_ref;
157 
158  int num_normal_intervals;
159  int add_controls_last_interval;
160 
161  if (_num_u_per_interv_ref <= 1)
162  {
163  num_normal_intervals = n_init - 1;
164  add_controls_last_interval = 0;
165  }
166  else
167  {
168  std::div_t interv_div = std::div(n_init - 1, _num_u_per_interv_ref);
169  num_normal_intervals = interv_div.quot;
170  add_controls_last_interval = interv_div.rem;
171  }
172 
173  // we initialize the state trajectory linearly
174  Eigen::VectorXd dir = xf - x0;
175  double dist = dir.norm();
176  if (dist != 0) dir /= dist;
177  double step = dist / (n_init - 1);
178 
179  int k = 0;
180  for (int i = 0; i < num_normal_intervals; ++i)
181  {
182  // add shooting interval
183  _intervals.emplace_back();
184  _intervals.back().s.set(x0 + (double)k * step * dir, nlp_fun.x_lb, nlp_fun.x_ub);
185  // _intervals.back().u_seq.resize(controls_per_interval, VectorVertex(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_ub));
186  for (int j = 0; j < _num_u_per_interv_ref; ++j) _intervals.back().u_seq.emplace_back(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_ub);
187 
189  }
190 
191  // add last shooting interval
192  if (add_controls_last_interval > 0)
193  {
194  _intervals.emplace_back();
195  _intervals.back().s.set(x0 + (double)k * step * dir, nlp_fun.x_lb, nlp_fun.x_ub);
196  // _intervals.back().u_seq.resize(controls_last_interval, VectorVertex(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_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);
199  }
200 
201  // add final state (even if isXfShootingNode() is false, we store xf here)
202  _xf.set(xf, nlp_fun.x_lb, nlp_fun.x_ub, _xf_fixed);
203 
204  // set first state as fixed
205  _intervals.front().s.setFixed(true);
206 
207  // set dt
209 
210  assert(!_intervals.empty());
211 
212  // notify graph that vertices are changed
213  setModified(true);
214 }
215 
216 void ShootingGridBase::initializeSequences(const Eigen::VectorXd& x0, const Eigen::VectorXd& xf, ReferenceTrajectoryInterface& xref,
218 {
219  // clear(); // make sure everything is cleared
220  _intervals.clear();
221  _xf.clear();
222  _dt.clear();
223  _active_vertices.clear();
224 
225  // TODO(roesmann): check if this is ever needed in any pracital realization:
226  // if ((x0 - xref.getReferenceCached(0)).norm() > _non_static_ref_dist_threshold)
227  // {
228  // initializeSequences(x0, xref.getReferenceCached(getN() - 1), uref, nlp_fun);
229  // }
230 
231  // check or initalize bounds if empty
232  nlp_fun.checkAndInitializeBoundDimensions(x0.size(), uref.getDimension());
233 
234  // check x_fixed
236 
237  int n_init = _n_adapt > 0 ? _n_adapt : _n_ref;
238 
239  int num_normal_intervals;
240  int add_controls_last_interval;
241 
242  if (_num_u_per_interv_ref <= 1)
243  {
244  num_normal_intervals = n_init - 1;
245  add_controls_last_interval = 0;
246  }
247  else
248  {
249  std::div_t interv_div = std::div(n_init - 1, _num_u_per_interv_ref);
250  num_normal_intervals = interv_div.quot;
251  add_controls_last_interval = interv_div.rem;
252  }
253 
254  int k = 0;
255  for (int i = 0; i < num_normal_intervals; ++i)
256  {
257  // add shooting interval
258  _intervals.emplace_back();
259  _intervals.back().s.set(xref.getReferenceCached(k), nlp_fun.x_lb, nlp_fun.x_ub);
260  // _intervals.back().u_seq.resize(controls_per_interval, VectorVertex(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_ub));
261  for (int j = 0; j < _num_u_per_interv_ref; ++j)
262  _intervals.back().u_seq.emplace_back(uref.getReferenceCached(k + j), nlp_fun.u_lb, nlp_fun.u_ub);
263 
265  }
266 
267  // add last shooting interval
268  if (add_controls_last_interval > 0)
269  {
270  _intervals.emplace_back();
271  _intervals.back().s.set(xref.getReferenceCached(k), nlp_fun.x_lb, nlp_fun.x_ub);
272  // _intervals.back().u_seq.resize(controls_last_interval, VectorVertex(uref.getReferenceCached(k), nlp_fun.u_lb, nlp_fun.u_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);
275  }
276 
277  // add final state (even if isXfShootingNode() is false, we store xf here)
278  _xf.set(xf, nlp_fun.x_lb, nlp_fun.x_ub, _xf_fixed);
279 
280  // set first state as fixed
281  _intervals.front().s.setFixed(true);
282 
283  // set dt
285 
286  assert(!_intervals.empty());
287 
288  // notify graph that vertices are changed
289  setModified(true);
290 }
291 
292 void ShootingGridBase::warmStartShifting(const Eigen::VectorXd& x0)
293 {
294  // find nearest state to x0 (ideally it is the second one in _x_seq).
295  int num_shift = findNearestShootingInterval(x0);
296  if (num_shift <= 0) return;
297 
299  {
300  if (num_shift > getN() - 2)
301  {
302  PRINT_ERROR_NAMED("Cannot shift if num_shift > N-2");
303  return;
304  }
305 
306  // the simplest strategy would be to just remove remove x_seq[0], append xf to x_seq and replace xf (num_shift=1)
307  // however, this requries to change the structure which always triggers an edge recreation and so the solver must reallocate memory.
308  // TOOD(roesmann): for time-optimal stuff, if we are sure that we resize the grid, it is then more efficent to implement the strategy above...
309 
310  // shift from end to front:
311  for (int i = 0; i < getN() - num_shift; ++i)
312  {
313  int idx = i + num_shift;
314  if (idx == getN() - 1)
315  {
316  // final state reached
317  _intervals[i].s.values() = _xf.values();
318  }
319  else
320  {
321  _intervals[i].s.values() = _intervals[idx].s.values();
322  _intervals[i].u_seq.front().values() = _intervals[idx].u_seq.front().values();
323  }
324  }
325 
326  int idx = getN() - num_shift;
327  if (idx < 0)
328  {
329  PRINT_ERROR_NAMED("idx < 0...");
330  return;
331  }
332  for (int i = 0; i < num_shift; ++i, ++idx)
333  {
334  // now extrapolate
335  assert(idx > 1);
336 
337  // linearly extrapolate states
338  if (i == num_shift - 1) // consider xf
339  {
340  _xf.values() = _intervals[idx - 2].s.values() + 2.0 * (_intervals[idx - 1].s.values() - _intervals[idx - 2].s.values());
341  }
342  else
343  {
344  _intervals[idx].s.values() = _intervals[idx - 2].s.values() + 2.0 * (_intervals[idx - 1].s.values() - _intervals[idx - 2].s.values());
345  // TODO(roesmann) multiply by fraction of last dt and _dt
346  }
347  _intervals[idx - 1].u_seq.front().values() = _intervals[idx - 2].u_seq.front().values();
348  }
349  }
350  else
351  {
352  PRINT_WARNING_ONCE("Shifting for shooting grids with more than 1 control per interval not yet implemented.");
353  }
354 }
355 
356 int ShootingGridBase::findNearestShootingInterval(const Eigen::VectorXd& x0)
357 {
358  assert(!isEmpty());
359  assert(isValid());
360 
361  // same start as before
362  double first_dist = (x0 - _intervals.front().s.values()).norm();
363  if (std::abs(first_dist) < 1e-12) return 0;
364 
365  // find nearest state (using l2-norm) in order to prune the trajectory
366  // (remove already passed states, should be 1 if the sampling times of the planning and controller call match, but could be higher if rates
367  // differ)
368 
369  int num_interv = (int)_intervals.size();
370 
371  double dist_cache = first_dist;
372  double dist;
373  int num_keep_interv = 1; // std::max(1, _num_states_min - 1); // we need to keep at least this number of intervals in the trajectory
374  int lookahead = std::min(num_interv - num_keep_interv, 20); // max 20 samples
375 
376  int nearest_idx = 0;
377 
378  for (int i = 1; i <= lookahead; ++i)
379  {
380  dist = (x0 - _intervals[i].s.values()).norm();
381  if (dist < dist_cache)
382  {
383  dist_cache = dist;
384  nearest_idx = i;
385  }
386  else
387  break;
388  }
389 
390  return nearest_idx;
391 }
392 
393 bool ShootingGridBase::getFirstControlInput(Eigen::VectorXd& u0)
394 {
395  if (isEmpty() || !isValid()) return false;
396 
397  u0 = _intervals.front().u_seq.front().values();
398  return true;
399 }
400 
402 {
403  if (_full_discretization) return _intervals.size() + 1;
404  int n = 1; // xf
405  for (const ShootingInterval& interv : _intervals)
406  {
407  n += interv.u_seq.size();
408  }
409  return n;
410 }
411 
413 {
414  // clear grid if we change n
415  if (n != getN()) clear();
416  if (n < 2)
417  {
418  PRINT_ERROR_NAMED("Number of states must be n>1.");
419  _n_ref = 2;
420  return;
421  }
422  _n_ref = n;
423  _n_adapt = 0;
424 }
425 
427 {
428  if (_xf_fixed.size() == 0)
429  {
430  _xf_fixed.setConstant(dim_x, false);
431  return true;
432  }
433  else if (_xf_fixed.size() == dim_x)
434  return true;
435 
436  PRINT_ERROR_NAMED("Dimensions mismatch between xf_fixed and xf. Setting xf_fixed to false.");
437  _xf_fixed.setConstant(dim_x, false);
438  return false;
439 }
440 
442 {
443  if (isEmpty()) return;
444  for (ShootingInterval& interv : _intervals)
445  {
446  if (interv.s.getDimension() == nlp_fun.x_lb.size())
447  interv.s.setLowerBounds(nlp_fun.x_lb);
448  else
449  PRINT_ERROR_NAMED("Cannot update lower state bounds due to dimensions mismatch");
450 
451  if (interv.s.getDimension() == nlp_fun.x_ub.size())
452  interv.s.setUpperBounds(nlp_fun.u_ub);
453  else
454  PRINT_ERROR_NAMED("Cannot update upper state bounds due to dimensions mismatch");
455 
456  for (VectorVertex& vtx : interv.u_seq)
457  {
458  if (vtx.getDimension() == nlp_fun.u_lb.size())
459  vtx.setLowerBounds(nlp_fun.u_lb);
460  else
461  PRINT_ERROR_NAMED("Cannot update lower control input bounds due to dimensions mismatch");
462 
463  if (vtx.getDimension() == nlp_fun.u_ub.size())
464  vtx.setUpperBounds(nlp_fun.u_ub);
465  else
466  PRINT_ERROR_NAMED("Cannot update upper control input bounds due to dimensions mismatch");
467  }
468  }
471 }
472 
474 {
476  {
477  assert(isValid());
478  int n = getN();
479  if (n == n_new) return;
480 
481  // copy vertices (vertices itself are shared pointers)
484  TimeSeries::Ptr ts_states_old = std::make_shared<TimeSeries>();
485  TimeSeries::Ptr ts_controls_old = std::make_shared<TimeSeries>();
486  getStateAndControlTimeSeries(ts_states_old, ts_controls_old);
487 
488  TimeSeries::ValuesMatMap x_seq_old = ts_states_old->getValuesMatrixView();
489  TimeSeries::ValuesMatMap u_seq_old = ts_controls_old->getValuesMatrixView();
490 
491  int num_interv = n - 1;
492 
493  double dt_old = getDt();
494  // compute new time diff
495  double dt_new = dt_old * double(n - 1) / double(n_new - 1);
496 
497  double t_new;
498  int idx_old = 1;
499  double t_old_p1 = dt_old; // time for old sample with index idx_old (acutally its the subsequent time step w.r.t t_new)
500 
501  for (int idx_new = 1; idx_new < n_new - 1; ++idx_new) // n_new-1 since last state is identical and copied later. idx_new=1, since start
502  // sample is already valid (we do not touch it)
503  // we allow a small mismatch for the control u_1 and let the optimizer correct it later
504  {
505  t_new = dt_new * double(idx_new);
506  while (t_new > double(idx_old) * dt_old && idx_old < n)
507  {
508  ++idx_old;
509  }; // find idx_old that represents the state subsequent to the new one (w.r.t. time)
510  t_old_p1 = double(idx_old) * dt_old;
511 
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();
514 
515  if (idx_new < num_interv)
516  {
517  // states
518  _intervals[idx_new].s.values() = x_prev + (t_new - (t_old_p1 - dt_old)) / dt_old * (x_cur - x_prev);
519 
520  // controls
521  // TODO(roesmann): we do not have a valid control (u_f), so hold last
522  _intervals[idx_new].u_seq.front().values() = u_seq_old.col(idx_old - 1);
523  }
524  else
525  {
526  // add new pair
527  _intervals.emplace_back();
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);
530  }
531  }
532 
533  // clear invalid states
534  if (n_new < n)
535  {
536  _intervals.resize(n_new - 1);
537  }
538 
539  // save new dt
540  _dt.value() = dt_new;
541 
542  // set first vertex always to fixed
543  // _x_seq.front().setFixed(true); // should not be necessary here (we just change values in the first node)
544 
545  // notify graph that vertices are changed
546  setModified(true);
547  }
548  else
549  {
550  PRINT_WARNING_ONCE("Resampling for shooting grids with more than 1 control per interval not yet implemented.");
551  // TODO(roesmann): probably we must adhere to _num_interv_ref while resampling, so recalculate how many controls are in every shooting
552  // interval
553  }
554 }
555 
557 {
558  _intervals.clear();
559  _xf.clear();
560  _dt.clear();
561  _n_adapt = 0;
562  _first_run = true;
563  _active_vertices.clear();
564  setModified(true);
565 }
566 
567 void ShootingGridBase::getVertices(std::vector<VertexInterface*>& vertices)
568 {
569  vertices.clear();
570  // order doesn't matter here
571  for (ShootingInterval& interv : _intervals)
572  {
573  vertices.push_back(&interv.s);
574  for (VectorVertex& u_vtx : interv.u_seq) vertices.push_back(&u_vtx);
575  }
576  if (isXfShootingNode()) vertices.push_back(&_xf); // TODO(roesmann) check if xf_shooting_node is implemented correctly everywhere
577  vertices.push_back(&_dt); // make sure to make it fixed if desired in any subclass
578  vertices.push_back(&_u_prev); // always fixed...
579  vertices.push_back(&_u_ref);
580  vertices.push_back(&_u_prev_dt);
581 }
582 
584 {
585  _active_vertices.clear();
586  assert(isValid());
587 
588  for (ShootingInterval& interv : _intervals)
589  {
590  if (!interv.s.isFixed()) _active_vertices.push_back(&interv.s);
591  for (VectorVertex& u_vtx : interv.u_seq)
592  {
593  if (!u_vtx.isFixed()) _active_vertices.push_back(&u_vtx);
594  }
595  }
596  if (isXfShootingNode() && !_xf.isFixed()) _active_vertices.push_back(&_xf);
597  if (!_dt.isFixed()) _active_vertices.push_back(&_dt);
598 }
599 
601 {
602  if (x_sequence) x_sequence->clear();
603  if (u_sequence) u_sequence->clear();
604 
605  if (isEmpty()) return;
606  assert(isValid());
607 
608  PRINT_ERROR_COND_NAMED(t_max < 0, "t_max >= 0 required");
609 
610  double dt = getDt();
611 
612  double t = 0;
613  for (const ShootingInterval& interv : _intervals)
614  {
615  if (x_sequence) x_sequence->add(t, interv.s.values());
616  if (u_sequence)
617  {
618  for (const VectorVertex& u_vtx : interv.u_seq)
619  {
620  u_sequence->add(t, u_vtx.values());
621  t += dt;
622  if (t > t_max) break;
623  }
624  }
625  else
626  {
627  t += dt * (double)interv.u_seq.size();
628  if (t > t_max) break;
629  }
630  }
631  if (t <= t_max && isXfShootingNode())
632  {
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());
636  }
637 }
638 
639 } // namespace corbo
virtual bool isDtFixedIntended() const
void getStateAndControlTimeSeries(TimeSeries::Ptr x_sequence, TimeSeries::Ptr u_sequence, double t_max=CORBO_INF_DBL) const override
Return state and control trajectory as time series object (shared instance)
#define PRINT_ERROR_NAMED(msg)
Definition: console.h:260
#define max(a, b)
Definition: datatypes.h:20
#define PRINT_WARNING_ONCE(msg)
Print msg-stream only once.
Definition: console.h:149
Eigen::VectorXd x_lb
Definition: nlp_functions.h:46
#define PRINT_ERROR_COND_NAMED(cond, msg)
Definition: console.h:262
void computeActiveVertices() override
return int(ret)+1
#define min(a, b)
Definition: datatypes.h:19
void setPreviousControl(const Eigen::VectorXd &prev_u, double prev_u_dt)
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:94
Eigen::VectorXd u_ub
Definition: nlp_functions.h:49
virtual bool isFixed() const
Check if all components are fixed.
bool isEmpty() const override
virtual bool adaptGrid(bool new_run, NlpFunctions &nlp_fun)
void checkAndInitializeBoundDimensions(int x_dim, int u_dim)
virtual int getDimension() const =0
bool hasSingleDt() const override
Eigen::VectorXd u_lb
Definition: nlp_functions.h:48
virtual bool isStatic() const =0
void updateBounds(const NlpFunctions &nlp_fun)
Representation of time stamps.
Definition: time.h:251
void resampleTrajectory(int n_new, NlpFunctions &nlp_fun)
virtual const OutputVector & getReferenceCached(int k) const =0
Eigen::Matrix< bool, -1, 1 > _xf_fixed
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const AbsReturnType abs() const
bool isModified() const
Definition: vertex_set.h:83
Eigen::VectorXd x_ub
Definition: nlp_functions.h:47
std::vector< VertexInterface * > _active_vertices
GridUpdateResult update(const Eigen::VectorXd &x0, ReferenceTrajectoryInterface &xref, ReferenceTrajectoryInterface &uref, NlpFunctions &nlp_fun, OptimizationEdgeSet &edges, SystemDynamicsInterface::Ptr dynamics, bool new_run, const Time &t, ReferenceTrajectoryInterface *sref=nullptr, const Eigen::VectorXd *prev_u=nullptr, double prev_u_dt=0, ReferenceTrajectoryInterface *xinit=nullptr, ReferenceTrajectoryInterface *uinit=nullptr) override
std::vector< ShootingInterval > _intervals
void setModified(bool modified)
Definition: vertex_set.h:82
void getVertices(std::vector< VertexInterface *> &vertices) override
void setUpperBounds(const Eigen::Ref< const Eigen::VectorXd > &ub) override
Define upper bounds on the vertex values [getDimension() x 1].
EIGEN_DEVICE_FUNC Derived & setConstant(Index size, const Scalar &val)
void clear() override
Clear complete backup container.
int getN() const override
int getDimension() const override
Return number of elements/values/components stored in this vertex.
Definition: vector_vertex.h:96
void setLastControlRef(const Eigen::VectorXd &last_u_ref)
void set(const Eigen::Ref< const Eigen::VectorXd > &values, const Eigen::Ref< const Eigen::VectorXd > &lb, const Eigen::Ref< const Eigen::VectorXd > &ub, bool fixed=false) override
Set values and bounds at once.
int findNearestShootingInterval(const Eigen::VectorXd &x0)
const double & value() const
Get underlying value.
void clear() override
Clear complete backup container.
void setUpperBound(double ub)
Set upper bound.
double toSec() const
Cast time stamp to seconds.
Definition: time.h:281
bool checkAndInitializeXfFixedFlags(int dim_x)
virtual void createEdges(NlpFunctions &nlp_fun, OptimizationEdgeSet &edges, SystemDynamicsInterface::Ptr dynamics)=0
Interface class for reference trajectories.
virtual bool isGridAdaptActive() const
void initializeSequences(const Eigen::VectorXd &x0, const Eigen::VectorXd &xf, ReferenceTrajectoryInterface &uref, NlpFunctions &nlp_fun)
void setLowerBounds(const Eigen::Ref< const Eigen::VectorXd > &lb) override
Define lower bounds on the vertex values [getDimension() x 1].
virtual bool isXfShootingNode() const
void setLowerBound(double lb)
Set lower bound.
Vertex implementation that stores an Eigen::VectorXd (dynamic dimension)
Definition: vector_vertex.h:51
bool update(int n, double t, ReferenceTrajectoryInterface &xref, ReferenceTrajectoryInterface &uref, ReferenceTrajectoryInterface *sref, bool single_dt, const Eigen::VectorXd &x0, const std::vector< double > &dts, const DiscretizationGridInterface *grid)
virtual bool isCached(double dt, int n, Time t) const =0
const Eigen::VectorXd & values() const
Read-access to the underlying value vector.
std::shared_ptr< TimeSeries > Ptr
Definition: time_series.h:64
bool getFirstControlInput(Eigen::VectorXd &u0) override
PartiallyFixedVectorVertex _xf
void warmStartShifting(const Eigen::VectorXd &x0)
virtual void precompute(double dt, int n, Time t)=0
PlainMatrixType mat * n
Definition: eigenvalues.cpp:41
void set(double value, double lb, double ub, bool fixed)
Definition: scalar_vertex.h:90
std::shared_ptr< SystemDynamicsInterface > Ptr
virtual bool isMovingHorizonWarmStartActive() const


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:07:18