Crocoddyl
cost-sum.hpp
1 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, LAAS-CNRS, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
9 
10 #ifndef CROCODDYL_CORE_COSTS_COST_SUM_HPP_
11 #define CROCODDYL_CORE_COSTS_COST_SUM_HPP_
12 
13 #include "crocoddyl/core/cost-base.hpp"
14 #include "crocoddyl/core/fwd.hpp"
15 
16 namespace crocoddyl {
17 
18 template <typename _Scalar>
19 struct CostItemTpl {
20  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
21 
22  typedef _Scalar Scalar;
24 
25  CostItemTpl() {}
26  CostItemTpl(const std::string& name, std::shared_ptr<CostModelAbstract> cost,
27  const Scalar weight, const bool active = true)
28  : name(name), cost(cost), weight(weight), active(active) {}
29 
30  template <typename NewScalar>
31  CostItemTpl<NewScalar> cast() const {
32  typedef CostItemTpl<NewScalar> ReturnType;
33  ReturnType ret(name, cost->template cast<NewScalar>(),
34  scalar_cast<NewScalar>(weight), active);
35  return ret;
36  }
37 
41  friend std::ostream& operator<<(std::ostream& os,
42  const CostItemTpl<Scalar>& model) {
43  os << "{w=" << model.weight << ", " << *model.cost << "}";
44  return os;
45  }
46 
47  std::string name;
48  std::shared_ptr<CostModelAbstract> cost;
49  Scalar weight;
50  bool active;
51 };
52 
74 template <typename _Scalar>
76  public:
77  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
78 
79  typedef _Scalar Scalar;
87  typedef typename MathBase::VectorXs VectorXs;
88  typedef typename MathBase::MatrixXs MatrixXs;
89 
90  typedef std::map<std::string, std::shared_ptr<CostItem> > CostModelContainer;
91  typedef std::map<std::string, std::shared_ptr<CostDataAbstract> >
92  CostDataContainer;
93 
100  CostModelSumTpl(std::shared_ptr<StateAbstract> state, const std::size_t nu);
101 
109  explicit CostModelSumTpl(std::shared_ptr<StateAbstract> state);
110  ~CostModelSumTpl();
111 
120  void addCost(const std::string& name, std::shared_ptr<CostModelAbstract> cost,
121  const Scalar weight, const bool active = true);
122 
128  void removeCost(const std::string& name);
129 
136  void changeCostStatus(const std::string& name, const bool active);
137 
145  void calc(const std::shared_ptr<CostDataSum>& data,
146  const Eigen::Ref<const VectorXs>& x,
147  const Eigen::Ref<const VectorXs>& u);
148 
159  void calc(const std::shared_ptr<CostDataSum>& data,
160  const Eigen::Ref<const VectorXs>& x);
161 
169  void calcDiff(const std::shared_ptr<CostDataSum>& data,
170  const Eigen::Ref<const VectorXs>& x,
171  const Eigen::Ref<const VectorXs>& u);
172 
185  void calcDiff(const std::shared_ptr<CostDataSum>& data,
186  const Eigen::Ref<const VectorXs>& x);
187 
199  std::shared_ptr<CostDataSum> createData(DataCollectorAbstract* const data);
200 
210  template <typename NewScalar>
212 
216  const std::shared_ptr<StateAbstract>& get_state() const;
217 
221  const CostModelContainer& get_costs() const;
222 
226  std::size_t get_nu() const;
227 
231  std::size_t get_nr() const;
232 
236  std::size_t get_nr_total() const;
237 
241  const std::set<std::string>& get_active_set() const;
242 
246  const std::set<std::string>& get_inactive_set() const;
247 
248  DEPRECATED(
249  "get_active() is deprecated and will be replaced with get_active_set()",
250  const std::vector<std::string>& get_active() {
251  active_.clear();
252  active_.reserve(active_set_.size());
253  for (const auto& contact : active_set_) {
254  active_.push_back(contact);
255  }
256  return active_;
257  };)
258 
259  DEPRECATED(
260  "get_inactive() is deprecated and will be replaced with "
261  "get_inactive_set()",
262  const std::vector<std::string>& get_inactive() {
263  inactive_.clear();
264  inactive_.reserve(inactive_set_.size());
265  for (const auto& contact : inactive_set_) {
266  inactive_.push_back(contact);
267  }
268  return inactive_;
269  };)
270 
276  bool getCostStatus(const std::string& name) const;
277 
281  template <class Scalar>
282  friend std::ostream& operator<<(std::ostream& os,
283  const CostModelSumTpl<Scalar>& model);
284 
285  private:
286  std::shared_ptr<StateAbstract> state_;
287  CostModelContainer costs_;
288  std::size_t nu_;
289  std::size_t nr_;
290  std::size_t nr_total_;
291  std::set<std::string> active_set_;
292  std::set<std::string>
293  inactive_set_;
294 
295  // Vector variants. These are to maintain the API compatibility for the
296  // deprecated syntax. These will be removed in future versions along with
297  // get_active() / get_inactive()
298  std::vector<std::string> active_;
299  std::vector<std::string> inactive_;
300 };
301 
302 template <typename _Scalar>
304  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
305 
306  typedef _Scalar Scalar;
310  typedef typename MathBase::VectorXs VectorXs;
311  typedef typename MathBase::MatrixXs MatrixXs;
312 
313  template <template <typename Scalar> class Model>
314  CostDataSumTpl(Model<Scalar>* const model, DataCollectorAbstract* const data)
315  : Lx_internal(model->get_state()->get_ndx()),
316  Lu_internal(model->get_nu()),
317  Lxx_internal(model->get_state()->get_ndx(),
318  model->get_state()->get_ndx()),
319  Lxu_internal(model->get_state()->get_ndx(), model->get_nu()),
320  Luu_internal(model->get_nu(), model->get_nu()),
321  shared(data),
322  cost(Scalar(0.)),
323  Lx(Lx_internal.data(), model->get_state()->get_ndx()),
324  Lu(Lu_internal.data(), model->get_nu()),
325  Lxx(Lxx_internal.data(), model->get_state()->get_ndx(),
326  model->get_state()->get_ndx()),
327  Lxu(Lxu_internal.data(), model->get_state()->get_ndx(),
328  model->get_nu()),
329  Luu(Luu_internal.data(), model->get_nu(), model->get_nu()) {
330  Lx.setZero();
331  Lu.setZero();
332  Lxx.setZero();
333  Lxu.setZero();
334  Luu.setZero();
336  it = model->get_costs().begin();
337  it != model->get_costs().end(); ++it) {
338  const std::shared_ptr<CostItem>& item = it->second;
339  costs.insert(std::make_pair(item->name, item->cost->createData(data)));
340  }
341  }
342 
343  template <class ActionData>
344  void shareMemory(ActionData* const data) {
345  // Save memory by setting the internal variables with null dimension
346  Lx_internal.resize(0);
347  Lu_internal.resize(0);
348  Lxx_internal.resize(0, 0);
349  Lxu_internal.resize(0, 0);
350  Luu_internal.resize(0, 0);
351  // Share memory with the differential action data
352  new (&Lx) Eigen::Map<VectorXs>(data->Lx.data(), data->Lx.size());
353  new (&Lu) Eigen::Map<VectorXs>(data->Lu.data(), data->Lu.size());
354  new (&Lxx) Eigen::Map<MatrixXs>(data->Lxx.data(), data->Lxx.rows(),
355  data->Lxx.cols());
356  new (&Lxu) Eigen::Map<MatrixXs>(data->Lxu.data(), data->Lxu.rows(),
357  data->Lxu.cols());
358  new (&Luu) Eigen::Map<MatrixXs>(data->Luu.data(), data->Luu.rows(),
359  data->Luu.cols());
360  }
361 
362  VectorXs get_Lx() const { return Lx; }
363  VectorXs get_Lu() const { return Lu; }
364  MatrixXs get_Lxx() const { return Lxx; }
365  MatrixXs get_Lxu() const { return Lxu; }
366  MatrixXs get_Luu() const { return Luu; }
367 
368  void set_Lx(const VectorXs& _Lx) {
369  if (Lx.size() != _Lx.size()) {
370  throw_pretty(
371  "Invalid argument: " << "Lx has wrong dimension (it should be " +
372  std::to_string(Lx.size()) + ")");
373  }
374  Lx = _Lx;
375  }
376  void set_Lu(const VectorXs& _Lu) {
377  if (Lu.size() != _Lu.size()) {
378  throw_pretty(
379  "Invalid argument: " << "Lu has wrong dimension (it should be " +
380  std::to_string(Lu.size()) + ")");
381  }
382  Lu = _Lu;
383  }
384  void set_Lxx(const MatrixXs& _Lxx) {
385  if (Lxx.rows() != _Lxx.rows() || Lxx.cols() != _Lxx.cols()) {
386  throw_pretty(
387  "Invalid argument: " << "Lxx has wrong dimension (it should be " +
388  std::to_string(Lxx.rows()) + ", " +
389  std::to_string(Lxx.cols()) + ")");
390  }
391  Lxx = _Lxx;
392  }
393  void set_Lxu(const MatrixXs& _Lxu) {
394  if (Lxu.rows() != _Lxu.rows() || Lxu.cols() != _Lxu.cols()) {
395  throw_pretty(
396  "Invalid argument: " << "Lxu has wrong dimension (it should be " +
397  std::to_string(Lxu.rows()) + ", " +
398  std::to_string(Lxu.cols()) + ")");
399  }
400  Lxu = _Lxu;
401  }
402  void set_Luu(const MatrixXs& _Luu) {
403  if (Luu.rows() != _Luu.rows() || Luu.cols() != _Luu.cols()) {
404  throw_pretty(
405  "Invalid argument: " << "Luu has wrong dimension (it should be " +
406  std::to_string(Luu.rows()) + ", " +
407  std::to_string(Luu.cols()) + ")");
408  }
409  Luu = _Luu;
410  }
411 
412  // Creates internal data in case we don't share it externally
413  VectorXs Lx_internal;
414  VectorXs Lu_internal;
415  MatrixXs Lxx_internal;
416  MatrixXs Lxu_internal;
417  MatrixXs Luu_internal;
418 
420  DataCollectorAbstract* shared;
421  Scalar cost;
422  Eigen::Map<VectorXs> Lx;
423  Eigen::Map<VectorXs> Lu;
424  Eigen::Map<MatrixXs> Lxx;
425  Eigen::Map<MatrixXs> Lxu;
426  Eigen::Map<MatrixXs> Luu;
427 };
428 
429 } // namespace crocoddyl
430 
431 /* --- Details -------------------------------------------------------------- */
432 /* --- Details -------------------------------------------------------------- */
433 /* --- Details -------------------------------------------------------------- */
434 #include "crocoddyl/core/costs/cost-sum.hxx"
435 
436 CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(crocoddyl::CostItemTpl)
437 CROCODDYL_DECLARE_EXTERN_TEMPLATE_CLASS(crocoddyl::CostModelSumTpl)
438 CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(crocoddyl::CostDataSumTpl)
439 
440 #endif // CROCODDYL_CORE_COSTS_COST_SUM_HPP_
Abstract class for cost models.
Definition: cost-base.hpp:64
Summation of individual cost models.
Definition: cost-sum.hpp:75
void calcDiff(const std::shared_ptr< CostDataSum > &data, const Eigen::Ref< const VectorXs > &x)
Compute the Jacobian and Hessian of the total cost for nodes that depends on the state only.
void removeCost(const std::string &name)
Remove a cost item.
void addCost(const std::string &name, std::shared_ptr< CostModelAbstract > cost, const Scalar weight, const bool active=true)
Add a cost item.
std::shared_ptr< CostDataSum > createData(DataCollectorAbstract *const data)
Create the cost data.
void calc(const std::shared_ptr< CostDataSum > &data, const Eigen::Ref< const VectorXs > &x)
Compute the total cost value for nodes that depends only on the state.
void calc(const std::shared_ptr< CostDataSum > &data, const Eigen::Ref< const VectorXs > &x, const Eigen::Ref< const VectorXs > &u)
Compute the total cost value.
void changeCostStatus(const std::string &name, const bool active)
Change the cost status.
CostModelSumTpl(std::shared_ptr< StateAbstract > state)
Initialize the cost-sum model.
CostModelSumTpl(std::shared_ptr< StateAbstract > state, const std::size_t nu)
Initialize the cost-sum model.
void calcDiff(const std::shared_ptr< CostDataSum > &data, const Eigen::Ref< const VectorXs > &x, const Eigen::Ref< const VectorXs > &u)
Compute the Jacobian and Hessian of the total cost.
friend std::ostream & operator<<(std::ostream &os, const CostModelSumTpl< Scalar > &model)
Print information on the stack of costs.
std::size_t get_nr_total() const
Return the dimension of the total residual vector.
CostModelSumTpl< NewScalar > cast() const
Cast the cost-sum model to a different scalar type.
const std::set< std::string > & get_inactive_set() const
Return the names of the set of inactive costs.
const std::shared_ptr< StateAbstract > & get_state() const
Return the state.
const std::set< std::string > & get_active_set() const
Return the names of the set of active costs.
std::size_t get_nr() const
Return the dimension of the active residual vector.
const CostModelContainer & get_costs() const
Return the stack of cost models.
bool getCostStatus(const std::string &name) const
Return the status of a given cost name.
std::size_t get_nu() const
Return the dimension of the control input.
Abstract class for the state representation.
Definition: state-base.hpp:48
friend std::ostream & operator<<(std::ostream &os, const CostItemTpl< Scalar > &model)
Print information on the cost item.
Definition: cost-sum.hpp:41