Crocoddyl
 
Loading...
Searching...
No Matches
action-base.hpp
1
3// BSD 3-Clause License
4//
5// Copyright (C) 2019-2024, LAAS-CNRS, INRIA, University of Edinburgh,
6// Heriot-Watt University
7// Copyright note valid unless otherwise stated in individual files.
8// All rights reserved.
10
11#ifndef CROCODDYL_CORE_CODEGEN_ACTION_BASE_HPP_
12#define CROCODDYL_CORE_CODEGEN_ACTION_BASE_HPP_
13
14#include <functional>
15
16#include "crocoddyl/core/action-base.hpp"
17#include "pinocchio/codegen/cppadcg.hpp"
18
19namespace crocoddyl {
20
21template <typename Scalar>
22struct ActionDataCodeGenTpl;
23
24template <typename _Scalar>
26 public:
27 typedef _Scalar Scalar;
31 typedef typename MathBaseTpl<Scalar>::VectorXs VectorXs;
32 typedef typename MathBaseTpl<Scalar>::MatrixXs MatrixXs;
33
34 typedef CppAD::cg::CG<Scalar> CGScalar;
35 typedef CppAD::AD<CGScalar> ADScalar;
39 typedef typename MathBaseTpl<ADScalar>::VectorXs ADVectorXs;
40 typedef typename MathBaseTpl<ADScalar>::MatrixXs ADMatrixXs;
41 typedef typename MathBaseTpl<ADScalar>::Vector3s ADVector3s;
42 typedef typename MathBaseTpl<ADScalar>::Matrix3s ADMatrix3s;
43
44 typedef
45 typename PINOCCHIO_EIGEN_PLAIN_ROW_MAJOR_TYPE(ADMatrixXs) RowADMatrixXs;
46
47 typedef CppAD::ADFun<CGScalar> ADFun;
48
49 ActionModelCodeGenTpl(std::shared_ptr<ADBase> admodel,
50 std::shared_ptr<Base> model,
51 const std::string& library_name,
52 const std::size_t n_env = 0,
53 std::function<void(std::shared_ptr<ADBase>,
54 const Eigen::Ref<const ADVectorXs>&)>
55 fn_record_env = empty_record_env,
56 const std::string& function_name_calc = "calc",
57 const std::string& function_name_calcDiff = "calcDiff")
58 : Base(model->get_state(), model->get_nu()),
59 model(model),
60 ad_model(admodel),
61 ad_data(ad_model->createData()),
63 function_name_calcDiff(function_name_calcDiff),
65 n_env(n_env),
67 ad_X(ad_model->get_state()->get_nx() + ad_model->get_nu() + n_env),
68 ad_X2(ad_model->get_state()->get_nx() + ad_model->get_nu() + n_env),
69 ad_calcout(ad_model->get_state()->get_nx() + 1) {
70 const std::size_t ndx = ad_model->get_state()->get_ndx();
71 const std::size_t nu = ad_model->get_nu();
72 ad_calcDiffout.resize(2 * ndx * ndx + 2 * ndx * nu + nu * nu + ndx + nu);
73 initLib();
74 loadLib();
75 }
76
77 static void empty_record_env(std::shared_ptr<ADBase>,
78 const Eigen::Ref<const ADVectorXs>&) {}
79
80 void recordCalc() {
81 CppAD::Independent(ad_X);
82 const std::size_t nx = ad_model->get_state()->get_nx();
83 const std::size_t nu = ad_model->get_nu();
84
85 fn_record_env(ad_model, ad_X.tail(n_env));
86
87 ad_model->calc(ad_data, ad_X.head(nx), ad_X.segment(nx, nu));
88 collect_calcout();
89 // ad_calcout.template head<1>()[0] = ad_data->cost;
90 // ad_calcout.tail(ad_model->get_state()->get_nx()) = ad_data->xnext;
91 ad_calc.Dependent(ad_X, ad_calcout);
92 ad_calc.optimize("no_compare_op");
93 }
94
95 void collect_calcout() {
96 ad_calcout[0] = ad_data->cost;
97 ad_calcout.tail(ad_model->get_state()->get_nx()) = ad_data->xnext;
98 }
99
100 void collect_calcDiffout() {
101 ADVectorXs& ad_Y = ad_calcDiffout;
102
103 const std::size_t ndx = ad_model->get_state()->get_ndx();
104 const std::size_t nu = ad_model->get_nu();
105 Eigen::DenseIndex it_Y = 0;
106 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, ndx) = ad_data->Fx;
107 it_Y += ndx * ndx;
108 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, nu) = ad_data->Fu;
109 it_Y += ndx * nu;
110 Eigen::Map<ADVectorXs>(ad_Y.data() + it_Y, ndx) = ad_data->Lx;
111 it_Y += ndx;
112 Eigen::Map<ADVectorXs>(ad_Y.data() + it_Y, nu) = ad_data->Lu;
113 it_Y += nu;
114 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, ndx) = ad_data->Lxx;
115 it_Y += ndx * ndx;
116 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, nu) = ad_data->Lxu;
117 it_Y += ndx * nu;
118 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, nu, nu) = ad_data->Luu;
119 }
120
121 void recordCalcDiff() {
122 CppAD::Independent(ad_X2);
123 const std::size_t nx = ad_model->get_state()->get_nx();
124 const std::size_t nu = ad_model->get_nu();
125
126 fn_record_env(ad_model, ad_X2.tail(n_env));
127
128 ad_model->calc(ad_data, ad_X2.head(nx), ad_X2.segment(nx, nu));
129 ad_model->calcDiff(ad_data, ad_X2.head(nx), ad_X2.segment(nx, nu));
130
131 collect_calcDiffout();
132 ad_calcDiff.Dependent(ad_X2, ad_calcDiffout);
133 ad_calcDiff.optimize("no_compare_op");
134 }
135
136 void initLib() {
137 recordCalc();
138
139 // generates source code
140 calcgen_ptr = std::unique_ptr<CppAD::cg::ModelCSourceGen<Scalar> >(
141 new CppAD::cg::ModelCSourceGen<Scalar>(ad_calc, function_name_calc));
142 calcgen_ptr->setCreateForwardZero(true);
143 calcgen_ptr->setCreateJacobian(false);
144
145 // generates source code
146 recordCalcDiff();
147 calcDiffgen_ptr = std::unique_ptr<CppAD::cg::ModelCSourceGen<Scalar> >(
148 new CppAD::cg::ModelCSourceGen<Scalar>(ad_calcDiff,
149 function_name_calcDiff));
150 calcDiffgen_ptr->setCreateForwardZero(true);
151 calcDiffgen_ptr->setCreateJacobian(false);
152
153 libcgen_ptr = std::unique_ptr<CppAD::cg::ModelLibraryCSourceGen<Scalar> >(
154 new CppAD::cg::ModelLibraryCSourceGen<Scalar>(*calcgen_ptr,
155 *calcDiffgen_ptr));
156
157 dynamicLibManager_ptr =
158 std::unique_ptr<CppAD::cg::DynamicModelLibraryProcessor<Scalar> >(
159 new CppAD::cg::DynamicModelLibraryProcessor<Scalar>(*libcgen_ptr,
160 library_name));
161 }
162
163 void compileLib() {
164 CppAD::cg::GccCompiler<Scalar> compiler;
165 std::vector<std::string> compile_options = compiler.getCompileFlags();
166 compile_options[0] = "-O3";
167 compiler.setCompileFlags(compile_options);
168 dynamicLibManager_ptr->createDynamicLibrary(compiler, false);
169 }
170
171 bool existLib() const {
172 const std::string filename =
173 dynamicLibManager_ptr->getLibraryName() +
174 CppAD::cg::system::SystemInfo<>::DYNAMIC_LIB_EXTENSION;
175 std::ifstream file(filename.c_str());
176 return file.good();
177 }
178
179 void loadLib(const bool generate_if_not_exist = true) {
180 if (not existLib() && generate_if_not_exist) compileLib();
181
182 const auto it = dynamicLibManager_ptr->getOptions().find("dlOpenMode");
183 if (it == dynamicLibManager_ptr->getOptions().end()) {
184 dynamicLib_ptr.reset(new CppAD::cg::LinuxDynamicLib<Scalar>(
185 dynamicLibManager_ptr->getLibraryName() +
186 CppAD::cg::system::SystemInfo<>::DYNAMIC_LIB_EXTENSION));
187 } else {
188 int dlOpenMode = std::stoi(it->second);
189 dynamicLib_ptr.reset(new CppAD::cg::LinuxDynamicLib<Scalar>(
190 dynamicLibManager_ptr->getLibraryName() +
191 CppAD::cg::system::SystemInfo<>::DYNAMIC_LIB_EXTENSION,
192 dlOpenMode));
193 }
194
195 calcFun_ptr = dynamicLib_ptr->model(function_name_calc.c_str());
196 calcDiffFun_ptr = dynamicLib_ptr->model(function_name_calcDiff.c_str());
197 }
198
199 void set_env(const std::shared_ptr<ActionDataAbstract>& data,
200 const Eigen::Ref<const VectorXs>& env_val) const {
201 Data* d = static_cast<Data*>(data.get());
202 d->xu.tail(n_env) = env_val;
203 }
204
205 void calc(const std::shared_ptr<ActionDataAbstract>& data,
206 const Eigen::Ref<const VectorXs>& x,
207 const Eigen::Ref<const VectorXs>& u) {
208 Data* d = static_cast<Data*>(data.get());
209 const std::size_t nx = ad_model->get_state()->get_nx();
210 const std::size_t nu = ad_model->get_nu();
211
212 d->xu.head(nx) = x;
213 d->xu.segment(nx, nu) = u;
214
215 calcFun_ptr->ForwardZero(d->xu, d->calcout);
216 d->distribute_calcout();
217 }
218
219 void calcDiff(const std::shared_ptr<ActionDataAbstract>& data,
220 const Eigen::Ref<const VectorXs>& x,
221 const Eigen::Ref<const VectorXs>& u) {
222 Data* d = static_cast<Data*>(data.get());
223 const std::size_t nx = ad_model->get_state()->get_nx();
224 const std::size_t nu = ad_model->get_nu();
225
226 d->xu.head(nx) = x;
227 d->xu.segment(nx, nu) = u;
228 calcDiffFun_ptr->ForwardZero(d->xu, d->calcDiffout);
229 d->distribute_calcDiffout();
230 }
231
232 std::shared_ptr<ActionDataAbstract> createData() {
233 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
234 }
235
237 Eigen::DenseIndex getInputDimension() const { return ad_X.size(); }
238
239 protected:
242 using Base::nr_;
243 using Base::nu_;
244 using Base::state_;
245 using Base::u_lb_;
246 using Base::u_ub_;
247
248 std::shared_ptr<Base> model;
249 std::shared_ptr<ADBase> ad_model;
250 std::shared_ptr<ADActionDataAbstract> ad_data;
251
253 const std::string function_name_calc, function_name_calcDiff;
254
256 const std::string library_name;
257
259 const std::size_t n_env;
260
263 std::function<void(std::shared_ptr<ADBase>,
264 const Eigen::Ref<const ADVectorXs>&)>
266
270
271 ADVectorXs ad_X, ad_X2;
272
273 ADVectorXs ad_calcout;
274 ADVectorXs ad_calcDiffout;
275
276 ADFun ad_calc, ad_calcDiff;
277
278 std::unique_ptr<CppAD::cg::ModelCSourceGen<Scalar> > calcgen_ptr,
279 calcDiffgen_ptr;
280 std::unique_ptr<CppAD::cg::ModelLibraryCSourceGen<Scalar> > libcgen_ptr;
281 std::unique_ptr<CppAD::cg::DynamicModelLibraryProcessor<Scalar> >
282 dynamicLibManager_ptr;
283 std::unique_ptr<CppAD::cg::DynamicLib<Scalar> > dynamicLib_ptr;
284 std::unique_ptr<CppAD::cg::GenericModel<Scalar> > calcFun_ptr,
285 calcDiffFun_ptr;
286
287}; // struct CodeGenBase
288
289template <typename _Scalar>
291 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
292
293 typedef _Scalar Scalar;
296 typedef typename MathBase::VectorXs VectorXs;
297 typedef typename MathBase::MatrixXs MatrixXs;
298
299 using Base::cost;
300 using Base::Fu;
301 using Base::Fx;
302 using Base::Lu;
303 using Base::Luu;
304 using Base::Lx;
305 using Base::Lxu;
306 using Base::Lxx;
307 using Base::r;
308 using Base::xnext;
309
310 VectorXs xu, calcout;
311
312 VectorXs calcDiffout;
313
314 void distribute_calcout() {
315 cost = calcout[0];
316 xnext = calcout.tail(xnext.size());
317 }
318
319 void distribute_calcDiffout() {
320 VectorXs& Y = calcDiffout;
321 const std::size_t ndx = Fx.rows();
322 const std::size_t nu = Fu.cols();
323
324 Eigen::DenseIndex it_Y = 0;
325 Fx = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, ndx);
326 it_Y += ndx * ndx;
327 Fu = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, nu);
328 it_Y += ndx * nu;
329 Lx = Eigen::Map<VectorXs>(Y.data() + it_Y, ndx);
330 it_Y += ndx;
331 Lu = Eigen::Map<VectorXs>(Y.data() + it_Y, nu);
332 it_Y += nu;
333 Lxx = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, ndx);
334 it_Y += ndx * ndx;
335 Lxu = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, nu);
336 it_Y += ndx * nu;
337 Luu = Eigen::Map<MatrixXs>(Y.data() + it_Y, nu, nu);
338 }
339
340 template <template <typename Scalar> class Model>
341 explicit ActionDataCodeGenTpl(Model<Scalar>* const model)
342 : Base(model), calcout(model->get_state()->get_nx() + 1) {
344 static_cast<ActionModelCodeGenTpl<Scalar>*>(model);
345 xu.resize(m->getInputDimension());
346 xu.setZero();
347 calcout.setZero();
348 const std::size_t ndx = model->get_state()->get_ndx();
349 const std::size_t nu = model->get_nu();
350 calcDiffout.resize(2 * ndx * ndx + 2 * ndx * nu + nu * nu + ndx + nu);
351 calcDiffout.setZero();
352 }
353};
354
355} // namespace crocoddyl
356
357#endif // ifndef CROCODDYL_CORE_CODEGEN_ACTION_BASE_HPP_
Abstract class for action model.
std::shared_ptr< StateAbstract > state_
Model of the state.
VectorXs u_lb_
Lower control limits.
VectorXs u_ub_
Upper control limits.
std::size_t nu_
Control dimension.
const std::shared_ptr< StateAbstract > & get_state() const
Return the state.
std::size_t nr_
Dimension of the cost residual.
std::function< void(std::shared_ptr< ADBase >, const Eigen::Ref< const ADVectorXs > &)> fn_record_env
A function that updates the environment variables before starting record.
Eigen::DenseIndex getInputDimension() const
Dimension of the input vector.
std::shared_ptr< ActionDataAbstract > createData()
Create the action data.
const std::string function_name_calc
Name of the function.
std::shared_ptr< Base > model
< Upper control limits
const std::size_t n_env
Size of the environment variables.
bool build_forward
Options to generate or not the source code for the evaluation function.
const std::string library_name
Name of the library.
VectorXs xnext
evolution state
MatrixXs Fx
Jacobian of the dynamics w.r.t. the state .
MatrixXs Fu
Jacobian of the dynamics w.r.t. the control .
MatrixXs Luu
Hessian of the cost w.r.t. the control .
VectorXs Lx
Jacobian of the cost w.r.t. the state .
MatrixXs Lxx
Hessian of the cost w.r.t. the state .
VectorXs Lu
Jacobian of the cost w.r.t. the control .
VectorXs xnext
evolution state
MatrixXs Fx
Jacobian of the dynamics w.r.t. the state .
MatrixXs Fu
Jacobian of the dynamics w.r.t. the control .
MatrixXs Luu
Hessian of the cost w.r.t. the control .
VectorXs Lx
Jacobian of the cost w.r.t. the state .
MatrixXs Lxx
Hessian of the cost w.r.t. the state .
VectorXs Lu
Jacobian of the cost w.r.t. the control .