DirectTrajectoryOptimization  v0.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
base_method_interface.hpp
Go to the documentation of this file.
1 /***********************************************************************************
2 Copyright (c) 2017, Diego Pardo. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without modification,
5 are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright notice,
7  this list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright notice,
9  this list of conditions and the following disclaimer in the documentation
10  and/or other materials provided with the distribution.
11  * Neither the name of ETH ZURICH nor the names of its contributors may be used
12  to endorse or promote products derived from this software without specific
13  prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
16 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
18 SHALL ETH ZURICH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 ***************************************************************************************/
25 
30 #ifndef INCLUDE_METHOD_INTERFACES_BASE_METHOD_INTERFACE_HPP_
31 #define INCLUDE_METHOD_INTERFACES_BASE_METHOD_INTERFACE_HPP_
32 
33 #define infy 1e20
34 
35 #include <unistd.h>
36 #include <Eigen/Core>
37 #include <cmath>
38 #include <map>
39 #include <memory>
40 #include <vector>
41 
42 #include <method_interfaces/nonlinear_program/nonlinear_program.hpp>
43 
44 #include <dynamical_systems/base/DynamicsBase.hpp>
45 #include <dynamical_systems/base/DerivativesBaseDS.hpp>
48 #include <optimization/constraints/InterPhaseBaseConstraint.hpp>
49 #include <optimization/constraints/GuardBase.hpp>
50 
51 namespace DirectTrajectoryOptimization {
52 
59 template<typename DIMENSIONS>
61 
62 public:
63  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
64 
65  typedef typename DIMENSIONS::state_vector_t state_vector_t;
66  typedef typename DIMENSIONS::control_vector_t control_vector_t;
67  typedef typename DIMENSIONS::state_vector_array_t state_vector_array_t;
68  typedef typename DIMENSIONS::control_vector_array_t control_vector_array_t;
69 
70  virtual ~DTOMethodInterface() {
71 
72  }
73 
80  std::vector<std::shared_ptr<DynamicsBase<DIMENSIONS> > > dynamics,
81  std::vector<std::shared_ptr<DerivativesBaseDS<DIMENSIONS> > > derivatives,
82  std::shared_ptr<BaseClass::CostFunctionBase<DIMENSIONS> > costFunction,
83  std::vector<std::shared_ptr<BaseClass::ConstraintsBase<DIMENSIONS> > > constraints,
84  Eigen::Vector2d duration, int number_of_nodes, bool methodVerbose);
85 
86  /* user functions */
87  void Initialize(); // WHY is THE SOLVER Initializing the method?
88  virtual void SetDircolMethod(const int &dcm) {}
89  void SetInitialState(const state_vector_t & y0);
90  void SetFinalState(const state_vector_t & yF);
91 
92  void SetInitialControl(const control_vector_t & u0);
93  void SetFinalControl(const control_vector_t & uf);
94 
95  void SetFinalVelocityZero(const Eigen::VectorXi & indexes) {
96  vel_state_to_zero.resize(indexes.rows());
97  vel_state_to_zero = indexes;
98  _finalVelocityZero = true;
99  }
100 
101  void SetEvenTimeIncrements(bool flag) {
102  _evenTimeIncr = flag;
103  }
104  void SetVerbosity(bool verbose) {
105  _verbose = verbose;
106  }
107 
108  void SetGuardFunction(std::vector<double (*)(state_vector_t&)> usrFct) {
109 
110  if (usrFct.size() != num_phases - 1) {
111  throw std::invalid_argument("Vector of guard functions are of the wrong size.");
112  }
113 
114  //Future: this must be a condition given a vector of dynamics and not user-dependent
115  _guardVector = usrFct;
116  _usingGuardFunction = true;
117  }
118 
119  void SetInterPhaseFunctions(std::vector<std::shared_ptr<BaseClass::GuardBase<DIMENSIONS> > > gconst,
120  std::vector<std::shared_ptr<BaseClass::InterPhaseBase<DIMENSIONS>>> intph) {
121 
122  if (gconst.size() != num_phases - 1) {
123  throw std::invalid_argument("Vector of guard functions are of the wrong size.");
124  }
125 
126  if (intph.size() != num_phases - 1) {
127  throw std::invalid_argument("Vector of interPhase functions are of the wrong size.");
128  }
129 
130  _guards = gconst;
131  _interphase_constraint = intph;
132 
133  //_usingGuardFunction = true;
134  }
135 
136  void SetPercentageNodesPerDynamics(Eigen::VectorXd nodeSplit);
137  void SetNodesPerPhase(const Eigen::VectorXi & nodes);
138  void SetStateBounds(const state_vector_t & lb, const state_vector_t & ub);
139  void SetStateBounds(const state_vector_array_t & lb, const state_vector_array_t & ub);
140  void SetControlBounds(const control_vector_t & lb, const control_vector_t & ub);
141  void SetControlBounds(const control_vector_array_t & lb, const control_vector_array_t & ub);
142  void SetFreeFinalState(int state_number);
143 
144  // Check this!!, redundat w.r.t. solver?!
145  void InitializeNLPvector(Eigen::VectorXd & x,
146  const state_vector_array_t & state_initial,
147  const control_vector_array_t & control_initial,
148  const Eigen::VectorXd & h_initial);
149 
150  void setTimeIncrementsBounds(const double & h_min, const double & h_max);
151 
152  /* Public Methods allow to collect data from the solver app */
153  inline int getNumDefects() {
154  return num_defects;
155  }
156 
157  // Check this! remove TEMPLATE from SOLVER
158  inline int getNumStates() {
159  return _numStates;
160  }
161  inline int getNumActions() {
162  return _numControls;
163  }
164  inline int getNumIncrements() {
165  return n_inc;
166  }
167 
168  // The solver is using this for set names of the variables?
169  // ToDo: Bring that to this class
170  void getTrajectoryIndexes(Eigen::VectorXi &hs, Eigen::MatrixXi &ys,
171  Eigen::MatrixXi &us);
172 
173  // CHECK: Deprecated way of getting the DTO solution
174  // ToDo : User should get solution from THIS CLASS
175  // ToDo : when finished, solver should update the DTO NLP member
176  // int getSolution(Eigen::VectorXd &hs, Eigen::MatrixXd &ys,
177  // Eigen::MatrixXd &us, Eigen::VectorXd & contact_switching_index);
178 
179  // Solver interface functions
180  void UpdateDecisionVariables(const double* x);
181  void evalObjective(double *f);
182  void evalConstraintFct(double* g, const int& m);
183 
184  void evalSparseJacobianCost(double* val);
185  virtual void evalSparseJacobianConstraint(double* val) = 0;
186 
187 protected :
188 
189  /* Called during class initialization */
190  void SetSizeOfVariables();
191  void SetSizeOfConstraints();
192  void SetTOConstraintsBounds();
193  void SetTOVariablesBounds();
194  void SetupJacobianVariables();
195  virtual void Method_specific_initialization() {}; // virtual method to allow specific initialization of the methods
196 
197  /* setting G-Jacobian sparsity */
198  void setNLPnnzConstraintJacobian();
199  void setSparsityJacobianCost();
200  void setSparsityJacobianConstraint();
201 
202  /* auxiliary for setting G-Jacobian sparsity */
203  int getNumNonZeroUserJacobian();
204  int getNumNonZeroGuardFunctionJacobian();
205  int getNumNonZeroInterphaseJacobian();
206 
207  /* setting Gcost-Jacobian sparsity */
208  void setNLPnnzCostFunctionJacobian();
209 
210  /* validate user inputs */
211  bool ValidateDuration();
212  bool ValidateStateControlBounds();
213 
214  /* required to getConstraintFct */
215  virtual void evaluateDefects(Eigen::VectorXd & defect_vector) = 0;
216  void evaluateParametricConstraints(Eigen::VectorXd & parametric_vector);
217  void evaluateUserConstraints(Eigen::VectorXd & constraints_vector);
218  void evaluateGuardConstraints(Eigen::VectorXd & constraints_vector);
219  void evaluateInterphaseConstraints(Eigen::VectorXd & constraints_vector);
220 
221 
222 public:
223 
224  void getStateControlIncrementsTrajectoriesFromDecisionVariables(
225  const Eigen::Map<Eigen::VectorXd> & x_local,
226  state_vector_array_t & y_trajectory,
227  control_vector_array_t & u_trajectory,
228  Eigen::VectorXd & h_trajectory);
229  void getStateControlIncrementsTrajectoriesFromDecisionVariables(
230  const Eigen::VectorXd & x_local,
231  state_vector_array_t & y_trajectory,
232  control_vector_array_t & u_trajectory,
233  Eigen::VectorXd & h_trajectory);
234 
235  void UpdateDTOTrajectoriesFromDecisionVariables(
236  const Eigen::Map<Eigen::VectorXd> & x_local);
237 
238  void getCompleteSolution(state_vector_array_t & yTraj,
239  state_vector_array_t & ydotTraj,
240  control_vector_array_t & uTraj,
241  Eigen::VectorXd & hTraj,
242  std::vector<int> & phaseId) const;
243 
244  void SetDecisionVariablesFromStateControlIncrementsTrajectories(
245  Eigen::VectorXd & x_vector,
246  const state_vector_array_t & y_sol,
247  const control_vector_array_t & u_sol,
248  const Eigen::VectorXd & h_sol);
249 
250  void getProtectedVariables(state_vector_array_t & y_t , state_vector_array_t & yd_t,
251  control_vector_array_t & u_t, Eigen::VectorXd & h_t) {
252  y_t = _y_trajectory;
253  yd_t = _ydot_trajectory;
254  u_t = _u_trajectory;
255  h_t = _h_trajectory;
256  }
257 
258 protected:
259 
260  bool _verbose;
261  int _numberOfNodes;
262  int _minNodesPerPhase = 2;
263  double min_traj_time = 0.01;
264  double minimum_increment_size = 0.005;//0.0015;//0.0015; //0.01; // Default values for DT
265  double maximum_increment_size = 0.1;//0.15; //0.2;
266  bool _initialControlZero = false;
267  bool _finalVelocityZero = false;
268  bool _evenTimeIncr = false;
269  bool _nodeSplitSet = false;
270  bool _nodeDistribution = false;
271  bool _usingGuardFunction = false;
272  bool _multiphaseproblem = false;
273 
274  Eigen::Vector2d _trajTimeRange;
275  Eigen::VectorXd _nodeSplitPercentage;
276 
277  const int _numStates;
278  const int _numControls;
279 
280  int num_phases = 0;
281 public:
282  int n_inc = 0;
283  int num_defects = 0;
284 protected:
285  int num_parametric_constraints = 0;
286  int num_user_constraints = 0;
287  int num_guards = 0;
288  int num_interphase_constraints = 0;
289 
290  int nnz_user_constraints = 0;
291 
292  std::vector<int> num_user_constraints_per_node_in_phase;
293  std::vector<int> num_nonzero_jacobian_user_per_node_in_phase;
294 
295  std::vector<int> size_interphase_constraint;
296  std::vector<int> size_guard;
297 
298  // System states and actions initial and final conditions and bounds
299  state_vector_t y_0, y_f;
300  state_vector_array_t y_lb, y_ub;
301  control_vector_t u_0, u_f;
302  control_vector_array_t u_lb, u_ub;
303 
304  // Velocity Index to set to zero
305  Eigen::VectorXi vel_state_to_zero;
306 
307  // flags to verify user setting final_state
308  // ToDo: convert to boolean arrays using 'typedef Matrix<bool, Dynamic, 1> VectorXb;'
309  Eigen::VectorXi _flagInitialState;
310  Eigen::VectorXi _flagFinalState;
311 
312  Eigen::VectorXi _flagInitialControl;
313  Eigen::VectorXi _flagFinalControl;
314 
315  // indexes of the TO problem in the Optimization vector
316  Eigen::VectorXi h_inds;
317  Eigen::MatrixXi y_inds;
318  Eigen::MatrixXi u_inds;
319 
320  // Number of node of the bounds between phases
321  Eigen::VectorXi leftphase_nodes;
322  Eigen::VectorXi rightphase_nodes;
323 
324  // Defect bounds (Just for readability)
325  Eigen::VectorXd defects_ub;
326  Eigen::VectorXd defects_lb;
327 
328  // Parametric bounds
329  Eigen::VectorXd parametricConstraints_lb;
330  Eigen::VectorXd parametricConstraints_ub;
331 
332  // User Constraints bounds
333  Eigen::VectorXd userConstraints_lb;
334  Eigen::VectorXd userConstraints_ub;
335 
336  // Guard Function bounds
337  Eigen::VectorXd guard_lb;
338  Eigen::VectorXd guard_ub;
339 
340  // Interphase Constraints bounds
341  Eigen::VectorXd interphase_lb;
342  Eigen::VectorXd interphase_ub;
343 
344  // Constraint vectors
345  Eigen::VectorXd defect_out_;
346  Eigen::VectorXd parametric_out_;
347  Eigen::VectorXd user_constraints_out_;
348 
349  // Guard vectors
350  Eigen::VectorXd guard_vector_;
351  Eigen::VectorXd interface_vector_;
352 
353 
354  // Solution to log using Cereal
355  Eigen::VectorXd increments_solution;
356  Eigen::VectorXd time_solution;
357  Eigen::MatrixXd states_solution;
358  Eigen::MatrixXd controls_solution;
359  bool problem_is_infeasible = false;
360 
361 
362 public:
363  // dynamic to node mapping
364  // ToDo this should be a map from int to weak_ptr's but this
365  // may cause issues with Eigen...
366  std::vector<int> node_to_phase_map;
367  std::vector<int> number_nodes_phase;
368  std::vector<int> user_non_zero_G_phase;
369  std::vector<double (*)(state_vector_t &)> _guardVector;
370  std::vector<void (*)(state_vector_t &x, state_vector_t & J) > _guardVectorDerivative;
371 
372 //protected:
373  // dto trajectories
374  state_vector_array_t _y_trajectory;
375  control_vector_array_t _u_trajectory;
376  Eigen::VectorXd _h_trajectory;
377  state_vector_array_t _ydot_trajectory;
378 
379 public:
380  // shared_ptr's
381  std::vector<std::shared_ptr<DynamicsBase<DIMENSIONS> > > _dynamics; /* to system dynamics */
382  std::vector<std::shared_ptr<DerivativesBaseDS<DIMENSIONS> > > _derivatives; /* to dynamics derivatives */
383  std::shared_ptr<BaseClass::CostFunctionBase<DIMENSIONS> > _costFunction; /* to cost Function*/
384  std::vector<std::shared_ptr<BaseClass::ConstraintsBase<DIMENSIONS> > > _constraints;/* to constraints*/
385  std::vector<std::shared_ptr<BaseClass::InterPhaseBase<DIMENSIONS> > > _interphase_constraint; /* to interphase_constraints */
386  std::vector<std::shared_ptr<BaseClass::GuardBase<DIMENSIONS> > > _guards; /* to guards constraints */
387 
388  //NLP
389 public:
390  nonlinearprogram myNLP;
391 
392 };
393 
394 } //namespace DirectTrajectoryOptimization
395 
396 #include <method_interfaces/bmi_implementation.hpp>
397 
398 #endif /*INCLUDE_METHOD_INTERFACES_BASE_METHOD_INTERFACE_HPP_*/
This class serves as a base interface for inheriting classes.
Definition: base_method_interface.hpp:60
This class contains all the information related to the NLP.
Definition: nonlinear_program.hpp:44
Base class for constraints.
Base class for TO constraints.
Definition: ConstraintsBase.hpp:46
Base class to derive cost functions.
DTOMethodInterface(std::vector< std::shared_ptr< DynamicsBase< DIMENSIONS > > > dynamics, std::vector< std::shared_ptr< DerivativesBaseDS< DIMENSIONS > > > derivatives, std::shared_ptr< BaseClass::CostFunctionBase< DIMENSIONS > > costFunction, std::vector< std::shared_ptr< BaseClass::ConstraintsBase< DIMENSIONS > > > constraints, Eigen::Vector2d duration, int number_of_nodes, bool methodVerbose)
Construct an instance of the DTOMethodInterface class.
Definition: bmi_implementation.hpp:35