8#include <boost/mpl/bool.hpp>
15template <
typename _Scalar,
template <
typename>
class _BaseTpl>
16struct finite_diff_traits;
18template <
typename Scalar>
struct finite_diff_traits<
Scalar, StageFunctionTpl> {
20 struct Data : StageFunctionDataTpl<Scalar> {
21 using SFD = StageFunctionDataTpl<Scalar>;
24 shared_ptr<SFD> data_0;
25 shared_ptr<SFD> data_1;
32 , data_0(model.func_->createData())
33 , data_1(model.func_->createData())
49template <
typename Scalar>
struct finite_diff_traits<
Scalar, DynamicsModelTpl> {
51 struct Data : DynamicsDataTpl<Scalar> {
52 using DD = DynamicsDataTpl<Scalar>;
56 shared_ptr<DD> data_0;
57 shared_ptr<DD> data_1;
64 , data_0(model.func_->createData())
65 , data_1(model.func_->createData())
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>;
97 static_assert(std::is_base_of_v<BaseData, Data>);
99 xyz::polymorphic<Manifold> space_;
100 xyz::polymorphic<Base> func_;
104 static constexpr bool IsDynamics =
105 std::is_same_v<Base, DynamicsModelTpl<Scalar>>;
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)
115 , nx2(space->nx()) {}
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_ = {})
127 , nx2(space->nx()) {}
131 void evaluateImpl(
const Args &args, BaseData &data)
const {
132 Data &d =
static_cast<Data &
>(
data);
135 if constexpr (IsDynamics) {
136 func_->evaluate(args.x, args.u, args.y, *d.data_0);
138 func_->evaluate(args.x, args.u, *d.data_0);
140 d.value_ = d.data_0->value_;
143 void computeJacobiansImpl(
const Args &args, BaseData &data)
const {
144 Data &d =
static_cast<Data &
>(
data);
148 VectorXs &v0 = d.data_0->value_;
149 VectorXs &vp = d.data_1->value_;
151 for (
int i = 0; i < func_->ndx1; i++) {
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);
157 func_->evaluate(d.xp, args.u, *d.data_1);
159 data.Jx_.col(i) = (vp - v0) / fd_eps;
163 if constexpr (IsDynamics) {
164 for (
int i = 0; i < func_->ndx2; i++) {
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;
173 for (
int i = 0; i < func_->nu; i++) {
175 d.up = args.u + d.du;
176 if constexpr (IsDynamics) {
177 func_->evaluate(args.x, d.up, args.y, *d.data_1);
179 func_->evaluate(args.x, d.up, *d.data_1);
181 data.Ju_.col(i) = (vp - v0) / fd_eps;
186 void computeVectorHessianProductsImpl(
const ConstVectorRef &,
187 const ConstVectorRef &,
188 const ConstVectorRef &,
189 const ConstVectorRef &,
192 shared_ptr<BaseData> createDataImpl()
const {
193 return std::make_shared<Data>(*
this);
205template <
typename _Scalar>
208 using Impl = internal::finite_difference_impl<Scalar, StageFunctionTpl>;
212 using Data =
typename Impl::Data;
221 , impl(space, func, fd_eps) {}
223 void evaluate(
const ConstVectorRef &x,
const ConstVectorRef &u,
225 impl.evaluateImpl({x, u}, data);
230 impl.computeJacobiansImpl({x, u}, data);
233 shared_ptr<BaseData>
createData()
const {
return impl.createDataImpl(); }
239template <
typename _Scalar>
245 using Impl = internal::finite_difference_impl<Scalar, DynamicsModelTpl>;
246 using Data =
typename Impl::Data;
255 , impl(
space, func, fd_eps) {}
257 void evaluate(
const ConstVectorRef &x,
const ConstVectorRef &u,
258 const ConstVectorRef &xn,
BaseData &data)
const {
259 impl.evaluateImpl({x, u, xn}, data);
263 const ConstVectorRef &xn,
BaseData &data)
const {
264 impl.computeJacobiansImpl({x, u, xn}, data);
267 shared_ptr<BaseData>
createData()
const {
return impl.createDataImpl(); }
273#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
274extern template struct FiniteDifferenceHelper<context::Scalar>;
275extern template struct DynamicsFiniteDifferenceHelper<context::Scalar>;
Base definitions for ternary functions.
#define ALIGATOR_DYNAMIC_TYPEDEFS(Scalar)
::aligator::context::Scalar Scalar
constexpr auto data(C &c) noexcept(noexcept(c.data())) -> decltype(c.data())
const Manifold & space() const
State space for the input.
const int nu
Control dimension.
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)
DynamicsDataTpl< Scalar > BaseData
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
ManifoldAbstractTpl< Scalar > Manifold
DynamicsModelTpl< Scalar > DynamicsModel
ALIGATOR_DYNAMIC_TYPEDEFS(_Scalar)
shared_ptr< BaseData > createData() 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...
ManifoldAbstractTpl< Scalar > Manifold
internal::finite_difference_impl< Scalar, StageFunctionTpl > Impl
StageFunctionDataTpl< Scalar > BaseData
StageFunctionTpl< Scalar > StageFunction
ALIGATOR_DYNAMIC_TYPEDEFS(_Scalar)
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.