aligator  0.6.1
A primal-dual augmented Lagrangian-type solver for nonlinear trajectory optimization.
Loading...
Searching...
No Matches
finite-difference.hpp
Go to the documentation of this file.
1
3#pragma once
4
7#include <proxsuite-nlp/manifold-base.hpp>
8#include <boost/mpl/bool.hpp>
9
10namespace aligator {
11namespace autodiff {
12
13namespace internal {
14
15// fwd declare the implementation of finite difference algorithms.
16template <typename _Scalar, template <typename> class _Base>
17struct finite_difference_impl : virtual _Base<_Scalar> {
18 using Scalar = _Scalar;
20 using Base = _Base<Scalar>;
21 using BaseData = typename Base::Data;
22 using Manifold = ManifoldAbstractTpl<Scalar>;
23
24 shared_ptr<Manifold> space_;
25 shared_ptr<Base> func_;
26 Scalar fd_eps;
27 int nx1, nx2;
28
29 struct Data : BaseData {
30 using BaseData::ndx1;
31 using BaseData::ndx2;
32 using BaseData::nr;
33 using BaseData::nu;
34 shared_ptr<BaseData> data_0;
35 shared_ptr<BaseData> data_1;
36 VectorXs dx, du, dy;
37 VectorXs xp, up, yp;
38
39 Data(finite_difference_impl const &model)
40 : BaseData(model.ndx1, model.nu, model.ndx2, model.nr),
41 data_0(model.func_->createData()), data_1(model.func_->createData()),
42 dx(ndx1), du(nu), dy(ndx2), xp(model.nx1), up(model.nu),
43 yp(model.nx2) {
44 dx.setZero();
45 du.setZero();
46 dy.setZero();
47 }
48 };
49
50 template <typename U = Base, class = std::enable_if_t<
51 std::is_same_v<U, StageFunctionTpl<Scalar>>>>
52 finite_difference_impl(shared_ptr<Manifold> space, shared_ptr<U> func,
53 const Scalar fd_eps)
54 : Base(func->ndx1, func->nu, func->ndx2, func->nr), space_(space),
55 func_(func), fd_eps(fd_eps), nx1(space->nx()), nx2(space->nx()) {}
56
57 template <typename U = Base, class = std::enable_if_t<
58 std::is_same_v<U, DynamicsModelTpl<Scalar>>>>
59 finite_difference_impl(shared_ptr<Manifold> space, shared_ptr<U> func,
60 const Scalar fd_eps, boost::mpl::false_ = {})
61 : Base(space, func->nu, space), space_(space), func_(func),
62 fd_eps(fd_eps), nx1(space->nx()), nx2(space->nx()) {}
63
64 void evaluate(const ConstVectorRef &x, const ConstVectorRef &u,
65 const ConstVectorRef &y, BaseData &data) const {
66 Data &d = static_cast<Data &>(data);
67 func_->evaluate(x, u, y, *d.data_0);
68 d.value_ = d.data_0->value_;
69 }
70
71 void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u,
72 const ConstVectorRef &y, BaseData &data) const {
73 Data &d = static_cast<Data &>(data);
74
75 VectorXs &v0 = d.data_0->value_;
76 VectorXs &vp = d.data_1->value_;
77
78 for (int i = 0; i < func_->ndx1; i++) {
79 d.dx[i] = fd_eps;
80 space_->integrate(x, d.dx, d.xp);
81 func_->evaluate(d.xp, u, y, *d.data_1);
82 data.Jx_.col(i) = (vp - v0) / fd_eps;
83 d.dx[i] = 0.;
84 }
85
86 for (int i = 0; i < func_->ndx2; i++) {
87 d.dy[i] = fd_eps;
88 space_->integrate(y, d.dy, d.yp);
89 func_->evaluate(x, u, d.yp, *d.data_1);
90 data.Jy_.col(i) = (vp - v0) / fd_eps;
91 d.dy[i] = 0.;
92 }
93
94 for (int i = 0; i < func_->nu; i++) {
95 d.du[i] = fd_eps;
96 d.up = u + d.du;
97 func_->evaluate(x, d.up, y, *d.data_1);
98 data.Ju_.col(i) = (vp - v0) / fd_eps;
99 d.du[i] = 0.;
100 }
101 }
102
103 void computeVectorHessianProducts(const ConstVectorRef &,
104 const ConstVectorRef &,
105 const ConstVectorRef &,
106 const ConstVectorRef &, BaseData &) const {}
107
108 shared_ptr<BaseData> createData() const {
109 return std::make_shared<Data>(*this);
110 }
111};
112
113} // namespace internal
114
115template <typename _Scalar> struct FiniteDifferenceHelper;
116
121template <typename _Scalar>
123 : internal::finite_difference_impl<_Scalar, StageFunctionTpl> {
124 using Scalar = _Scalar;
125
126 using StageFunction = StageFunctionTpl<Scalar>;
127 using Manifold = ManifoldAbstractTpl<Scalar>;
128 using Base = internal::finite_difference_impl<Scalar, StageFunctionTpl>;
129 using Base::computeJacobians;
130 using Base::computeVectorHessianProducts;
131 using Base::evaluate;
132
134
135 FiniteDifferenceHelper(shared_ptr<Manifold> space,
136 shared_ptr<StageFunction> func, const Scalar fd_eps)
137 : StageFunction(func->ndx1, func->nu, func->ndx2, func->nr),
138 Base(space, func, fd_eps) {}
139};
140
141template <typename _Scalar>
143 : internal::finite_difference_impl<_Scalar, DynamicsModelTpl> {
144 using Scalar = _Scalar;
145
146 using DynamicsModel = DynamicsModelTpl<Scalar>;
147 using Manifold = ManifoldAbstractTpl<Scalar>;
148 using Base = internal::finite_difference_impl<Scalar, DynamicsModelTpl>;
149 using Base::computeJacobians;
150 using Base::computeVectorHessianProducts;
151 using Base::evaluate;
152
154
155 DynamicsFiniteDifferenceHelper(shared_ptr<Manifold> space,
156 shared_ptr<DynamicsModel> func,
157 const Scalar fd_eps)
158 : DynamicsModel(space, func->nu, space), Base(space, func, fd_eps) {}
159};
160
161template <typename Scalar>
163 using Manifold = ManifoldAbstractTpl<Scalar>;
164 using CostBase = CostAbstractTpl<Scalar>;
165 using CostData = CostDataAbstractTpl<Scalar>;
166
167 using CostBase::space;
168
170
171 struct Data : CostData {
172
173 shared_ptr<CostData> c1, c2;
174 VectorXs dx, du;
175 VectorXs xp, up;
176
178 : CostData(obj), dx(obj.ndx()), du(obj.nu), xp(obj.nx()), up(obj.nu) {
179 c1 = obj.cost_->createData();
180 c2 = obj.cost_->createData();
181 }
182 };
183
184 CostFiniteDifferenceHelper(shared_ptr<CostBase> cost, const Scalar fd_eps)
185
186 : CostBase(cost->space, cost->nu), cost_(cost), fd_eps(fd_eps) {}
187
188 void evaluate(const ConstVectorRef &x, const ConstVectorRef &u,
189 CostData &data_) const override {
190 Data &d = static_cast<Data &>(data_);
191 cost_->evaluate(x, u, *d.c1);
192
193 d.value_ = d.c1->value_;
194 }
195
196 void computeGradients(const ConstVectorRef &x, const ConstVectorRef &u,
197 CostData &data_) const override {
198 Data &d = static_cast<Data &>(data_);
199 Manifold const &space = *this->space;
200
201 cost_->evaluate(x, u, *d.c1);
202
203 d.dx.setZero();
204 for (int i = 0; i < this->ndx(); i++) {
205 d.dx[i] = fd_eps;
206 space.integrate(x, d.dx, d.xp);
207 cost_->evaluate(d.xp, u, *d.c2);
208
209 d.Lx_[i] = (d.c2->value_ - d.c1->value_) / fd_eps;
210 d.dx[i] = 0.;
211 }
212
213 d.du.setZero();
214 for (int i = 0; i < this->nu; i++) {
215 d.du[i] = fd_eps;
216 d.up = u + d.du;
217 cost_->evaluate(x, d.up, *d.c2);
218
219 d.Lu_[i] = (d.c2->value_ - d.c1->value_) / fd_eps;
220 d.du[i] = 0.;
221 }
222 }
223
225 void computeHessians(const ConstVectorRef &, const ConstVectorRef &,
226 CostData &) const override {}
227
228 shared_ptr<CostData> createData() const override {
229 return std::make_shared<Data>(*this);
230 }
231
232 shared_ptr<CostBase> cost_;
234};
235
236#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
237extern template struct FiniteDifferenceHelper<context::Scalar>;
238extern template struct DynamicsFiniteDifferenceHelper<context::Scalar>;
239extern template struct CostFiniteDifferenceHelper<context::Scalar>;
240#endif
241
242} // namespace autodiff
243} // namespace aligator
#define ALIGATOR_DYNAMIC_TYPEDEFS(Scalar)
Definition math.hpp:18
Main package namespace.
Stage costs for control problems.
shared_ptr< Manifold > space
State dimension.
CostFiniteDifferenceHelper(shared_ptr< CostBase > cost, const Scalar fd_eps)
shared_ptr< CostData > createData() const override
void computeGradients(const ConstVectorRef &x, const ConstVectorRef &u, CostData &data_) const override
Compute the cost gradients .
void evaluate(const ConstVectorRef &x, const ConstVectorRef &u, CostData &data_) const override
Evaluate the cost function.
void computeHessians(const ConstVectorRef &, const ConstVectorRef &, CostData &) const override
Compute the cost Hessians .
internal::finite_difference_impl< Scalar, DynamicsModelTpl > Base
DynamicsFiniteDifferenceHelper(shared_ptr< Manifold > space, shared_ptr< DynamicsModel > func, const Scalar fd_eps)
Approximate the derivatives of a given function using finite differences, to downcast the function to...
FiniteDifferenceHelper(shared_ptr< Manifold > space, shared_ptr< StageFunction > func, const Scalar fd_eps)
internal::finite_difference_impl< Scalar, StageFunctionTpl > Base