aligator  0.14.0
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
8#include <boost/mpl/bool.hpp>
9
10namespace aligator {
11namespace autodiff {
12
13namespace internal {
14
15template <typename _Scalar, template <typename> class _BaseTpl>
16struct finite_diff_traits;
17
18template <typename Scalar> struct finite_diff_traits<Scalar, StageFunctionTpl> {
20 struct Data : StageFunctionDataTpl<Scalar> {
21 using SFD = StageFunctionDataTpl<Scalar>;
22 using SFD::ndx1;
23 using SFD::nu;
24 shared_ptr<SFD> data_0;
25 shared_ptr<SFD> data_1;
26 VectorXs dx, du;
27 VectorXs xp, up;
28
29 template <typename U>
30 Data(U const &model)
31 : SFD(*model.func_)
32 , data_0(model.func_->createData())
33 , data_1(model.func_->createData())
34 , dx(ndx1)
35 , du(nu)
36 , xp(model.nx1)
37 , up(model.nu) {
38 dx.setZero();
39 du.setZero();
40 }
41 };
42
43 struct Args {
44 ConstVectorRef x;
45 ConstVectorRef u;
46 };
47};
48
49template <typename Scalar> struct finite_diff_traits<Scalar, DynamicsModelTpl> {
51 struct Data : DynamicsDataTpl<Scalar> {
52 using DD = DynamicsDataTpl<Scalar>;
53 using DD::ndx1;
54 using DD::ndx2;
55 using DD::nu;
56 shared_ptr<DD> data_0;
57 shared_ptr<DD> data_1;
58 VectorXs dx, du, dy;
59 VectorXs xp, up, yp;
60
61 template <typename U>
62 Data(U const &model)
63 : DD(*model.func_)
64 , data_0(model.func_->createData())
65 , data_1(model.func_->createData())
66 , dx(ndx1)
67 , du(nu)
68 , dy(ndx2)
69 , xp(model.nx1)
70 , up(model.nu)
71 , yp(model.nx2) {
72 dx.setZero();
73 du.setZero();
74 dy.setZero();
75 }
76 };
77
78 struct Args {
79 ConstVectorRef x;
80 ConstVectorRef u;
81 ConstVectorRef y;
82 };
83};
84
86template <typename _Scalar, template <typename> class _BaseTpl>
87struct finite_difference_impl : finite_diff_traits<_Scalar, _BaseTpl> {
88 using Scalar = _Scalar;
90 using Traits = finite_diff_traits<Scalar, _BaseTpl>;
91 using Data = typename Traits::Data;
92 using Args = typename Traits::Args;
93 using Base = _BaseTpl<Scalar>;
94 using BaseData = typename Base::Data;
95 using Manifold = ManifoldAbstractTpl<Scalar>;
96
97 static_assert(std::is_base_of_v<BaseData, Data>);
98
99 xyz::polymorphic<Manifold> space_;
100 xyz::polymorphic<Base> func_;
101 Scalar fd_eps;
102 int nx1, nu, nx2;
103
104 static constexpr bool IsDynamics =
105 std::is_same_v<Base, DynamicsModelTpl<Scalar>>;
106
107 template <typename U = Base, class = std::enable_if_t<
108 std::is_same_v<U, StageFunctionTpl<Scalar>>>>
109 finite_difference_impl(xyz::polymorphic<Manifold> space,
110 xyz::polymorphic<U> func, const Scalar fd_eps)
111 : space_(space)
112 , func_(func)
113 , fd_eps(fd_eps)
114 , nx1(space->nx())
115 , nx2(space->nx()) {}
116
117 template <typename U = Base, class = std::enable_if_t<
118 std::is_same_v<U, DynamicsModelTpl<Scalar>>>>
119 finite_difference_impl(xyz::polymorphic<Manifold> space,
120 xyz::polymorphic<U> func, const Scalar fd_eps,
121 boost::mpl::false_ = {})
122 : space_(space)
123 , func_(func)
124 , fd_eps(fd_eps)
125 , nx1(space->nx())
126 , nu(func->nu)
127 , nx2(space->nx()) {}
128
131 void evaluateImpl(const Args &args, BaseData &data) const {
132 Data &d = static_cast<Data &>(data);
133 assert(d.data_0);
134 assert(d.data_1);
135 if constexpr (IsDynamics) {
136 func_->evaluate(args.x, args.u, args.y, *d.data_0);
137 } else {
138 func_->evaluate(args.x, args.u, *d.data_0);
139 }
140 d.value_ = d.data_0->value_;
141 }
142
143 void computeJacobiansImpl(const Args &args, BaseData &data) const {
144 Data &d = static_cast<Data &>(data);
145 assert(d.data_0);
146 assert(d.data_1);
147
148 VectorXs &v0 = d.data_0->value_;
149 VectorXs &vp = d.data_1->value_;
150
151 for (int i = 0; i < func_->ndx1; i++) {
152 d.dx[i] = fd_eps;
153 space_->integrate(args.x, d.dx, d.xp);
154 if constexpr (IsDynamics) {
155 func_->evaluate(d.xp, args.u, args.y, *d.data_1);
156 } else {
157 func_->evaluate(d.xp, args.u, *d.data_1);
158 }
159 data.Jx_.col(i) = (vp - v0) / fd_eps;
160 d.dx[i] = 0.;
161 }
162
163 if constexpr (IsDynamics) {
164 for (int i = 0; i < func_->ndx2; i++) {
165 d.dy[i] = fd_eps;
166 space_->integrate(args.y, d.dy, d.yp);
167 func_->evaluate(args.x, args.u, d.yp, *d.data_1);
168 data.Jy_.col(i) = (vp - v0) / fd_eps;
169 d.dy[i] = 0.;
170 }
171 }
172
173 for (int i = 0; i < func_->nu; i++) {
174 d.du[i] = fd_eps;
175 d.up = args.u + d.du;
176 if constexpr (IsDynamics) {
177 func_->evaluate(args.x, d.up, args.y, *d.data_1);
178 } else {
179 func_->evaluate(args.x, d.up, *d.data_1);
180 }
181 data.Ju_.col(i) = (vp - v0) / fd_eps;
182 d.du[i] = 0.;
183 }
184 }
185
186 void computeVectorHessianProductsImpl(const ConstVectorRef &,
187 const ConstVectorRef &,
188 const ConstVectorRef &,
189 const ConstVectorRef &,
190 BaseData &) const {}
191
192 shared_ptr<BaseData> createDataImpl() const {
193 return std::make_shared<Data>(*this);
194 }
195};
196
197} // namespace internal
198
199template <typename _Scalar> struct FiniteDifferenceHelper;
200
205template <typename _Scalar>
207 using Scalar = _Scalar;
208 using Impl = internal::finite_difference_impl<Scalar, StageFunctionTpl>;
209
212 using Data = typename Impl::Data;
214
216
219 const Scalar fd_eps)
220 : StageFunction(func->ndx1, func->nu, func->nr)
221 , impl(space, func, fd_eps) {}
222
223 void evaluate(const ConstVectorRef &x, const ConstVectorRef &u,
224 BaseData &data) const {
225 impl.evaluateImpl({x, u}, data);
226 }
227
228 void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u,
229 BaseData &data) const {
230 impl.computeJacobiansImpl({x, u}, data);
231 }
232
233 shared_ptr<BaseData> createData() const { return impl.createDataImpl(); }
234
235private:
236 Impl impl;
237};
238
239template <typename _Scalar>
241 using Scalar = _Scalar;
242
245 using Impl = internal::finite_difference_impl<Scalar, DynamicsModelTpl>;
246 using Data = typename Impl::Data;
248
250
256
257 void evaluate(const ConstVectorRef &x, const ConstVectorRef &u,
258 const ConstVectorRef &xn, BaseData &data) const {
259 impl.evaluateImpl({x, u, xn}, data);
260 }
261
262 void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u,
263 const ConstVectorRef &xn, BaseData &data) const {
264 impl.computeJacobiansImpl({x, u, xn}, data);
265 }
266
267 shared_ptr<BaseData> createData() const { return impl.createDataImpl(); }
268
269private:
270 Impl impl;
271};
272
273#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
274extern template struct FiniteDifferenceHelper<context::Scalar>;
275extern template struct DynamicsFiniteDifferenceHelper<context::Scalar>;
276#endif
277
278} // namespace autodiff
279} // namespace aligator
Base definitions for ternary functions.
#define ALIGATOR_DYNAMIC_TYPEDEFS(Scalar)
Definition math.hpp:8
::aligator::context::Scalar Scalar
Definition context.hpp:14
Main package namespace.
constexpr auto data(C &c) noexcept(noexcept(c.data())) -> decltype(c.data())
Definition data.hpp:18
const Manifold & space() const
State space for the input.
Definition dynamics.hpp:32
const int nu
Control dimension.
Definition dynamics.hpp:27
DynamicsModelTpl(xyz::polymorphic< Manifold > space, const int nu)
Constructor for dynamics.
Base class for manifolds, to use in cost funcs, solvers...
Base struct for function data.
const int nu
Control dimension.
const int ndx1
Current state dimension.
const int nr
Function codimension.
StageFunctionTpl(const int ndx, const int nu, const int nr)
internal::finite_difference_impl< Scalar, DynamicsModelTpl > Impl
DynamicsFiniteDifferenceHelper(xyz::polymorphic< Manifold > space, xyz::polymorphic< DynamicsModel > func, const Scalar fd_eps)
void evaluate(const ConstVectorRef &x, const ConstVectorRef &u, const ConstVectorRef &xn, BaseData &data) const
void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u, const ConstVectorRef &xn, BaseData &data) const
Approximate the derivatives of a given function using finite differences, to downcast the function to...
internal::finite_difference_impl< Scalar, StageFunctionTpl > Impl
void evaluate(const ConstVectorRef &x, const ConstVectorRef &u, BaseData &data) const
Evaluate the function.
void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u, BaseData &data) const
Compute Jacobians of this function.
FiniteDifferenceHelper(xyz::polymorphic< Manifold > space, xyz::polymorphic< StageFunction > func, const Scalar fd_eps)
shared_ptr< BaseData > createData() const
Instantiate a Data object.