- 3.0.2 optimal control module.
ConstraintDiscretizer.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
10 
14 
15 namespace ct {
16 namespace optcon {
17 
18 
29 template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR = double>
31 {
32 public:
33  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
34 
38 
41 
43  typedef Eigen::Matrix<SCALAR, Eigen::Dynamic, 1> VectorXs;
44 
48  ConstraintDiscretizer() = default;
52  ~ConstraintDiscretizer() override = default;
62  std::shared_ptr<SplinerBase<control_vector_t, SCALAR>> controlSpliner,
63  std::shared_ptr<tpl::TimeGrid<SCALAR>> timeGrid,
64  size_t N)
65  : w_(w),
66  controlSpliner_(controlSpliner),
67  timeGrid_(timeGrid),
68  N_(N),
69  constraintsCount_(0),
70  constraintsIntermediateCount_(0),
71  constraintsTerminalCount_(0),
72  nonZeroJacCount_(0),
73  nonZeroJacCountIntermediate_(0),
74  nonZeroJacCountTerminal_(0)
75  {
76  }
77 
78 
80  {
81  constraints_.push_back(boxConstraints);
82  constraintsIntermediateCount_ += (N_ + 1) * boxConstraints->getIntermediateConstraintsCount();
83  constraintsTerminalCount_ += boxConstraints->getTerminalConstraintsCount();
84  constraintsCount_ = constraintsIntermediateCount_ + constraintsTerminalCount_;
85 
86  discreteConstraints_.resize(constraintsCount_);
87  discreteLowerBound_.resize(constraintsCount_);
88  discreteUpperBound_.resize(constraintsCount_);
89 
90  nonZeroJacCountIntermediate_ += (N_ + 1) * (boxConstraints->getJacobianStateNonZeroCountIntermediate() +
91  boxConstraints->getJacobianInputNonZeroCountIntermediate());
92  nonZeroJacCountTerminal_ += boxConstraints->getJacobianStateNonZeroCountTerminal() +
93  boxConstraints->getJacobianInputNonZeroCountTerminal();
94  nonZeroJacCount_ = nonZeroJacCountIntermediate_ + nonZeroJacCountTerminal_;
95 
96  discreteJac_.resize(nonZeroJacCount_);
97  discreteIRow_.resize(nonZeroJacCount_);
98  discreteJCol_.resize(nonZeroJacCount_);
99  }
100 
102  std::shared_ptr<LinearConstraintContainer<STATE_DIM, CONTROL_DIM, SCALAR>> generalConstraints)
103  {
104  constraints_.push_back(generalConstraints);
105  constraintsIntermediateCount_ += (N_ + 1) * generalConstraints->getIntermediateConstraintsCount();
106  constraintsTerminalCount_ += generalConstraints->getTerminalConstraintsCount();
107  constraintsCount_ = constraintsIntermediateCount_ + constraintsTerminalCount_;
108 
109  discreteConstraints_.resize(constraintsCount_);
110  discreteLowerBound_.resize(constraintsCount_);
111  discreteUpperBound_.resize(constraintsCount_);
112 
113  nonZeroJacCountIntermediate_ += (N_ + 1) * generalConstraints->getJacobianStateNonZeroCountIntermediate();
114  nonZeroJacCountTerminal_ += generalConstraints->getJacobianStateNonZeroCountTerminal();
115  nonZeroJacCount_ = nonZeroJacCountIntermediate_ + nonZeroJacCountTerminal_;
116 
117  discreteJac_.resize(nonZeroJacCount_);
118  discreteIRow_.resize(nonZeroJacCount_);
119  discreteJCol_.resize(nonZeroJacCount_);
120  }
121 
122  VectorXs eval() override
123  {
124  size_t constraintSize = 0;
125  size_t discreteInd = 0;
126 
127  for (size_t n = 0; n < N_ + 1; ++n)
128  {
129  SCALAR tShot = timeGrid_->getShotStartTime(n);
130  for (auto constraint : constraints_)
131  {
132  constraint->setCurrentStateAndControl(
133  w_->getOptimizedState(n), controlSpliner_->evalSpline(tShot, n), tShot);
134  constraintSize = constraint->getIntermediateConstraintsCount();
135  if (constraintSize > 0)
136  {
137  discreteConstraints_.segment(discreteInd, constraintSize) = constraint->evaluateIntermediate();
138  discreteInd += constraintSize;
139  }
140  }
141  }
142 
143  for (auto constraint : constraints_)
144  {
145  constraintSize = constraint->getTerminalConstraintsCount();
146  if (constraintSize > 0)
147  {
148  discreteConstraints_.segment(discreteInd, constraintSize) = constraint->evaluateTerminal();
149  discreteInd += constraintSize;
150  }
151  }
152 
153  return discreteConstraints_;
154  }
155 
156  VectorXs evalSparseJacobian() override
157  {
158  size_t jacSize = 0;
159  size_t discreteInd = 0;
160 
161  for (size_t n = 0; n < N_ + 1; ++n)
162  {
163  SCALAR tShot = timeGrid_->getShotStartTime(n);
164 
165  for (auto constraint : constraints_)
166  {
167  constraint->setCurrentStateAndControl(
168  w_->getOptimizedState(n), controlSpliner_->evalSpline(tShot, n), tShot);
169  jacSize = constraint->getJacobianStateNonZeroCountIntermediate();
170  if (jacSize > 0)
171  {
172  discreteJac_.segment(discreteInd, jacSize) = constraint->jacobianStateSparseIntermediate();
173  discreteInd += jacSize;
174  }
175 
176  jacSize = constraint->getJacobianInputNonZeroCountIntermediate();
177  if (jacSize > 0)
178  {
179  discreteJac_.segment(discreteInd, jacSize) = constraint->jacobianInputSparseIntermediate();
180  discreteInd += jacSize;
181  }
182  }
183  }
184 
185  for (auto constraint : constraints_)
186  {
187  jacSize = constraint->getJacobianStateNonZeroCountTerminal();
188  if (jacSize > 0)
189  {
190  discreteJac_.segment(discreteInd, jacSize) = constraint->jacobianStateSparseTerminal();
191  discreteInd += jacSize;
192  }
193  jacSize = constraint->getJacobianInputNonZeroCountTerminal();
194  if (jacSize > 0)
195  {
196  discreteJac_.segment(discreteInd, jacSize) = constraint->jacobianInputSparseTerminal();
197  discreteInd += jacSize;
198  }
199  }
200 
201  return discreteJac_;
202  }
203 
204  size_t getNumNonZerosJacobian() override { return nonZeroJacCount_; }
205  void genSparsityPattern(Eigen::VectorXi& iRow_vec, Eigen::VectorXi& jCol_vec) override
206  {
207  size_t discreteInd = 0;
208  size_t rowOffset = 0;
209  size_t nnEle = 0;
210 
211  for (size_t n = 0; n < N_ + 1; ++n)
212  {
213  for (auto constraint : constraints_)
214  {
215  nnEle = constraint->getJacobianStateNonZeroCountIntermediate();
216  if (nnEle > 0)
217  {
218  Eigen::VectorXi iRowStateIntermediate(constraint->getJacobianStateNonZeroCountIntermediate());
219  Eigen::VectorXi jColStateIntermediate(constraint->getJacobianStateNonZeroCountIntermediate());
220  constraint->sparsityPatternStateIntermediate(iRowStateIntermediate, jColStateIntermediate);
221  discreteIRow_.segment(discreteInd, nnEle) = iRowStateIntermediate.array() + rowOffset;
222  discreteJCol_.segment(discreteInd, nnEle) = jColStateIntermediate.array() + w_->getStateIndex(n);
223  discreteInd += nnEle;
224  }
225 
226  nnEle = constraint->getJacobianInputNonZeroCountIntermediate();
227  if (nnEle > 0)
228  {
229  Eigen::VectorXi iRowInputIntermediate(constraint->getJacobianInputNonZeroCountIntermediate());
230  Eigen::VectorXi jColInputIntermediate(constraint->getJacobianInputNonZeroCountIntermediate());
231  constraint->sparsityPatternInputIntermediate(iRowInputIntermediate, jColInputIntermediate);
232  discreteIRow_.segment(discreteInd, nnEle) = iRowInputIntermediate.array() + rowOffset;
233  discreteJCol_.segment(discreteInd, nnEle) = jColInputIntermediate.array() + w_->getControlIndex(n);
234  discreteInd += nnEle;
235  }
236 
237  rowOffset += constraint->getIntermediateConstraintsCount();
238  }
239  }
240 
241  for (auto constraint : constraints_)
242  {
243  nnEle = constraint->getJacobianStateNonZeroCountTerminal();
244  if (nnEle > 0)
245  {
246  Eigen::VectorXi iRowStateTerminal(constraint->getJacobianStateNonZeroCountTerminal());
247  Eigen::VectorXi jColStateTerminal(constraint->getJacobianStateNonZeroCountTerminal());
248  constraint->sparsityPatternStateTerminal(iRowStateTerminal, jColStateTerminal);
249  discreteIRow_.segment(discreteInd, nnEle) = iRowStateTerminal.array() + rowOffset;
250  discreteJCol_.segment(discreteInd, nnEle) = jColStateTerminal.array() + w_->getStateIndex(N_);
251  discreteInd += nnEle;
252  }
253 
254  nnEle = constraint->getJacobianInputNonZeroCountTerminal();
255  if (nnEle > 0)
256  {
257  Eigen::VectorXi iRowInputTerminal(constraint->getJacobianInputNonZeroCountTerminal());
258  Eigen::VectorXi jColInputTerminal(constraint->getJacobianInputNonZeroCountTerminal());
259  constraint->sparsityPatternInputTerminal(iRowInputTerminal, jColInputTerminal);
260  discreteIRow_.segment(discreteInd, nnEle) = iRowInputTerminal.array() + rowOffset;
261  discreteJCol_.segment(discreteInd, nnEle) = jColInputTerminal.array() + w_->getControlIndex(N_);
262  discreteInd += nnEle;
263  }
264  rowOffset += constraint->getTerminalConstraintsCount();
265  }
266 
267  iRow_vec = discreteIRow_;
268  jCol_vec = discreteJCol_;
269  }
270 
271  VectorXs getLowerBound() override
272  {
273  size_t discreteInd = 0;
274  size_t constraintSize = 0;
275 
276  for (size_t n = 0; n < N_ + 1; ++n)
277  {
278  for (auto constraint : constraints_)
279  {
280  constraintSize = constraint->getIntermediateConstraintsCount();
281  if (constraintSize > 0)
282  {
283  discreteLowerBound_.segment(discreteInd, constraintSize) = constraint->getLowerBoundsIntermediate();
284  discreteInd += constraintSize;
285  }
286  }
287  }
288 
289  for (auto constraint : constraints_)
290  {
291  constraintSize = constraint->getTerminalConstraintsCount();
292  if (constraintSize > 0)
293  {
294  discreteLowerBound_.segment(discreteInd, constraintSize) = constraint->getLowerBoundsTerminal();
295  discreteInd += constraintSize;
296  }
297  }
298 
299  return discreteLowerBound_;
300  }
301 
302  VectorXs getUpperBound() override
303  {
304  size_t discreteInd = 0;
305  size_t constraintSize = 0;
306 
307  for (size_t n = 0; n < N_ + 1; ++n)
308  {
309  for (auto constraint : constraints_)
310  {
311  constraintSize = constraint->getIntermediateConstraintsCount();
312  if (constraintSize > 0)
313  {
314  discreteUpperBound_.segment(discreteInd, constraintSize) = constraint->getUpperBoundsIntermediate();
315  discreteInd += constraintSize;
316  }
317  }
318  }
319 
320  for (auto constraint : constraints_)
321  {
322  constraintSize = constraint->getTerminalConstraintsCount();
323  if (constraintSize > 0)
324  {
325  discreteUpperBound_.segment(discreteInd, constraintSize) = constraint->getUpperBoundsTerminal();
326  discreteInd += constraintSize;
327  }
328  }
329 
330  return discreteUpperBound_;
331  }
332 
333  size_t getConstraintSize() override { return constraintsCount_; }
334 private:
335  std::shared_ptr<OptVectorDms<STATE_DIM, CONTROL_DIM, SCALAR>> w_;
336  std::shared_ptr<SplinerBase<control_vector_t, SCALAR>> controlSpliner_;
337  std::shared_ptr<tpl::TimeGrid<SCALAR>> timeGrid_;
338  size_t N_;
339 
340  std::vector<std::shared_ptr<LinearConstraintContainer<STATE_DIM, CONTROL_DIM, SCALAR>>> constraints_;
341 
342  size_t constraintsCount_;
343  size_t constraintsIntermediateCount_;
344  size_t constraintsTerminalCount_;
345 
346  VectorXs discreteConstraints_;
347  VectorXs discreteLowerBound_;
348  VectorXs discreteUpperBound_;
349 
350  VectorXs discreteJac_;
351  Eigen::VectorXi discreteIRow_;
352  Eigen::VectorXi discreteJCol_;
353 
354  size_t nonZeroJacCount_;
355  size_t nonZeroJacCountIntermediate_;
356  size_t nonZeroJacCountTerminal_;
357 };
358 }
359 }
VectorXs getUpperBound() override
Returns the upper bound of the constraint.
Definition: ConstraintDiscretizer.h:302
VectorXs getLowerBound() override
Returns the lower bound of the constraint.
Definition: ConstraintDiscretizer.h:271
size_t getNumNonZerosJacobian() override
Returns the number of non zero elements of the jacobian.
Definition: ConstraintDiscretizer.h:204
A base function for linear constraint functions which have a first derivative.
Definition: LinearConstraintContainer.h:27
ct::core::ControlVectorArray< CONTROL_DIM, SCALAR > control_vector_array_t
Definition: ConstraintDiscretizer.h:40
void setGeneralConstraints(std::shared_ptr< LinearConstraintContainer< STATE_DIM, CONTROL_DIM, SCALAR >> generalConstraints)
Definition: ConstraintDiscretizer.h:101
ct::core::StateVector< STATE_DIM, SCALAR > state_vector_t
Definition: ConstraintDiscretizer.h:36
EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef tpl::DiscreteConstraintBase< SCALAR > BASE
Definition: ConstraintDiscretizer.h:35
Abstract base class for the control input splining between the DMS shots.
Definition: SplinerBase.h:20
ConstraintDiscretizer()=default
Default constructor.
Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 > VectorXs
Definition: ConstraintDiscretizer.h:43
Implements an abstract base class from which all the discrete custom NLP constraints should derive...
Definition: DiscreteConstraintBase.h:21
This class is a wrapper around the NLP Optvector. It wraps the Vectors from the NLP solvers into stat...
Definition: OptVectorDms.h:37
~ConstraintDiscretizer() override=default
Destructor.
void genSparsityPattern(Eigen::VectorXi &iRow_vec, Eigen::VectorXi &jCol_vec) override
Returns the sparsity structure of the constraint jacobian.
Definition: ConstraintDiscretizer.h:205
CppAD::AD< CppAD::cg::CG< double > > SCALAR
ConstraintDiscretizer(std::shared_ptr< OptVectorDms< STATE_DIM, CONTROL_DIM, SCALAR >> w, std::shared_ptr< SplinerBase< control_vector_t, SCALAR >> controlSpliner, std::shared_ptr< tpl::TimeGrid< SCALAR >> timeGrid, size_t N)
Custom constructor.
Definition: ConstraintDiscretizer.h:61
ct::core::StateVectorArray< STATE_DIM, SCALAR > state_vector_array_t
Definition: ConstraintDiscretizer.h:37
constexpr size_t n
void setBoxConstraints(std::shared_ptr< LinearConstraintContainer< STATE_DIM, CONTROL_DIM, SCALAR >> boxConstraints)
Definition: ConstraintDiscretizer.h:79
Definition: TimeGrid.h:27
VectorXs evalSparseJacobian() override
Returns the non zero elements of the eval method with respect to the optimization variables...
Definition: ConstraintDiscretizer.h:156
ct::core::tpl::TimeArray< SCALAR > time_array_t
Definition: ConstraintDiscretizer.h:42
size_t getConstraintSize() override
Returns size of the constraint vector.
Definition: ConstraintDiscretizer.h:333
The class takes continuous constraints defined with the constraint toolbox and discretizes them over ...
Definition: ConstraintDiscretizer.h:30
ct::core::ControlVector< CONTROL_DIM, SCALAR > control_vector_t
Definition: ConstraintDiscretizer.h:39
VectorXs eval() override
Evaluates the constraint violation.
Definition: ConstraintDiscretizer.h:122