| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////// | ||
| 2 | // BSD 3-Clause License | ||
| 3 | // | ||
| 4 | // Copyright (C) 2022-2023, IRI: CSIC-UPC, Heriot-Watt University | ||
| 5 | // Copyright note valid unless otherwise stated in individual files. | ||
| 6 | // All rights reserved. | ||
| 7 | /////////////////////////////////////////////////////////////////////////////// | ||
| 8 | |||
| 9 | #include "crocoddyl/core/solvers/ipopt/ipopt-iface.hpp" | ||
| 10 | |||
| 11 | #include <cmath> | ||
| 12 | |||
| 13 | namespace crocoddyl { | ||
| 14 | |||
| 15 | ✗ | IpoptInterface::IpoptInterface(const std::shared_ptr<ShootingProblem>& problem) | |
| 16 | ✗ | : problem_(problem) { | |
| 17 | ✗ | const std::size_t T = problem_->get_T(); | |
| 18 | ✗ | xs_.resize(T + 1); | |
| 19 | ✗ | us_.resize(T); | |
| 20 | ✗ | datas_.resize(T + 1); | |
| 21 | ✗ | ixu_.resize(T + 1); | |
| 22 | |||
| 23 | ✗ | nconst_ = 0; | |
| 24 | ✗ | nvar_ = 0; | |
| 25 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 26 | ✗ | problem_->get_runningModels(); | |
| 27 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 28 | ✗ | const std::size_t nxi = models[t]->get_state()->get_nx(); | |
| 29 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 30 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 31 | |||
| 32 | ✗ | xs_[t] = models[t]->get_state()->zero(); | |
| 33 | ✗ | us_[t] = Eigen::VectorXd::Zero(nui); | |
| 34 | ✗ | datas_[t] = createData(nxi, ndxi, nui); | |
| 35 | ✗ | ixu_[t] = nvar_; | |
| 36 | ✗ | nconst_ += ndxi; // T*ndx eq. constraints for dynamics | |
| 37 | ✗ | nvar_ += ndxi + nui; // Multiple shooting, states and controls | |
| 38 | } | ||
| 39 | ✗ | ixu_[T] = nvar_; | |
| 40 | |||
| 41 | // Initial condition | ||
| 42 | ✗ | nconst_ += models[0]->get_state()->get_ndx(); | |
| 43 | |||
| 44 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 45 | ✗ | problem_->get_terminalModel(); | |
| 46 | ✗ | const std::size_t nxi = model->get_state()->get_nx(); | |
| 47 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 48 | ✗ | nvar_ += ndxi; // final node | |
| 49 | ✗ | xs_[T] = model->get_state()->zero(); | |
| 50 | ✗ | datas_[T] = createData(nxi, ndxi, 0); | |
| 51 | ✗ | } | |
| 52 | |||
| 53 | ✗ | void IpoptInterface::resizeData() { | |
| 54 | ✗ | const std::size_t T = problem_->get_T(); | |
| 55 | ✗ | nvar_ = 0; | |
| 56 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 57 | ✗ | problem_->get_runningModels(); | |
| 58 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 59 | ✗ | const std::size_t nxi = models[t]->get_state()->get_nx(); | |
| 60 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 61 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 62 | |||
| 63 | ✗ | xs_[t].conservativeResize(nxi); | |
| 64 | ✗ | us_[t].conservativeResize(nui); | |
| 65 | ✗ | datas_[t]->resize(nxi, ndxi, nui); | |
| 66 | ✗ | ixu_[t] = nvar_; | |
| 67 | ✗ | nconst_ += ndxi; // T*ndx eq. constraints for dynamics | |
| 68 | ✗ | nvar_ += ndxi + nui; // Multiple shooting, states and controls | |
| 69 | } | ||
| 70 | ✗ | ixu_[T] = nvar_; | |
| 71 | |||
| 72 | // Initial condition | ||
| 73 | ✗ | nconst_ += models[0]->get_state()->get_ndx(); | |
| 74 | |||
| 75 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 76 | ✗ | problem_->get_terminalModel(); | |
| 77 | ✗ | const std::size_t nxi = model->get_state()->get_nx(); | |
| 78 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 79 | ✗ | nvar_ += ndxi; // final node | |
| 80 | ✗ | xs_[T].conservativeResize(nxi); | |
| 81 | ✗ | datas_[T]->resize(nxi, ndxi, 0); | |
| 82 | ✗ | } | |
| 83 | |||
| 84 | ✗ | IpoptInterface::~IpoptInterface() {} | |
| 85 | |||
| 86 | ✗ | bool IpoptInterface::get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, | |
| 87 | Ipopt::Index& nnz_jac_g, | ||
| 88 | Ipopt::Index& nnz_h_lag, | ||
| 89 | IndexStyleEnum& index_style) { | ||
| 90 | ✗ | n = static_cast<Ipopt::Index>(nvar_); // number of variables | |
| 91 | ✗ | m = static_cast<Ipopt::Index>(nconst_); // number of constraints | |
| 92 | |||
| 93 | ✗ | nnz_jac_g = 0; // Jacobian nonzeros for dynamic constraints | |
| 94 | ✗ | nnz_h_lag = 0; // Hessian nonzeros (only lower triangular part) | |
| 95 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 96 | ✗ | problem_->get_runningModels(); | |
| 97 | ✗ | const std::size_t T = problem_->get_T(); | |
| 98 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 99 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 100 | const std::size_t ndxi_next = | ||
| 101 | ✗ | t + 1 == T ? problem_->get_terminalModel()->get_state()->get_ndx() | |
| 102 | ✗ | : models[t + 1]->get_state()->get_ndx(); | |
| 103 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 104 | ✗ | nnz_jac_g += ndxi * (ndxi + ndxi_next + nui); | |
| 105 | |||
| 106 | // Hessian | ||
| 107 | ✗ | std::size_t nonzero = 0; | |
| 108 | ✗ | for (std::size_t i = 1; i <= (ndxi + nui); ++i) { | |
| 109 | ✗ | nonzero += i; | |
| 110 | } | ||
| 111 | ✗ | nnz_h_lag += nonzero; | |
| 112 | } | ||
| 113 | |||
| 114 | // Initial condition | ||
| 115 | ✗ | nnz_jac_g += | |
| 116 | ✗ | models[0]->get_state()->get_ndx() * models[0]->get_state()->get_ndx(); | |
| 117 | |||
| 118 | // Hessian nonzero for the terminal cost | ||
| 119 | const std::size_t ndxi = | ||
| 120 | ✗ | problem_->get_terminalModel()->get_state()->get_ndx(); | |
| 121 | ✗ | std::size_t nonzero = 0; | |
| 122 | ✗ | for (std::size_t i = 1; i <= ndxi; ++i) { | |
| 123 | ✗ | nonzero += i; | |
| 124 | } | ||
| 125 | ✗ | nnz_h_lag += nonzero; | |
| 126 | |||
| 127 | // use the C style indexing (0-based) | ||
| 128 | ✗ | index_style = Ipopt::TNLP::C_STYLE; | |
| 129 | |||
| 130 | ✗ | return true; | |
| 131 | } | ||
| 132 | |||
| 133 | #ifndef NDEBUG | ||
| 134 | ✗ | bool IpoptInterface::get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, | |
| 135 | Ipopt::Number* x_u, Ipopt::Index m, | ||
| 136 | Ipopt::Number* g_l, Ipopt::Number* g_u) { | ||
| 137 | #else | ||
| 138 | bool IpoptInterface::get_bounds_info(Ipopt::Index, Ipopt::Number* x_l, | ||
| 139 | Ipopt::Number* x_u, Ipopt::Index, | ||
| 140 | Ipopt::Number* g_l, Ipopt::Number* g_u) { | ||
| 141 | #endif | ||
| 142 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 143 | "Inconsistent number of decision variables"); | ||
| 144 | ✗ | assert_pretty(m == static_cast<Ipopt::Index>(nconst_), | |
| 145 | "Inconsistent number of constraints"); | ||
| 146 | |||
| 147 | // Adding bounds | ||
| 148 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 149 | ✗ | problem_->get_runningModels(); | |
| 150 | ✗ | for (std::size_t t = 0; t < problem_->get_T(); ++t) { | |
| 151 | // Running state bounds | ||
| 152 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 153 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 154 | |||
| 155 | ✗ | for (std::size_t j = 0; j < ndxi; ++j) { | |
| 156 | ✗ | x_l[ixu_[t] + j] = std::numeric_limits<double>::lowest(); | |
| 157 | ✗ | x_u[ixu_[t] + j] = std::numeric_limits<double>::max(); | |
| 158 | } | ||
| 159 | ✗ | for (std::size_t j = 0; j < nui; ++j) { | |
| 160 | ✗ | x_l[ixu_[t] + ndxi + j] = models[t]->get_has_control_limits() | |
| 161 | ✗ | ? models[t]->get_u_lb()(j) | |
| 162 | ✗ | : std::numeric_limits<double>::lowest(); | |
| 163 | ✗ | x_u[ixu_[t] + ndxi + j] = models[t]->get_has_control_limits() | |
| 164 | ✗ | ? models[t]->get_u_ub()(j) | |
| 165 | ✗ | : std::numeric_limits<double>::max(); | |
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | // Final state bounds | ||
| 170 | const std::size_t ndxi = | ||
| 171 | ✗ | problem_->get_terminalModel()->get_state()->get_ndx(); | |
| 172 | ✗ | for (std::size_t j = 0; j < ndxi; j++) { | |
| 173 | ✗ | x_l[ixu_.back() + j] = std::numeric_limits<double>::lowest(); | |
| 174 | ✗ | x_u[ixu_.back() + j] = std::numeric_limits<double>::max(); | |
| 175 | } | ||
| 176 | |||
| 177 | // Dynamics & Initial conditions (all equal to zero) | ||
| 178 | ✗ | for (Ipopt::Index i = 0; i < static_cast<Ipopt::Index>(nconst_); ++i) { | |
| 179 | ✗ | g_l[i] = 0; | |
| 180 | ✗ | g_u[i] = 0; | |
| 181 | } | ||
| 182 | |||
| 183 | ✗ | return true; | |
| 184 | } | ||
| 185 | |||
| 186 | #ifndef NDEBUG | ||
| 187 | ✗ | bool IpoptInterface::get_starting_point(Ipopt::Index n, bool init_x, | |
| 188 | Ipopt::Number* x, bool init_z, | ||
| 189 | Ipopt::Number* /*z_L*/, | ||
| 190 | Ipopt::Number* /*z_U*/, Ipopt::Index m, | ||
| 191 | bool init_lambda, | ||
| 192 | Ipopt::Number* /*lambda*/) { | ||
| 193 | #else | ||
| 194 | bool IpoptInterface::get_starting_point(Ipopt::Index, bool /*init_x*/, | ||
| 195 | Ipopt::Number* x, bool, Ipopt::Number*, | ||
| 196 | Ipopt::Number*, Ipopt::Index, bool, | ||
| 197 | Ipopt::Number*) { | ||
| 198 | #endif | ||
| 199 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 200 | "Inconsistent number of decision variables"); | ||
| 201 | ✗ | assert_pretty(m == static_cast<Ipopt::Index>(nconst_), | |
| 202 | "Inconsistent number of constraints"); | ||
| 203 | ✗ | assert_pretty(init_x == true, | |
| 204 | "Make sure to provide initial value for primal variables"); | ||
| 205 | ✗ | assert_pretty(init_z == false, | |
| 206 | "Cannot provide initial value for bound multipliers"); | ||
| 207 | ✗ | assert_pretty(init_lambda == false, | |
| 208 | "Cannot provide initial value for constraint multipliers"); | ||
| 209 | |||
| 210 | // initialize to the given starting point | ||
| 211 | // State variables are always at 0 since they represent increments from the | ||
| 212 | // given initial point | ||
| 213 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 214 | ✗ | problem_->get_runningModels(); | |
| 215 | ✗ | for (std::size_t t = 0; t < problem_->get_T(); ++t) { | |
| 216 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 217 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 218 | ✗ | for (std::size_t j = 0; j < ndxi; ++j) { | |
| 219 | ✗ | x[ixu_[t] + j] = 0; | |
| 220 | } | ||
| 221 | ✗ | for (std::size_t j = 0; j < nui; ++j) { | |
| 222 | ✗ | x[ixu_[t] + ndxi + j] = us_[t](j); | |
| 223 | } | ||
| 224 | } | ||
| 225 | const std::size_t ndxi = | ||
| 226 | ✗ | problem_->get_terminalModel()->get_state()->get_ndx(); | |
| 227 | ✗ | for (std::size_t j = 0; j < ndxi; j++) { | |
| 228 | ✗ | x[ixu_.back() + j] = 0; | |
| 229 | } | ||
| 230 | |||
| 231 | ✗ | return true; | |
| 232 | } | ||
| 233 | |||
| 234 | #ifndef NDEBUG | ||
| 235 | ✗ | bool IpoptInterface::eval_f(Ipopt::Index n, const Ipopt::Number* x, | |
| 236 | bool /*new_x*/, Ipopt::Number& obj_value) { | ||
| 237 | #else | ||
| 238 | bool IpoptInterface::eval_f(Ipopt::Index, const Ipopt::Number* x, bool, | ||
| 239 | Ipopt::Number& obj_value) { | ||
| 240 | #endif | ||
| 241 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 242 | "Inconsistent number of decision variables"); | ||
| 243 | |||
| 244 | // Running costs | ||
| 245 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 246 | ✗ | problem_->get_runningModels(); | |
| 247 | const std::vector<std::shared_ptr<ActionDataAbstract> >& datas = | ||
| 248 | ✗ | problem_->get_runningDatas(); | |
| 249 | ✗ | const std::size_t T = problem_->get_T(); | |
| 250 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 251 | #pragma omp parallel for num_threads(problem_->get_nthreads()) | ||
| 252 | #endif | ||
| 253 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 254 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 255 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 256 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 257 | ✗ | const std::size_t nui = model->get_nu(); | |
| 258 | |||
| 259 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 260 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 261 | ✗ | model->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 262 | ✗ | model->calc(data, datas_[t]->x, datas_[t]->u); | |
| 263 | } | ||
| 264 | |||
| 265 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 266 | #pragma omp simd reduction(+ : obj_value) | ||
| 267 | #endif | ||
| 268 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 269 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 270 | ✗ | obj_value += data->cost; | |
| 271 | } | ||
| 272 | |||
| 273 | // Terminal costs | ||
| 274 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 275 | ✗ | problem_->get_terminalModel(); | |
| 276 | const std::shared_ptr<ActionDataAbstract>& data = | ||
| 277 | ✗ | problem_->get_terminalData(); | |
| 278 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 279 | |||
| 280 | ✗ | datas_[T]->dx = Eigen::VectorXd::Map(x + ixu_.back(), ndxi); | |
| 281 | ✗ | model->get_state()->integrate(xs_[T], datas_[T]->dx, datas_[T]->x); | |
| 282 | ✗ | model->calc(data, datas_[T]->x); | |
| 283 | ✗ | obj_value += data->cost; | |
| 284 | |||
| 285 | ✗ | return true; | |
| 286 | } | ||
| 287 | |||
| 288 | #ifndef NDEBUG | ||
| 289 | ✗ | bool IpoptInterface::eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, | |
| 290 | bool /*new_x*/, Ipopt::Number* grad_f) { | ||
| 291 | #else | ||
| 292 | bool IpoptInterface::eval_grad_f(Ipopt::Index, const Ipopt::Number* x, bool, | ||
| 293 | Ipopt::Number* grad_f) { | ||
| 294 | #endif | ||
| 295 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 296 | "Inconsistent number of decision variables"); | ||
| 297 | |||
| 298 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 299 | ✗ | problem_->get_runningModels(); | |
| 300 | const std::vector<std::shared_ptr<ActionDataAbstract> >& datas = | ||
| 301 | ✗ | problem_->get_runningDatas(); | |
| 302 | ✗ | const std::size_t T = problem_->get_T(); | |
| 303 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 304 | #pragma omp parallel for num_threads(problem_->get_nthreads()) | ||
| 305 | #endif | ||
| 306 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 307 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 308 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 309 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 310 | ✗ | const std::size_t nui = model->get_nu(); | |
| 311 | |||
| 312 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 313 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 314 | ✗ | model->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 315 | ✗ | model->get_state()->Jintegrate(xs_[t], datas_[t]->dx, datas_[t]->Jint_dx, | |
| 316 | ✗ | datas_[t]->Jint_dx, second, setto); | |
| 317 | ✗ | model->calc(data, datas_[t]->x, datas_[t]->u); | |
| 318 | ✗ | model->calcDiff(data, datas_[t]->x, datas_[t]->u); | |
| 319 | ✗ | datas_[t]->Ldx.noalias() = datas_[t]->Jint_dx.transpose() * data->Lx; | |
| 320 | } | ||
| 321 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 322 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 323 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 324 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 325 | ✗ | const std::size_t nui = model->get_nu(); | |
| 326 | ✗ | for (std::size_t j = 0; j < ndxi; ++j) { | |
| 327 | ✗ | grad_f[ixu_[t] + j] = datas_[t]->Ldx(j); | |
| 328 | } | ||
| 329 | ✗ | for (std::size_t j = 0; j < nui; ++j) { | |
| 330 | ✗ | grad_f[ixu_[t] + ndxi + j] = data->Lu(j); | |
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | // Terminal model | ||
| 335 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 336 | ✗ | problem_->get_terminalModel(); | |
| 337 | const std::shared_ptr<ActionDataAbstract>& data = | ||
| 338 | ✗ | problem_->get_terminalData(); | |
| 339 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 340 | |||
| 341 | ✗ | datas_[T]->dx = Eigen::VectorXd::Map(x + ixu_.back(), ndxi); | |
| 342 | ✗ | model->get_state()->integrate(xs_[T], datas_[T]->dx, datas_[T]->x); | |
| 343 | ✗ | model->get_state()->Jintegrate(xs_[T], datas_[T]->dx, datas_[T]->Jint_dx, | |
| 344 | ✗ | datas_[T]->Jint_dx, second, setto); | |
| 345 | ✗ | model->calc(data, datas_[T]->x); | |
| 346 | ✗ | model->calcDiff(data, datas_[T]->x); | |
| 347 | ✗ | datas_[T]->Ldx.noalias() = datas_[T]->Jint_dx.transpose() * data->Lx; | |
| 348 | ✗ | for (std::size_t j = 0; j < ndxi; ++j) { | |
| 349 | ✗ | grad_f[ixu_.back() + j] = datas_[T]->Ldx(j); | |
| 350 | } | ||
| 351 | |||
| 352 | ✗ | return true; | |
| 353 | } | ||
| 354 | |||
| 355 | #ifndef NDEBUG | ||
| 356 | ✗ | bool IpoptInterface::eval_g(Ipopt::Index n, const Ipopt::Number* x, | |
| 357 | bool /*new_x*/, Ipopt::Index m, Ipopt::Number* g) { | ||
| 358 | #else | ||
| 359 | bool IpoptInterface::eval_g(Ipopt::Index, const Ipopt::Number* x, | ||
| 360 | bool /*new_x*/, Ipopt::Index, Ipopt::Number* g) { | ||
| 361 | #endif | ||
| 362 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 363 | "Inconsistent number of decision variables"); | ||
| 364 | ✗ | assert_pretty(m == static_cast<Ipopt::Index>(nconst_), | |
| 365 | "Inconsistent number of constraints"); | ||
| 366 | |||
| 367 | // Dynamic constraints | ||
| 368 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 369 | ✗ | problem_->get_runningModels(); | |
| 370 | const std::vector<std::shared_ptr<ActionDataAbstract> >& datas = | ||
| 371 | ✗ | problem_->get_runningDatas(); | |
| 372 | ✗ | const std::size_t T = problem_->get_T(); | |
| 373 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 374 | #pragma omp parallel for num_threads(problem_->get_nthreads()) | ||
| 375 | #endif | ||
| 376 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 377 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 378 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 379 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 380 | ✗ | const std::size_t nui = model->get_nu(); | |
| 381 | const std::shared_ptr<ActionModelAbstract>& model_next = | ||
| 382 | ✗ | t + 1 == T ? problem_->get_terminalModel() : models[t + 1]; | |
| 383 | ✗ | const std::size_t ndxi_next = model_next->get_state()->get_ndx(); | |
| 384 | |||
| 385 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 386 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 387 | ✗ | datas_[t]->dxnext = | |
| 388 | ✗ | Eigen::VectorXd::Map(x + ixu_[t] + ndxi + nui, ndxi_next); | |
| 389 | ✗ | model->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 390 | ✗ | model_next->get_state()->integrate(xs_[t + 1], datas_[t]->dxnext, | |
| 391 | ✗ | datas_[t]->xnext); | |
| 392 | ✗ | model->calc(data, datas_[t]->x, datas_[t]->u); | |
| 393 | ✗ | model->get_state()->diff(data->xnext, datas_[t]->xnext, datas_[t]->x_diff); | |
| 394 | } | ||
| 395 | |||
| 396 | ✗ | std::size_t ix = 0; | |
| 397 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 398 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 399 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 400 | ✗ | for (std::size_t j = 0; j < ndxi; ++j) { | |
| 401 | ✗ | g[ix + j] = datas_[t]->x_diff[j]; | |
| 402 | } | ||
| 403 | ✗ | ix += ndxi; | |
| 404 | } | ||
| 405 | |||
| 406 | // Initial conditions | ||
| 407 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[0]; | |
| 408 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 409 | ✗ | datas_[0]->dx = Eigen::VectorXd::Map(x, ndxi); | |
| 410 | ✗ | model->get_state()->integrate(xs_[0], datas_[0]->dx, datas_[0]->x); | |
| 411 | ✗ | model->get_state()->diff(datas_[0]->x, problem_->get_x0(), | |
| 412 | ✗ | datas_[0]->x_diff); // x(0) - x_0 | |
| 413 | ✗ | for (std::size_t j = 0; j < ndxi; j++) { | |
| 414 | ✗ | g[ix + j] = datas_[0]->x_diff[j]; | |
| 415 | } | ||
| 416 | |||
| 417 | ✗ | return true; | |
| 418 | } | ||
| 419 | |||
| 420 | #ifndef NDEBUG | ||
| 421 | ✗ | bool IpoptInterface::eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, | |
| 422 | bool /*new_x*/, Ipopt::Index m, | ||
| 423 | Ipopt::Index nele_jac, Ipopt::Index* iRow, | ||
| 424 | Ipopt::Index* jCol, Ipopt::Number* values) { | ||
| 425 | #else | ||
| 426 | bool IpoptInterface::eval_jac_g(Ipopt::Index, const Ipopt::Number* x, bool, | ||
| 427 | Ipopt::Index, Ipopt::Index, Ipopt::Index* iRow, | ||
| 428 | Ipopt::Index* jCol, Ipopt::Number* values) { | ||
| 429 | #endif | ||
| 430 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 431 | "Inconsistent number of decision variables"); | ||
| 432 | ✗ | assert_pretty(m == static_cast<Ipopt::Index>(nconst_), | |
| 433 | "Inconsistent number of constraints"); | ||
| 434 | |||
| 435 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 436 | ✗ | problem_->get_runningModels(); | |
| 437 | ✗ | if (values == NULL) { | |
| 438 | // Dynamic constraints | ||
| 439 | ✗ | std::size_t idx = 0; | |
| 440 | ✗ | std::size_t ix = 0; | |
| 441 | ✗ | const std::size_t T = problem_->get_T(); | |
| 442 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 443 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 444 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 445 | ✗ | const std::size_t nui = model->get_nu(); | |
| 446 | const std::size_t ndxi_next = | ||
| 447 | ✗ | t + 1 == T ? problem_->get_terminalModel()->get_state()->get_ndx() | |
| 448 | ✗ | : models[t + 1]->get_state()->get_ndx(); | |
| 449 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; ++idx_row) { | |
| 450 | ✗ | for (std::size_t idx_col = 0; idx_col < (ndxi + nui + ndxi_next); | |
| 451 | ++idx_col) { | ||
| 452 | ✗ | iRow[idx] = static_cast<Ipopt::Index>(ix + idx_row); | |
| 453 | ✗ | jCol[idx] = static_cast<Ipopt::Index>(ixu_[t] + idx_col); | |
| 454 | ✗ | idx++; | |
| 455 | } | ||
| 456 | } | ||
| 457 | ✗ | ix += ndxi; | |
| 458 | } | ||
| 459 | |||
| 460 | // Initial condition | ||
| 461 | ✗ | const std::size_t ndxi = models[0]->get_state()->get_ndx(); | |
| 462 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; ++idx_row) { | |
| 463 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; ++idx_col) { | |
| 464 | ✗ | iRow[idx] = static_cast<Ipopt::Index>(ix + idx_row); | |
| 465 | ✗ | jCol[idx] = static_cast<Ipopt::Index>(idx_col); | |
| 466 | ✗ | idx++; | |
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | ✗ | assert_pretty(nele_jac == static_cast<Ipopt::Index>(idx), | |
| 471 | "Number of jacobian elements set does not coincide with the " | ||
| 472 | "total non-zero Jacobian values"); | ||
| 473 | } else { | ||
| 474 | const std::vector<std::shared_ptr<ActionDataAbstract> >& datas = | ||
| 475 | ✗ | problem_->get_runningDatas(); | |
| 476 | // Dynamic constraints | ||
| 477 | ✗ | const std::size_t T = problem_->get_T(); | |
| 478 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 479 | #pragma omp parallel for num_threads(problem_->get_nthreads()) | ||
| 480 | #endif | ||
| 481 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 482 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 483 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 484 | const std::shared_ptr<ActionModelAbstract>& model_next = | ||
| 485 | ✗ | t + 1 == T ? problem_->get_terminalModel() : models[t + 1]; | |
| 486 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 487 | ✗ | const std::size_t ndxi_next = model_next->get_state()->get_ndx(); | |
| 488 | ✗ | const std::size_t nui = model->get_nu(); | |
| 489 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 490 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 491 | ✗ | datas_[t]->dxnext = | |
| 492 | ✗ | Eigen::VectorXd::Map(x + ixu_[t] + ndxi + nui, ndxi_next); | |
| 493 | |||
| 494 | ✗ | model->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 495 | ✗ | model_next->get_state()->integrate(xs_[t + 1], datas_[t]->dxnext, | |
| 496 | ✗ | datas_[t]->xnext); | |
| 497 | ✗ | model->calcDiff(data, datas_[t]->x, datas_[t]->u); | |
| 498 | ✗ | model_next->get_state()->Jintegrate( | |
| 499 | ✗ | xs_[t + 1], datas_[t]->dxnext, datas_[t]->Jint_dxnext, | |
| 500 | ✗ | datas_[t]->Jint_dxnext, second, | |
| 501 | setto); // datas_[t]->Jsum_dxnext == eq. 81 | ||
| 502 | ✗ | model->get_state()->Jdiff( | |
| 503 | ✗ | data->xnext, datas_[t]->xnext, datas_[t]->Jdiff_x, | |
| 504 | ✗ | datas_[t]->Jdiff_xnext, | |
| 505 | both); // datas_[t+1]->Jdiff_x == eq. 83, datas_[t]->Jdiff_x == eq.82 | ||
| 506 | ✗ | model->get_state()->Jintegrate(xs_[t], datas_[t]->dx, datas_[t]->Jint_dx, | |
| 507 | ✗ | datas_[t]->Jint_dx, second, | |
| 508 | setto); // datas_[t]->Jsum_dx == eq. 81 | ||
| 509 | ✗ | datas_[t]->Jg_dxnext.noalias() = | |
| 510 | ✗ | datas_[t]->Jdiff_xnext * datas_[t]->Jint_dxnext; // chain rule | |
| 511 | ✗ | datas_[t]->FxJint_dx.noalias() = data->Fx * datas_[t]->Jint_dx; | |
| 512 | ✗ | datas_[t]->Jg_dx.noalias() = datas_[t]->Jdiff_x * datas_[t]->FxJint_dx; | |
| 513 | ✗ | datas_[t]->Jg_u.noalias() = datas_[t]->Jdiff_x * data->Fu; | |
| 514 | } | ||
| 515 | ✗ | std::size_t idx = 0; | |
| 516 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 517 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 518 | const std::shared_ptr<ActionModelAbstract>& model_next = | ||
| 519 | ✗ | t + 1 == T ? problem_->get_terminalModel() : models[t + 1]; | |
| 520 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 521 | ✗ | const std::size_t nui = model->get_nu(); | |
| 522 | ✗ | const std::size_t ndxi_next = model_next->get_state()->get_ndx(); | |
| 523 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; ++idx_row) { | |
| 524 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; ++idx_col) { | |
| 525 | ✗ | values[idx] = datas_[t]->Jg_dx(idx_row, idx_col); | |
| 526 | ✗ | idx++; | |
| 527 | } | ||
| 528 | ✗ | for (std::size_t idx_col = 0; idx_col < nui; ++idx_col) { | |
| 529 | ✗ | values[idx] = datas_[t]->Jg_u(idx_row, idx_col); | |
| 530 | ✗ | idx++; | |
| 531 | } | ||
| 532 | // This could be more optimized since there are a lot of zeros! | ||
| 533 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi_next; ++idx_col) { | |
| 534 | ✗ | values[idx] = datas_[t]->Jg_dxnext(idx_row, idx_col); | |
| 535 | ✗ | idx++; | |
| 536 | } | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | // Initial condition | ||
| 541 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[0]; | |
| 542 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 543 | ✗ | datas_[0]->dx = Eigen::VectorXd::Map(x, ndxi); | |
| 544 | |||
| 545 | ✗ | model->get_state()->integrate(xs_[0], datas_[0]->dx, datas_[0]->x); | |
| 546 | ✗ | model->get_state()->Jdiff(datas_[0]->x, problem_->get_x0(), | |
| 547 | ✗ | datas_[0]->Jdiff_x, datas_[0]->Jdiff_x, first); | |
| 548 | ✗ | model->get_state()->Jintegrate(xs_[0], datas_[0]->dx, datas_[0]->Jint_dx, | |
| 549 | ✗ | datas_[0]->Jint_dx, second, setto); | |
| 550 | ✗ | datas_[0]->Jg_ic.noalias() = datas_[0]->Jdiff_x * datas_[0]->Jint_dx; | |
| 551 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; ++idx_row) { | |
| 552 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; ++idx_col) { | |
| 553 | ✗ | values[idx] = datas_[0]->Jg_ic(idx_row, idx_col); | |
| 554 | ✗ | idx++; | |
| 555 | } | ||
| 556 | } | ||
| 557 | } | ||
| 558 | |||
| 559 | ✗ | return true; | |
| 560 | } | ||
| 561 | |||
| 562 | #ifndef NDEBUG | ||
| 563 | ✗ | bool IpoptInterface::eval_h(Ipopt::Index n, const Ipopt::Number* x, | |
| 564 | bool /*new_x*/, Ipopt::Number obj_factor, | ||
| 565 | Ipopt::Index m, const Ipopt::Number* /*lambda*/, | ||
| 566 | bool /*new_lambda*/, Ipopt::Index nele_hess, | ||
| 567 | Ipopt::Index* iRow, Ipopt::Index* jCol, | ||
| 568 | Ipopt::Number* values) { | ||
| 569 | #else | ||
| 570 | bool IpoptInterface::eval_h(Ipopt::Index, const Ipopt::Number* x, bool, | ||
| 571 | Ipopt::Number obj_factor, Ipopt::Index, | ||
| 572 | const Ipopt::Number*, bool, Ipopt::Index, | ||
| 573 | Ipopt::Index* iRow, Ipopt::Index* jCol, | ||
| 574 | Ipopt::Number* values) { | ||
| 575 | #endif | ||
| 576 | ✗ | assert_pretty(n == static_cast<Ipopt::Index>(nvar_), | |
| 577 | "Inconsistent number of decision variables"); | ||
| 578 | ✗ | assert_pretty(m == static_cast<Ipopt::Index>(nconst_), | |
| 579 | "Inconsistent number of constraints"); | ||
| 580 | |||
| 581 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 582 | ✗ | problem_->get_runningModels(); | |
| 583 | ✗ | const std::size_t T = problem_->get_T(); | |
| 584 | ✗ | if (values == NULL) { | |
| 585 | // return the structure. This is a symmetric matrix, fill the lower left | ||
| 586 | // triangle only | ||
| 587 | |||
| 588 | // Running Costs | ||
| 589 | ✗ | std::size_t idx = 0; | |
| 590 | ✗ | for (std::size_t t = 0; t < problem_->get_T(); ++t) { | |
| 591 | ✗ | const std::shared_ptr<ActionModelAbstract> model = models[t]; | |
| 592 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 593 | ✗ | const std::size_t nui = model->get_nu(); | |
| 594 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi + nui; ++idx_row) { | |
| 595 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi + nui; ++idx_col) { | |
| 596 | // We need the lower triangular matrix | ||
| 597 | ✗ | if (idx_col > idx_row) { | |
| 598 | ✗ | break; | |
| 599 | } | ||
| 600 | ✗ | iRow[idx] = static_cast<Ipopt::Index>(ixu_[t] + idx_row); | |
| 601 | ✗ | jCol[idx] = static_cast<Ipopt::Index>(ixu_[t] + idx_col); | |
| 602 | ✗ | idx++; | |
| 603 | } | ||
| 604 | } | ||
| 605 | ✗ | } | |
| 606 | |||
| 607 | // Terminal costs | ||
| 608 | const std::size_t ndxi = | ||
| 609 | ✗ | problem_->get_terminalModel()->get_state()->get_ndx(); | |
| 610 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; idx_row++) { | |
| 611 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; idx_col++) { | |
| 612 | // We need the lower triangular matrix | ||
| 613 | ✗ | if (idx_col > idx_row) { | |
| 614 | ✗ | break; | |
| 615 | } | ||
| 616 | ✗ | iRow[idx] = static_cast<Ipopt::Index>(ixu_.back() + idx_row); | |
| 617 | ✗ | jCol[idx] = static_cast<Ipopt::Index>(ixu_.back() + idx_col); | |
| 618 | ✗ | idx++; | |
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | ✗ | assert_pretty(nele_hess == static_cast<Ipopt::Index>(idx), | |
| 623 | "Number of Hessian elements set does not coincide with the " | ||
| 624 | "total non-zero Hessian values"); | ||
| 625 | } else { | ||
| 626 | // return the values. This is a symmetric matrix, fill the lower left | ||
| 627 | // triangle only | ||
| 628 | // Running Costs | ||
| 629 | const std::vector<std::shared_ptr<ActionDataAbstract> >& datas = | ||
| 630 | ✗ | problem_->get_runningDatas(); | |
| 631 | #ifdef CROCODDYL_WITH_MULTITHREADING | ||
| 632 | #pragma omp parallel for num_threads(problem_->get_nthreads()) | ||
| 633 | #endif | ||
| 634 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 635 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 636 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 637 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 638 | ✗ | const std::size_t nui = model->get_nu(); | |
| 639 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 640 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 641 | |||
| 642 | ✗ | model->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 643 | ✗ | model->calcDiff(data, datas_[t]->x, | |
| 644 | ✗ | datas_[t]->u); // this might be removed | |
| 645 | ✗ | model->get_state()->Jintegrate(xs_[t], datas_[t]->dx, datas_[t]->Jint_dx, | |
| 646 | ✗ | datas_[t]->Jint_dx, second, setto); | |
| 647 | ✗ | datas_[t]->Ldxdx.noalias() = | |
| 648 | ✗ | datas_[t]->Jint_dx.transpose() * data->Lxx * datas_[t]->Jint_dx; | |
| 649 | ✗ | datas_[t]->Ldxu.noalias() = datas_[t]->Jint_dx.transpose() * data->Lxu; | |
| 650 | } | ||
| 651 | |||
| 652 | ✗ | std::size_t idx = 0; | |
| 653 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 654 | ✗ | const std::shared_ptr<ActionModelAbstract>& model = models[t]; | |
| 655 | ✗ | const std::shared_ptr<ActionDataAbstract>& data = datas[t]; | |
| 656 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 657 | ✗ | const std::size_t nui = model->get_nu(); | |
| 658 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; ++idx_row) { | |
| 659 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; ++idx_col) { | |
| 660 | // We need the lower triangular matrix | ||
| 661 | ✗ | if (idx_col > idx_row) { | |
| 662 | ✗ | break; | |
| 663 | } | ||
| 664 | ✗ | values[idx] = obj_factor * datas_[t]->Ldxdx(idx_row, idx_col); | |
| 665 | ✗ | idx++; | |
| 666 | } | ||
| 667 | } | ||
| 668 | ✗ | for (std::size_t idx_row = 0; idx_row < nui; ++idx_row) { | |
| 669 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; ++idx_col) { | |
| 670 | ✗ | values[idx] = obj_factor * datas_[t]->Ldxu(idx_col, idx_row); | |
| 671 | ✗ | idx++; | |
| 672 | } | ||
| 673 | ✗ | for (std::size_t idx_col = 0; idx_col < nui; ++idx_col) { | |
| 674 | ✗ | if (idx_col > idx_row) { | |
| 675 | ✗ | break; | |
| 676 | } | ||
| 677 | ✗ | values[idx] = obj_factor * data->Luu(idx_row, idx_col); | |
| 678 | ✗ | idx++; | |
| 679 | } | ||
| 680 | } | ||
| 681 | } | ||
| 682 | |||
| 683 | // Terminal costs | ||
| 684 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 685 | ✗ | problem_->get_terminalModel(); | |
| 686 | const std::shared_ptr<ActionDataAbstract>& data = | ||
| 687 | ✗ | problem_->get_terminalData(); | |
| 688 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 689 | ✗ | datas_[T]->dx = Eigen::VectorXd::Map(x + ixu_.back(), ndxi); | |
| 690 | |||
| 691 | ✗ | model->get_state()->integrate(xs_[T], datas_[T]->dx, datas_[T]->x); | |
| 692 | ✗ | model->calc(data, datas_[T]->x); | |
| 693 | ✗ | model->calcDiff(data, datas_[T]->x); | |
| 694 | ✗ | model->get_state()->Jintegrate(xs_[T], datas_[T]->dx, datas_[T]->Jint_dx, | |
| 695 | ✗ | datas_[T]->Jint_dx, second, setto); | |
| 696 | ✗ | datas_[T]->Ldxdx.noalias() = | |
| 697 | ✗ | datas_[T]->Jint_dx.transpose() * data->Lxx * datas_[T]->Jint_dx; | |
| 698 | ✗ | for (std::size_t idx_row = 0; idx_row < ndxi; idx_row++) { | |
| 699 | ✗ | for (std::size_t idx_col = 0; idx_col < ndxi; idx_col++) { | |
| 700 | // We need the lower triangular matrix | ||
| 701 | ✗ | if (idx_col > idx_row) { | |
| 702 | ✗ | break; | |
| 703 | } | ||
| 704 | ✗ | values[idx] = datas_[T]->Ldxdx(idx_row, idx_col); | |
| 705 | ✗ | idx++; | |
| 706 | } | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | ✗ | return true; | |
| 711 | } | ||
| 712 | |||
| 713 | ✗ | void IpoptInterface::finalize_solution( | |
| 714 | Ipopt::SolverReturn /*status*/, Ipopt::Index /*n*/, const Ipopt::Number* x, | ||
| 715 | const Ipopt::Number* /*z_L*/, const Ipopt::Number* /*z_U*/, | ||
| 716 | Ipopt::Index /*m*/, const Ipopt::Number* /*g*/, | ||
| 717 | const Ipopt::Number* /*lambda*/, Ipopt::Number obj_value, | ||
| 718 | const Ipopt::IpoptData* /*ip_data*/, | ||
| 719 | Ipopt::IpoptCalculatedQuantities* /*ip_cq*/) { | ||
| 720 | // Copy the solution to vector once solver is finished | ||
| 721 | const std::vector<std::shared_ptr<ActionModelAbstract> >& models = | ||
| 722 | ✗ | problem_->get_runningModels(); | |
| 723 | ✗ | const std::size_t T = problem_->get_T(); | |
| 724 | ✗ | for (std::size_t t = 0; t < T; ++t) { | |
| 725 | ✗ | const std::size_t ndxi = models[t]->get_state()->get_ndx(); | |
| 726 | ✗ | const std::size_t nui = models[t]->get_nu(); | |
| 727 | ✗ | datas_[t]->dx = Eigen::VectorXd::Map(x + ixu_[t], ndxi); | |
| 728 | ✗ | datas_[t]->u = Eigen::VectorXd::Map(x + ixu_[t] + ndxi, nui); | |
| 729 | |||
| 730 | ✗ | models[t]->get_state()->integrate(xs_[t], datas_[t]->dx, datas_[t]->x); | |
| 731 | ✗ | xs_[t] = datas_[t]->x; | |
| 732 | ✗ | us_[t] = datas_[t]->u; | |
| 733 | } | ||
| 734 | // Terminal node | ||
| 735 | const std::shared_ptr<ActionModelAbstract>& model = | ||
| 736 | ✗ | problem_->get_terminalModel(); | |
| 737 | ✗ | const std::size_t ndxi = model->get_state()->get_ndx(); | |
| 738 | ✗ | datas_[T]->dx = Eigen::VectorXd::Map(x + ixu_.back(), ndxi); | |
| 739 | ✗ | model->get_state()->integrate(xs_[T], datas_[T]->dx, datas_[T]->x); | |
| 740 | ✗ | xs_[T] = datas_[T]->x; | |
| 741 | |||
| 742 | ✗ | cost_ = obj_value; | |
| 743 | ✗ | } | |
| 744 | |||
| 745 | ✗ | bool IpoptInterface::intermediate_callback( | |
| 746 | Ipopt::AlgorithmMode /*mode*/, Ipopt::Index /*iter*/, | ||
| 747 | Ipopt::Number /*obj_value*/, Ipopt::Number /*inf_pr*/, | ||
| 748 | Ipopt::Number /*inf_du*/, Ipopt::Number /*mu*/, Ipopt::Number /*d_norm*/, | ||
| 749 | Ipopt::Number /*regularization_size*/, Ipopt::Number /*alpha_du*/, | ||
| 750 | Ipopt::Number /*alpha_pr*/, Ipopt::Index /*ls_trials*/, | ||
| 751 | const Ipopt::IpoptData* /*ip_data*/, | ||
| 752 | Ipopt::IpoptCalculatedQuantities* /*ip_cq*/) { | ||
| 753 | ✗ | return true; | |
| 754 | } | ||
| 755 | |||
| 756 | ✗ | std::shared_ptr<IpoptInterfaceData> IpoptInterface::createData( | |
| 757 | const std::size_t nx, const std::size_t ndx, const std::size_t nu) { | ||
| 758 | return std::allocate_shared<IpoptInterfaceData>( | ||
| 759 | ✗ | Eigen::aligned_allocator<IpoptInterfaceData>(), nx, ndx, nu); | |
| 760 | } | ||
| 761 | |||
| 762 | ✗ | void IpoptInterface::set_xs(const std::vector<Eigen::VectorXd>& xs) { | |
| 763 | ✗ | xs_ = xs; | |
| 764 | ✗ | } | |
| 765 | |||
| 766 | ✗ | void IpoptInterface::set_us(const std::vector<Eigen::VectorXd>& us) { | |
| 767 | ✗ | us_ = us; | |
| 768 | ✗ | } | |
| 769 | |||
| 770 | ✗ | std::size_t IpoptInterface::get_nvar() const { return nvar_; } | |
| 771 | |||
| 772 | ✗ | std::size_t IpoptInterface::get_nconst() const { return nconst_; } | |
| 773 | |||
| 774 | ✗ | const std::vector<Eigen::VectorXd>& IpoptInterface::get_xs() const { | |
| 775 | ✗ | return xs_; | |
| 776 | } | ||
| 777 | |||
| 778 | ✗ | const std::vector<Eigen::VectorXd>& IpoptInterface::get_us() const { | |
| 779 | ✗ | return us_; | |
| 780 | } | ||
| 781 | |||
| 782 | ✗ | const std::shared_ptr<ShootingProblem>& IpoptInterface::get_problem() const { | |
| 783 | ✗ | return problem_; | |
| 784 | } | ||
| 785 | |||
| 786 | ✗ | double IpoptInterface::get_cost() const { return cost_; } | |
| 787 | |||
| 788 | } // namespace crocoddyl | ||
| 789 |