| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////// | ||
| 2 | // BSD 3-Clause License | ||
| 3 | // | ||
| 4 | // Copyright (C) 2019-2025, LAAS-CNRS, University of Edinburgh, | ||
| 5 | // University of Oxford, Heriot-Watt University | ||
| 6 | // Copyright note valid unless otherwise stated in individual files. | ||
| 7 | // All rights reserved. | ||
| 8 | /////////////////////////////////////////////////////////////////////////////// | ||
| 9 | |||
| 10 | namespace crocoddyl { | ||
| 11 | |||
| 12 | template <typename Scalar> | ||
| 13 | ✗ | ActionModelAbstractTpl<Scalar>::ActionModelAbstractTpl( | |
| 14 | std::shared_ptr<StateAbstractTpl<Scalar> > state, const std::size_t nu, | ||
| 15 | const std::size_t nr, const std::size_t ng, const std::size_t nh, | ||
| 16 | const std::size_t ng_T, const std::size_t nh_T) | ||
| 17 | ✗ | : nu_(nu), | |
| 18 | ✗ | nr_(nr), | |
| 19 | ✗ | ng_(ng), | |
| 20 | ✗ | nh_(nh), | |
| 21 | ✗ | ng_T_(ng_T), | |
| 22 | ✗ | nh_T_(nh_T), | |
| 23 | ✗ | state_(state), | |
| 24 | ✗ | unone_(MathBase::VectorXs::Zero(nu)), | |
| 25 | ✗ | g_lb_(VectorXs::Constant(ng > ng_T ? ng : ng_T, | |
| 26 | ✗ | -std::numeric_limits<Scalar>::infinity())), | |
| 27 | ✗ | g_ub_(VectorXs::Constant(ng > ng_T ? ng : ng_T, | |
| 28 | ✗ | std::numeric_limits<Scalar>::infinity())), | |
| 29 | ✗ | u_lb_(MathBase::VectorXs::Constant( | |
| 30 | ✗ | nu, -std::numeric_limits<Scalar>::infinity())), | |
| 31 | ✗ | u_ub_(MathBase::VectorXs::Constant( | |
| 32 | ✗ | nu, std::numeric_limits<Scalar>::infinity())), | |
| 33 | ✗ | has_control_limits_(false) {} | |
| 34 | |||
| 35 | template <typename Scalar> | ||
| 36 | ✗ | ActionModelAbstractTpl<Scalar>::ActionModelAbstractTpl( | |
| 37 | const ActionModelAbstractTpl<Scalar>& other) | ||
| 38 | ✗ | : nu_(other.nu_), | |
| 39 | ✗ | nr_(other.nr_), | |
| 40 | ✗ | ng_(other.ng_), | |
| 41 | ✗ | nh_(other.nh_), | |
| 42 | ✗ | ng_T_(other.ng_T_), | |
| 43 | ✗ | nh_T_(other.nh_T_), | |
| 44 | ✗ | state_(other.state_), | |
| 45 | ✗ | g_lb_(other.g_lb_), | |
| 46 | ✗ | g_ub_(other.g_ub_), | |
| 47 | ✗ | u_lb_(other.u_lb_), | |
| 48 | ✗ | u_ub_(other.u_ub_), | |
| 49 | ✗ | has_control_limits_(other.has_control_limits_) {} | |
| 50 | |||
| 51 | template <typename Scalar> | ||
| 52 | ✗ | void ActionModelAbstractTpl<Scalar>::calc( | |
| 53 | const std::shared_ptr<ActionDataAbstract>& data, | ||
| 54 | const Eigen::Ref<const VectorXs>& x) { | ||
| 55 | ✗ | calc(data, x, unone_); | |
| 56 | ✗ | } | |
| 57 | |||
| 58 | template <typename Scalar> | ||
| 59 | ✗ | void ActionModelAbstractTpl<Scalar>::calcDiff( | |
| 60 | const std::shared_ptr<ActionDataAbstract>& data, | ||
| 61 | const Eigen::Ref<const VectorXs>& x) { | ||
| 62 | ✗ | calcDiff(data, x, unone_); | |
| 63 | ✗ | } | |
| 64 | |||
| 65 | template <typename Scalar> | ||
| 66 | ✗ | void ActionModelAbstractTpl<Scalar>::quasiStatic( | |
| 67 | const std::shared_ptr<ActionDataAbstract>& data, Eigen::Ref<VectorXs> u, | ||
| 68 | const Eigen::Ref<const VectorXs>& x, const std::size_t maxiter, | ||
| 69 | const Scalar tol) { | ||
| 70 | ✗ | if (static_cast<std::size_t>(u.size()) != nu_) { | |
| 71 | ✗ | throw_pretty( | |
| 72 | "Invalid argument: " << "u has wrong dimension (it should be " + | ||
| 73 | std::to_string(nu_) + ")"); | ||
| 74 | } | ||
| 75 | ✗ | if (static_cast<std::size_t>(x.size()) != state_->get_nx()) { | |
| 76 | ✗ | throw_pretty( | |
| 77 | "Invalid argument: " << "x has wrong dimension (it should be " + | ||
| 78 | std::to_string(state_->get_nx()) + ")"); | ||
| 79 | } | ||
| 80 | // Check the velocity input is zero | ||
| 81 | ✗ | assert_pretty(x.tail(state_->get_nv()).isZero(), | |
| 82 | "The velocity input should be zero for quasi-static to work."); | ||
| 83 | |||
| 84 | ✗ | const std::size_t ndx = state_->get_ndx(); | |
| 85 | ✗ | VectorXs dx = VectorXs::Zero(ndx); | |
| 86 | ✗ | if (nu_ != 0) { | |
| 87 | ✗ | VectorXs du = VectorXs::Zero(nu_); | |
| 88 | ✗ | for (std::size_t i = 0; i < maxiter; ++i) { | |
| 89 | ✗ | calc(data, x, u); | |
| 90 | ✗ | calcDiff(data, x, u); | |
| 91 | ✗ | state_->diff(x, data->xnext, dx); | |
| 92 | ✗ | du.noalias() = -pseudoInverse(data->Fu) * dx; | |
| 93 | ✗ | u += du; | |
| 94 | ✗ | if (du.norm() <= tol) { | |
| 95 | ✗ | break; | |
| 96 | } | ||
| 97 | } | ||
| 98 | ✗ | } | |
| 99 | ✗ | } | |
| 100 | |||
| 101 | template <typename Scalar> | ||
| 102 | typename MathBaseTpl<Scalar>::VectorXs | ||
| 103 | ✗ | ActionModelAbstractTpl<Scalar>::quasiStatic_x( | |
| 104 | const std::shared_ptr<ActionDataAbstract>& data, const VectorXs& x, | ||
| 105 | const std::size_t maxiter, const Scalar tol) { | ||
| 106 | ✗ | VectorXs u(nu_); | |
| 107 | ✗ | u.setZero(); | |
| 108 | ✗ | quasiStatic(data, u, x, maxiter, tol); | |
| 109 | ✗ | return u; | |
| 110 | ✗ | } | |
| 111 | |||
| 112 | template <typename Scalar> | ||
| 113 | std::shared_ptr<ActionDataAbstractTpl<Scalar> > | ||
| 114 | ✗ | ActionModelAbstractTpl<Scalar>::createData() { | |
| 115 | return std::allocate_shared<ActionDataAbstract>( | ||
| 116 | ✗ | Eigen::aligned_allocator<ActionDataAbstract>(), this); | |
| 117 | } | ||
| 118 | |||
| 119 | template <typename Scalar> | ||
| 120 | ✗ | bool ActionModelAbstractTpl<Scalar>::checkData( | |
| 121 | const std::shared_ptr<ActionDataAbstract>&) { | ||
| 122 | ✗ | return false; | |
| 123 | } | ||
| 124 | |||
| 125 | template <typename Scalar> | ||
| 126 | ✗ | void ActionModelAbstractTpl<Scalar>::print(std::ostream& os) const { | |
| 127 | ✗ | os << boost::core::demangle(typeid(*this).name()); | |
| 128 | ✗ | } | |
| 129 | |||
| 130 | template <typename Scalar> | ||
| 131 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_nu() const { | |
| 132 | ✗ | return nu_; | |
| 133 | } | ||
| 134 | |||
| 135 | template <typename Scalar> | ||
| 136 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_nr() const { | |
| 137 | ✗ | return nr_; | |
| 138 | } | ||
| 139 | |||
| 140 | template <typename Scalar> | ||
| 141 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_ng() const { | |
| 142 | ✗ | return ng_; | |
| 143 | } | ||
| 144 | |||
| 145 | template <typename Scalar> | ||
| 146 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_nh() const { | |
| 147 | ✗ | return nh_; | |
| 148 | } | ||
| 149 | |||
| 150 | template <typename Scalar> | ||
| 151 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_ng_T() const { | |
| 152 | ✗ | return ng_T_; | |
| 153 | } | ||
| 154 | |||
| 155 | template <typename Scalar> | ||
| 156 | ✗ | std::size_t ActionModelAbstractTpl<Scalar>::get_nh_T() const { | |
| 157 | ✗ | return nh_T_; | |
| 158 | } | ||
| 159 | |||
| 160 | template <typename Scalar> | ||
| 161 | const std::shared_ptr<StateAbstractTpl<Scalar> >& | ||
| 162 | ✗ | ActionModelAbstractTpl<Scalar>::get_state() const { | |
| 163 | ✗ | return state_; | |
| 164 | } | ||
| 165 | |||
| 166 | template <typename Scalar> | ||
| 167 | const typename MathBaseTpl<Scalar>::VectorXs& | ||
| 168 | ✗ | ActionModelAbstractTpl<Scalar>::get_g_lb() const { | |
| 169 | ✗ | return g_lb_; | |
| 170 | } | ||
| 171 | |||
| 172 | template <typename Scalar> | ||
| 173 | const typename MathBaseTpl<Scalar>::VectorXs& | ||
| 174 | ✗ | ActionModelAbstractTpl<Scalar>::get_g_ub() const { | |
| 175 | ✗ | return g_ub_; | |
| 176 | } | ||
| 177 | |||
| 178 | template <typename Scalar> | ||
| 179 | const typename MathBaseTpl<Scalar>::VectorXs& | ||
| 180 | ✗ | ActionModelAbstractTpl<Scalar>::get_u_lb() const { | |
| 181 | ✗ | return u_lb_; | |
| 182 | } | ||
| 183 | |||
| 184 | template <typename Scalar> | ||
| 185 | const typename MathBaseTpl<Scalar>::VectorXs& | ||
| 186 | ✗ | ActionModelAbstractTpl<Scalar>::get_u_ub() const { | |
| 187 | ✗ | return u_ub_; | |
| 188 | } | ||
| 189 | |||
| 190 | template <typename Scalar> | ||
| 191 | ✗ | bool ActionModelAbstractTpl<Scalar>::get_has_control_limits() const { | |
| 192 | ✗ | return has_control_limits_; | |
| 193 | } | ||
| 194 | |||
| 195 | template <typename Scalar> | ||
| 196 | ✗ | void ActionModelAbstractTpl<Scalar>::set_g_lb(const VectorXs& g_lb) { | |
| 197 | ✗ | const std::size_t ng = ng_ > ng_T_ ? ng_ : ng_T_; | |
| 198 | ✗ | if (static_cast<std::size_t>(g_lb.size()) != ng) { | |
| 199 | ✗ | throw_pretty( | |
| 200 | "Invalid argument: " | ||
| 201 | << "inequality lower bound has wrong dimension (it should be " + | ||
| 202 | std::to_string(ng) + ")"); | ||
| 203 | } | ||
| 204 | ✗ | g_lb_ = g_lb; | |
| 205 | ✗ | } | |
| 206 | |||
| 207 | template <typename Scalar> | ||
| 208 | ✗ | void ActionModelAbstractTpl<Scalar>::set_g_ub(const VectorXs& g_ub) { | |
| 209 | ✗ | const std::size_t ng = ng_ > ng_T_ ? ng_ : ng_T_; | |
| 210 | ✗ | if (static_cast<std::size_t>(g_ub.size()) != ng) { | |
| 211 | ✗ | throw_pretty( | |
| 212 | "Invalid argument: " | ||
| 213 | << "inequality upper bound has wrong dimension (it should be " + | ||
| 214 | std::to_string(ng_) + ")"); | ||
| 215 | } | ||
| 216 | ✗ | g_ub_ = g_ub; | |
| 217 | ✗ | } | |
| 218 | |||
| 219 | template <typename Scalar> | ||
| 220 | ✗ | void ActionModelAbstractTpl<Scalar>::set_u_lb(const VectorXs& u_lb) { | |
| 221 | ✗ | if (static_cast<std::size_t>(u_lb.size()) != nu_) { | |
| 222 | ✗ | throw_pretty("Invalid argument: " | |
| 223 | << "control lower bound has wrong dimension (it should be " + | ||
| 224 | std::to_string(nu_) + ")"); | ||
| 225 | } | ||
| 226 | ✗ | u_lb_ = u_lb; | |
| 227 | ✗ | update_has_control_limits(); | |
| 228 | ✗ | } | |
| 229 | |||
| 230 | template <typename Scalar> | ||
| 231 | ✗ | void ActionModelAbstractTpl<Scalar>::set_u_ub(const VectorXs& u_ub) { | |
| 232 | ✗ | if (static_cast<std::size_t>(u_ub.size()) != nu_) { | |
| 233 | ✗ | throw_pretty("Invalid argument: " | |
| 234 | << "control upper bound has wrong dimension (it should be " + | ||
| 235 | std::to_string(nu_) + ")"); | ||
| 236 | } | ||
| 237 | ✗ | u_ub_ = u_ub; | |
| 238 | ✗ | update_has_control_limits(); | |
| 239 | ✗ | } | |
| 240 | |||
| 241 | template <typename Scalar> | ||
| 242 | ✗ | void ActionModelAbstractTpl<Scalar>::update_has_control_limits() { | |
| 243 | ✗ | has_control_limits_ = | |
| 244 | ✗ | isfinite(u_lb_.template cast<ScalarType>().array()).any() && | |
| 245 | ✗ | isfinite(u_ub_.template cast<ScalarType>().array()).any(); | |
| 246 | ✗ | } | |
| 247 | |||
| 248 | template <typename Scalar> | ||
| 249 | ✗ | std::ostream& operator<<(std::ostream& os, | |
| 250 | const ActionModelAbstractTpl<Scalar>& model) { | ||
| 251 | ✗ | model.print(os); | |
| 252 | ✗ | return os; | |
| 253 | } | ||
| 254 | |||
| 255 | } // namespace crocoddyl | ||
| 256 |