aligator 0.18.0
A versatile and efficient C++ library for real-time constrained trajectory optimization.
Loading...
Searching...
No Matches
finite-difference.hpp
Go to the documentation of this file.
1
3#pragma once
4
8
9namespace aligator {
10namespace autodiff {
11
12namespace internal {
13
14template <typename _Scalar, template <typename> class _BaseTpl>
15struct finite_diff_traits;
16
17template <typename Scalar> struct finite_diff_traits<Scalar, StageFunctionTpl> {
19 struct Data : StageFunctionDataTpl<Scalar> {
20 using SFD = StageFunctionDataTpl<Scalar>;
21 using SFD::ndx1;
22 using SFD::nu;
23 shared_ptr<SFD> data_0;
24 shared_ptr<SFD> data_1;
25 VectorXs dx, du;
26 VectorXs xp, up;
27
28 template <typename U>
29 Data(U const &model)
30 : SFD(*model.func_)
31 , data_0(model.func_->createData())
32 , data_1(model.func_->createData())
33 , dx(ndx1)
34 , du(nu)
35 , xp(model.nx1)
36 , up(model.nu) {
37 dx.setZero();
38 du.setZero();
39 }
40 };
41
42 struct Args {
43 ConstVectorRef x;
44 ConstVectorRef u;
45 };
46};
47
48template <typename Scalar>
49struct finite_diff_traits<Scalar, ExplicitDynamicsModelTpl> {
51 struct Data : ExplicitDynamicsDataTpl<Scalar> {
52 using EDD = ExplicitDynamicsDataTpl<Scalar>;
53 using EDD::ndx1;
54 using EDD::ndx2;
55 using EDD::nu;
56 shared_ptr<EDD> data_0;
57 shared_ptr<EDD> data_1;
58 VectorXs dx, du;
59 VectorXs xp, up;
60 VectorXs dxnext;
61
62 template <typename U>
63 Data(U const &model)
64 : EDD(*model.func_)
65 , data_0(model.func_->createData())
66 , data_1(model.func_->createData())
67 , dx(ndx1)
68 , du(nu)
69 , xp(model.nx1)
70 , up(model.nu)
71 , dxnext(ndx2) {
72 dx.setZero();
73 du.setZero();
74 dxnext.setZero();
75 }
76 };
77
78 struct Args {
79 ConstVectorRef x;
80 ConstVectorRef u;
81 };
82};
83
85template <typename _Scalar, template <typename> class _BaseTpl>
86struct finite_difference_impl : finite_diff_traits<_Scalar, _BaseTpl> {
87 using Scalar = _Scalar;
89 using Traits = finite_diff_traits<Scalar, _BaseTpl>;
90 using Data = typename Traits::Data;
91 using Args = typename Traits::Args;
92 using Base = _BaseTpl<Scalar>;
93 using BaseData = typename Base::Data;
94 using Manifold = ManifoldAbstractTpl<Scalar>;
95
96 static_assert(std::is_base_of_v<BaseData, Data>);
97
98 xyz::polymorphic<Manifold> space_;
99 xyz::polymorphic<Base> func_;
100 Scalar fd_eps;
101 int nx1, nu, nx2;
102
103 static constexpr bool IsStage =
104 std::is_same_v<Base, StageFunctionTpl<Scalar>>;
105 static constexpr bool IsExplicitDynamics =
106 std::is_same_v<Base, ExplicitDynamicsModelTpl<Scalar>>;
107
108 static_assert(IsStage || IsExplicitDynamics,
109 "Unsupported finite_difference_impl base.");
110
111 template <
112 typename U = Base,
113 std::enable_if_t<std::is_same_v<U, StageFunctionTpl<Scalar>>, int> = 0>
114 finite_difference_impl(const xyz::polymorphic<Manifold> &space,
115 xyz::polymorphic<U> func, const Scalar fd_eps)
116 : space_(space)
117 , func_(std::move(func))
118 , fd_eps(fd_eps)
119 , nx1(space->nx())
120 , nx2(space->nx()) {}
121
122 template <typename U = Base,
123 std::enable_if_t<
124 std::is_same_v<U, ExplicitDynamicsModelTpl<Scalar>>, int> = 0>
125 finite_difference_impl(const xyz::polymorphic<Manifold> &space,
126 const xyz::polymorphic<U> &func, const Scalar fd_eps)
127 : space_(space)
128 , func_(func)
129 , fd_eps(fd_eps)
130 , nx1(space->nx())
131 , nu(func->nu)
132 , nx2(func->space_next().nx()) {}
133
136 void evaluateImpl(const Args &args, BaseData &data) const {
137 Data &d = static_cast<Data &>(data);
138 assert(d.data_0);
139 assert(d.data_1);
140 if constexpr (IsExplicitDynamics) {
141 func_->forward(args.x, args.u, *d.data_0);
142 d.xnext_ = d.data_0->xnext_;
143 } else {
144 func_->evaluate(args.x, args.u, *d.data_0);
145 d.value_ = d.data_0->value_;
146 }
147 }
148
149 void computeJacobiansImpl(const Args &args, BaseData &data) const {
150 Data &d = static_cast<Data &>(data);
151 assert(d.data_0);
152 assert(d.data_1);
153
154 auto output_ref = [](auto &data_ref) -> VectorXs & {
155 if constexpr (IsExplicitDynamics) {
156 return data_ref.xnext_;
157 } else {
158 return data_ref.value_;
159 }
160 };
161
162 VectorXs &v0 = output_ref(*d.data_0);
163 VectorXs &vp = output_ref(*d.data_1);
164
165 const int ndx1 = [&]() {
166 if constexpr (IsExplicitDynamics) {
167 return func_->ndx1();
168 } else {
169 return func_->ndx1;
170 }
171 }();
172
173 for (int i = 0; i < ndx1; i++) {
174 d.dx[i] = fd_eps;
175 space_->integrate(args.x, d.dx, d.xp);
176 if constexpr (IsExplicitDynamics) {
177 func_->forward(d.xp, args.u, *d.data_1);
178 func_->space_next().difference(v0, vp, d.dxnext);
179 data.Jx().col(i) = d.dxnext / fd_eps;
180 } else {
181 func_->evaluate(d.xp, args.u, *d.data_1);
182 data.Jx_.col(i) = (vp - v0) / fd_eps;
183 }
184 d.dx[i] = 0.;
185 }
186
187 for (int i = 0; i < func_->nu; i++) {
188 d.du[i] = fd_eps;
189 d.up = args.u + d.du;
190 if constexpr (IsExplicitDynamics) {
191 func_->forward(args.x, d.up, *d.data_1);
192 func_->space_next().difference(v0, vp, d.dxnext);
193 data.Ju().col(i) = d.dxnext / fd_eps;
194 } else {
195 func_->evaluate(args.x, d.up, *d.data_1);
196 data.Ju_.col(i) = (vp - v0) / fd_eps;
197 }
198 d.du[i] = 0.;
199 }
200 }
201
202 void computeVectorHessianProductsImpl(const ConstVectorRef &,
203 const ConstVectorRef &,
204 const ConstVectorRef &,
205 const ConstVectorRef &,
206 BaseData &) const {}
207
208 shared_ptr<BaseData> createDataImpl() const {
209 return std::make_shared<Data>(*this);
210 }
211};
212
213} // namespace internal
214
215template <typename _Scalar> struct FiniteDifferenceHelper;
216
221template <typename _Scalar>
223 using Scalar = _Scalar;
224 using Impl = internal::finite_difference_impl<Scalar, StageFunctionTpl>;
225
228 using Data = typename Impl::Data;
230
232
233 FiniteDifferenceHelper(xyz::polymorphic<Manifold> space,
234 xyz::polymorphic<StageFunction> func,
235 const Scalar fd_eps)
236 : StageFunction(func->ndx1, func->nu, func->nr)
237 , impl(space, func, fd_eps) {}
238
239 void evaluate(const ConstVectorRef &x, const ConstVectorRef &u,
240 BaseData &data) const {
241 impl.evaluateImpl({x, u}, data);
242 }
243
244 void computeJacobians(const ConstVectorRef &x, const ConstVectorRef &u,
245 BaseData &data) const {
246 impl.computeJacobiansImpl({x, u}, data);
247 }
248
249 shared_ptr<BaseData> createData() const { return impl.createDataImpl(); }
250
251private:
252 Impl impl;
253};
254
255template <typename _Scalar>
257 using Scalar = _Scalar;
258
261 using Impl =
262 internal::finite_difference_impl<Scalar, ExplicitDynamicsModelTpl>;
263 using Data = typename Impl::Data;
265
267
268 DynamicsFiniteDifferenceHelper(xyz::polymorphic<Manifold> space,
269 xyz::polymorphic<DynamicsModel> func,
270 const Scalar fd_eps)
271 : DynamicsModel(space, func->nu)
272 , impl(std::move(space), std::move(func), fd_eps) {}
273
274 void forward(const ConstVectorRef &x, const ConstVectorRef &u,
275 BaseData &data) const {
276 impl.evaluateImpl({x, u}, data);
277 }
278
279 void dForward(const ConstVectorRef &x, const ConstVectorRef &u,
280 BaseData &data) const {
281 impl.computeJacobiansImpl({x, u}, data);
282 }
283
284 shared_ptr<BaseData> createData() const { return impl.createDataImpl(); }
285
286private:
287 Impl impl;
288};
289
290#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
291extern template struct FiniteDifferenceHelper<context::Scalar>;
292extern template struct DynamicsFiniteDifferenceHelper<context::Scalar>;
293#endif
294
295} // namespace autodiff
296} // 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.
Specific data struct for explicit dynamics ExplicitDynamicsModelTpl.
ExplicitDynamicsModelTpl(const polymorphic< Manifold > &space, const int nu)
Constructor requires providing the next state's manifold.
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)
void forward(const ConstVectorRef &x, const ConstVectorRef &u, BaseData &data) const
Evaluate the forward discrete dynamics.
DynamicsFiniteDifferenceHelper(xyz::polymorphic< Manifold > space, xyz::polymorphic< DynamicsModel > func, const Scalar fd_eps)
void dForward(const ConstVectorRef &x, const ConstVectorRef &u, BaseData &data) const
Compute the Jacobians of the forward dynamics.
internal::finite_difference_impl< Scalar, ExplicitDynamicsModelTpl > Impl
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.