11 #ifndef CROCODDYL_CORE_CODEGEN_ACTION_BASE_HPP_
12 #define CROCODDYL_CORE_CODEGEN_ACTION_BASE_HPP_
16 #include "crocoddyl/core/action-base.hpp"
17 #include "pinocchio/codegen/cppadcg.hpp"
21 template <
typename Scalar>
22 struct ActionDataCodeGenTpl;
24 template <
typename _Scalar>
27 typedef _Scalar Scalar;
34 typedef CppAD::cg::CG<Scalar> CGScalar;
35 typedef CppAD::AD<CGScalar> ADScalar;
45 typename PINOCCHIO_EIGEN_PLAIN_ROW_MAJOR_TYPE(ADMatrixXs) RowADMatrixXs;
47 typedef CppAD::ADFun<CGScalar> ADFun;
50 boost::shared_ptr<Base>
model,
52 const std::size_t
n_env = 0,
53 std::function<
void(boost::shared_ptr<ADBase>,
54 const Eigen::Ref<const ADVectorXs>&)>
57 const std::string& function_name_calcDiff =
"calcDiff")
61 ad_data(ad_model->createData()),
63 function_name_calcDiff(function_name_calcDiff),
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);
77 static void empty_record_env(boost::shared_ptr<ADBase>,
78 const Eigen::Ref<const ADVectorXs>&) {}
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();
87 ad_model->calc(ad_data, ad_X.head(nx), ad_X.segment(nx, nu));
91 ad_calc.Dependent(ad_X, ad_calcout);
92 ad_calc.optimize(
"no_compare_op");
95 void collect_calcout() {
96 ad_calcout[0] = ad_data->cost;
97 ad_calcout.tail(ad_model->get_state()->get_nx()) = ad_data->xnext;
100 void collect_calcDiffout() {
101 ADVectorXs& ad_Y = ad_calcDiffout;
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;
108 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, nu) = ad_data->Fu;
110 Eigen::Map<ADVectorXs>(ad_Y.data() + it_Y, ndx) = ad_data->Lx;
112 Eigen::Map<ADVectorXs>(ad_Y.data() + it_Y, nu) = ad_data->Lu;
114 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, ndx) = ad_data->Lxx;
116 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, ndx, nu) = ad_data->Lxu;
118 Eigen::Map<ADMatrixXs>(ad_Y.data() + it_Y, nu, nu) = ad_data->Luu;
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();
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));
131 collect_calcDiffout();
132 ad_calcDiff.Dependent(ad_X2, ad_calcDiffout);
133 ad_calcDiff.optimize(
"no_compare_op");
140 calcgen_ptr = std::unique_ptr<CppAD::cg::ModelCSourceGen<Scalar> >(
142 calcgen_ptr->setCreateForwardZero(
true);
143 calcgen_ptr->setCreateJacobian(
false);
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);
153 libcgen_ptr = std::unique_ptr<CppAD::cg::ModelLibraryCSourceGen<Scalar> >(
154 new CppAD::cg::ModelLibraryCSourceGen<Scalar>(*calcgen_ptr,
157 dynamicLibManager_ptr =
158 std::unique_ptr<CppAD::cg::DynamicModelLibraryProcessor<Scalar> >(
159 new CppAD::cg::DynamicModelLibraryProcessor<Scalar>(*libcgen_ptr,
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);
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());
179 void loadLib(
const bool generate_if_not_exist =
true) {
180 if (not existLib() && generate_if_not_exist) compileLib();
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));
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,
196 calcDiffFun_ptr = dynamicLib_ptr->model(function_name_calcDiff.c_str());
199 void set_env(
const boost::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;
205 void calc(
const boost::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();
213 d->xu.segment(nx, nu) = u;
215 calcFun_ptr->ForwardZero(d->xu, d->calcout);
216 d->distribute_calcout();
219 void calcDiff(
const boost::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();
227 d->xu.segment(nx, nu) = u;
228 calcDiffFun_ptr->ForwardZero(d->xu, d->calcDiffout);
229 d->distribute_calcDiffout();
233 return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(),
this);
249 boost::shared_ptr<ADBase> ad_model;
250 boost::shared_ptr<ADActionDataAbstract> ad_data;
263 std::function<void(boost::shared_ptr<ADBase>,
264 const Eigen::Ref<const ADVectorXs>&)>
271 ADVectorXs ad_X, ad_X2;
273 ADVectorXs ad_calcout;
274 ADVectorXs ad_calcDiffout;
276 ADFun ad_calc, ad_calcDiff;
278 std::unique_ptr<CppAD::cg::ModelCSourceGen<Scalar> > calcgen_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,
289 template <
typename _Scalar>
291 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
293 typedef _Scalar Scalar;
296 typedef typename MathBase::VectorXs VectorXs;
297 typedef typename MathBase::MatrixXs MatrixXs;
310 VectorXs xu, calcout;
312 VectorXs calcDiffout;
314 void distribute_calcout() {
319 void distribute_calcDiffout() {
320 VectorXs& Y = calcDiffout;
321 const std::size_t ndx =
Fx.rows();
322 const std::size_t nu =
Fu.cols();
324 Eigen::DenseIndex it_Y = 0;
325 Fx = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, ndx);
327 Fu = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, nu);
329 Lx = Eigen::Map<VectorXs>(Y.data() + it_Y, ndx);
331 Lu = Eigen::Map<VectorXs>(Y.data() + it_Y, nu);
333 Lxx = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, ndx);
335 Lxu = Eigen::Map<MatrixXs>(Y.data() + it_Y, ndx, nu);
337 Luu = Eigen::Map<MatrixXs>(Y.data() + it_Y, nu, nu);
340 template <
template <
typename Scalar>
class Model>
342 :
Base(model), calcout(model->get_state()->get_nx() + 1) {
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();
Abstract class for action model.
const boost::shared_ptr< StateAbstract > & get_state() const
Return the state.
VectorXs u_lb_
Lower control limits.
VectorXs u_ub_
Upper control limits.
boost::shared_ptr< StateAbstract > state_
Model of the state.
std::size_t nu_
Control dimension.
std::size_t nr_
Dimension of the cost residual.
std::function< void(boost::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.
boost::shared_ptr< ActionDataAbstract > createData()
Create the action data.
const std::string function_name_calc
Name of the function.
boost::shared_ptr< Base > model
< Upper control limits
const std::size_t n_env
Size of the environment variables.
void calc(const boost::shared_ptr< ActionDataAbstract > &data, const Eigen::Ref< const VectorXs > &x, const Eigen::Ref< const VectorXs > &u)
Compute the next state and cost value.
bool build_forward
Options to generate or not the source code for the evaluation function.
void calcDiff(const boost::shared_ptr< ActionDataAbstract > &data, const Eigen::Ref< const VectorXs > &x, const Eigen::Ref< const VectorXs > &u)
Compute the derivatives of the dynamics and cost functions.
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 .