multiple_shooting_variable_grid.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 #include <corbo-core/console.h>
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <memory>
33 
34 namespace corbo {
35 
36 void MultipleShootingVariableGrid::setDtBounds(double dt_lb, double dt_ub)
37 {
38  _dt_lb = dt_lb;
39  _dt_ub = dt_ub;
40 }
41 
43 {
45  _n_max = n_max;
46  _dt_hyst_ratio = dt_hyst_ratio;
47 }
48 
50 {
52  _n_max = n_max;
53  _dt_hyst_ratio = dt_hyst_ratio;
54 }
55 
57 
59 {
60  // do not adapt grid in a new run
61  if (new_run && !_adapt_first_iter) return false;
62 
63  bool changed = false;
64  switch (_grid_adapt)
65  {
67  {
68  break;
69  }
71  {
72  changed = adaptGridTimeBasedSingleStep(nlp_fun);
73  break;
74  }
76  {
77  changed = adaptGridTimeBasedAggressiveEstimate(nlp_fun);
78  break;
79  }
81  {
82  changed = adaptGridSimpleShrinkingHorizon(nlp_fun);
83  break;
84  }
85  default:
86  {
87  PRINT_ERROR_NAMED("selected grid adaptation strategy not implemented.");
88  }
89  }
90  return changed;
91 }
92 
94 {
95  PRINT_WARNING_COND_NAMED(!isTimeVariableGrid(), "time based adaptation might only be used with a fixed dt.");
96 
97  int n = getN();
98 
99  double dt = getDt();
100  if (dt > _dt_ref * (1.0 + _dt_hyst_ratio) && n < _n_max)
101  {
102  resampleTrajectory(n + 1, nlp_fun);
103  _n_adapt = n + 1;
104  return true;
105  }
106  else if (dt < _dt_ref * (1.0 - _dt_hyst_ratio) && n > _n_min)
107  {
108  resampleTrajectory(n - 1, nlp_fun);
109  _n_adapt = n - 1;
110  return true;
111  }
112  return false;
113 }
114 
116 {
117  PRINT_WARNING_COND_NAMED(!isTimeVariableGrid(), "time based adaptation might only be used with a fixed dt.");
118 
119  int n = getN();
120  double dt = getDt();
121 
122  // check if hysteresis is satisfied
123  if (dt >= _dt_ref * (1.0 - _dt_hyst_ratio) && dt <= _dt_ref * (1.0 + _dt_hyst_ratio)) return false;
124 
125  // estimate number of samples based on the fraction dt/dt_ref.
126  // dt is the time difference obtained in a previous solution (with a coarser resp. finer trajectory resolution)
127  int new_n = n * (int)std::round(_dt.value() / _dt_ref);
128 
129  // bound value
130  if (new_n > _n_max)
131  new_n = _n_max;
132  else if (new_n < _n_min)
133  new_n = _n_min;
134 
135  if (new_n == n) return false;
136 
137  // and now resample
138  resampleTrajectory(new_n, nlp_fun);
139  _n_adapt = new_n;
140  return true;
141 }
142 
144 {
145  int n = getN();
146  if (n > _n_min)
147  {
148  resampleTrajectory(n - 1, nlp_fun);
149  _n_adapt = n - 1;
150  }
151  return false;
152 }
153 
154 #ifdef MESSAGE_SUPPORT
155 void MultipleShootingVariableGrid::fromMessage(const messages::MultipleShootingVariableGrid& message, std::stringstream* issues)
156 {
157  MultipleShootingGrid::fromMessage(message.multiple_shooting_grid(), issues);
158 
159  // xf fixed states
160  // if (grid_msg.xf_fixed_size() != _p && issues) *issues << "FullDiscretizationGrid: xf_fixed size does not match state dimension " << _p <<
161  // ".\n";
162  // TODO(roesmann): we need a warning in the gui if xf_fixed has the wrong dimension.
163  // maybe we could add a "verifyParameters()" method to all interfaces, so predictive control asks the ocp, the ocp the grid and so
164  // on
165  _xf_fixed = Eigen::Map<const Eigen::Matrix<bool, -1, 1>>(message.xf_fixed().data(), message.xf_fixed_size());
166 
167  // dt bounds
168  setDtBounds(message.dt_min(), message.dt_max());
169 
170  // auto resize
171  if (message.has_grid_adapt_strategy())
172  {
173  if (message.grid_adapt_strategy().has_no_grid_adapt())
174  {
176  }
177  else if (message.grid_adapt_strategy().has_time_based_single_step())
178  {
179  setGridAdaptTimeBasedSingleStep(message.grid_adapt_strategy().time_based_single_step().n_max(),
180  message.grid_adapt_strategy().time_based_single_step().dt_hyst_ratio());
181  }
182  else if (message.grid_adapt_strategy().has_time_based_aggr_estim())
183  {
184  setGridAdaptTimeBasedAggressiveEstimate(message.grid_adapt_strategy().time_based_aggr_estim().n_max(),
185  message.grid_adapt_strategy().time_based_aggr_estim().dt_hyst_ratio());
186  }
187  else if (message.grid_adapt_strategy().has_simple_shrinking_horizon())
188  {
190  }
191  }
192  _adapt_first_iter = message.grid_adapt_strategy().adapt_first_iter();
193 
194  // others
195  _n_min = message.n_min();
196 }
197 
198 void MultipleShootingVariableGrid::toMessage(messages::MultipleShootingVariableGrid& message) const
199 {
200  MultipleShootingGrid::toMessage(*message.mutable_multiple_shooting_grid());
201 
202  // xf fixed states
203  if (_xf_fixed.size() > 0)
204  {
205  message.mutable_xf_fixed()->Resize(_xf_fixed.size(), false);
206  Eigen::Map<Eigen::Matrix<bool, -1, 1>>(message.mutable_xf_fixed()->mutable_data(), _xf_fixed.size()) = _xf_fixed;
207  }
208 
209  // dt bounds
210  message.set_dt_min(_dt_lb);
211  message.set_dt_max(_dt_ub);
212 
213  // auto resize
214  switch (_grid_adapt)
215  {
217  {
218  message.mutable_grid_adapt_strategy()->mutable_no_grid_adapt();
219  break;
220  }
222  {
223  message.mutable_grid_adapt_strategy()->mutable_time_based_single_step()->set_n_max(_n_max);
224  message.mutable_grid_adapt_strategy()->mutable_time_based_single_step()->set_dt_hyst_ratio(_dt_hyst_ratio);
225  break;
226  }
228  {
229  message.mutable_grid_adapt_strategy()->mutable_time_based_aggr_estim()->set_n_max(_n_max);
230  message.mutable_grid_adapt_strategy()->mutable_time_based_aggr_estim()->set_dt_hyst_ratio(_dt_hyst_ratio);
231  break;
232  }
234  {
235  message.mutable_grid_adapt_strategy()->mutable_simple_shrinking_horizon();
236  break;
237  }
238  default:
239  {
240  PRINT_ERROR_NAMED("exporting of the selected auto resize strategy not implemented.");
241  }
242  }
243  message.mutable_grid_adapt_strategy()->set_adapt_first_iter(_adapt_first_iter);
244 
245  // others
246  message.set_n_min(_n_min);
247 }
248 #endif
249 
250 } // namespace corbo
#define PRINT_ERROR_NAMED(msg)
Definition: console.h:260
#define PRINT_WARNING_COND_NAMED(cond, msg)
Definition: console.h:257
return int(ret)+1
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:94
bool isTimeVariableGrid() const override
void resampleTrajectory(int n_new, NlpFunctions &nlp_fun)
bool adaptGridTimeBasedAggressiveEstimate(NlpFunctions &nlp_fun)
Eigen::Matrix< bool, -1, 1 > _xf_fixed
void setGridAdaptTimeBasedAggressiveEstimate(int n_max, double dt_hyst_ratio=0.1)
int getN() const override
const double & value() const
Get underlying value.
bool adaptGrid(bool new_run, NlpFunctions &nlp_fun) override
void setGridAdaptTimeBasedSingleStep(int n_max, double dt_hyst_ratio=0.1)
The matrix class, also used for vectors and row-vectors.
Definition: Matrix.h:178
PlainMatrixType mat * n
Definition: eigenvalues.cpp:41
EIGEN_DEVICE_FUNC const RoundReturnType round() const


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