14template <
typename _Scalar,
template <
typename>
class _BaseTpl>
15struct finite_diff_traits;
17template <
typename Scalar>
struct finite_diff_traits<
Scalar, StageFunctionTpl> {
19 struct Data : StageFunctionDataTpl<Scalar> {
20 using SFD = StageFunctionDataTpl<Scalar>;
23 shared_ptr<SFD> data_0;
24 shared_ptr<SFD> data_1;
31 , data_0(model.func_->createData())
32 , data_1(model.func_->createData())
48template <
typename Scalar>
49struct finite_diff_traits<
Scalar, ExplicitDynamicsModelTpl> {
51 struct Data : ExplicitDynamicsDataTpl<Scalar> {
52 using EDD = ExplicitDynamicsDataTpl<Scalar>;
56 shared_ptr<EDD> data_0;
57 shared_ptr<EDD> data_1;
65 , data_0(model.func_->createData())
66 , data_1(model.func_->createData())
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>;
96 static_assert(std::is_base_of_v<BaseData, Data>);
98 xyz::polymorphic<Manifold> space_;
99 xyz::polymorphic<Base> func_;
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>>;
108 static_assert(IsStage || IsExplicitDynamics,
109 "Unsupported finite_difference_impl 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)
117 , func_(std::move(func))
120 , nx2(space->nx()) {}
122 template <
typename U = Base,
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)
132 , nx2(func->space_next().nx()) {}
136 void evaluateImpl(
const Args &args, BaseData &data)
const {
137 Data &d =
static_cast<Data &
>(data);
140 if constexpr (IsExplicitDynamics) {
141 func_->forward(args.x, args.u, *d.data_0);
142 d.xnext_ = d.data_0->xnext_;
144 func_->evaluate(args.x, args.u, *d.data_0);
145 d.value_ = d.data_0->value_;
149 void computeJacobiansImpl(
const Args &args, BaseData &data)
const {
150 Data &d =
static_cast<Data &
>(data);
154 auto output_ref = [](
auto &data_ref) -> VectorXs & {
155 if constexpr (IsExplicitDynamics) {
156 return data_ref.xnext_;
158 return data_ref.value_;
162 VectorXs &v0 = output_ref(*d.data_0);
163 VectorXs &vp = output_ref(*d.data_1);
165 const int ndx1 = [&]() {
166 if constexpr (IsExplicitDynamics) {
167 return func_->ndx1();
173 for (
int i = 0; i < ndx1; i++) {
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;
181 func_->evaluate(d.xp, args.u, *d.data_1);
182 data.Jx_.col(i) = (vp - v0) / fd_eps;
187 for (
int i = 0; i < func_->nu; i++) {
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;
195 func_->evaluate(args.x, d.up, *d.data_1);
196 data.Ju_.col(i) = (vp - v0) / fd_eps;
202 void computeVectorHessianProductsImpl(
const ConstVectorRef &,
203 const ConstVectorRef &,
204 const ConstVectorRef &,
205 const ConstVectorRef &,
208 shared_ptr<BaseData> createDataImpl()
const {
209 return std::make_shared<Data>(*
this);
221template <
typename _Scalar>
224 using Impl = internal::finite_difference_impl<Scalar, StageFunctionTpl>;
228 using Data =
typename Impl::Data;
234 xyz::polymorphic<StageFunction> func,
237 , impl(space, func, fd_eps) {}
239 void evaluate(
const ConstVectorRef &x,
const ConstVectorRef &u,
241 impl.evaluateImpl({x, u}, data);
246 impl.computeJacobiansImpl({x, u}, data);
249 shared_ptr<BaseData>
createData()
const {
return impl.createDataImpl(); }
255template <
typename _Scalar>
262 internal::finite_difference_impl<Scalar, ExplicitDynamicsModelTpl>;
263 using Data =
typename Impl::Data;
269 xyz::polymorphic<DynamicsModel> func,
272 , impl(std::move(
space), std::move(func), fd_eps) {}
274 void forward(
const ConstVectorRef &x,
const ConstVectorRef &u,
276 impl.evaluateImpl({x, u}, data);
279 void dForward(
const ConstVectorRef &x,
const ConstVectorRef &u,
281 impl.computeJacobiansImpl({x, u}, data);
284 shared_ptr<BaseData>
createData()
const {
return impl.createDataImpl(); }
290#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
291extern template struct FiniteDifferenceHelper<context::Scalar>;
292extern template struct DynamicsFiniteDifferenceHelper<context::Scalar>;
Base definitions for ternary functions.
#define ALIGATOR_DYNAMIC_TYPEDEFS(Scalar)
::aligator::context::Scalar Scalar
Specific data struct for explicit dynamics ExplicitDynamicsModelTpl.
ExplicitDynamicsModelTpl(const polymorphic< Manifold > &space, const int nu)
Constructor requires providing the next state's manifold.
const Manifold & space() const
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)
ExplicitDynamicsModelTpl< Scalar > DynamicsModel
ExplicitDynamicsDataTpl< Scalar > BaseData
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)
ManifoldAbstractTpl< Scalar > Manifold
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
ALIGATOR_DYNAMIC_TYPEDEFS(_Scalar)
shared_ptr< BaseData > createData() 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.