crocoddyl  1.8.0
Contact RObot COntrol by Differential DYnamic programming Library (Crocoddyl)
2norm-barrier.hpp
1 // BSD 3-Clause License
3 //
4 // Copyright (C) 2021, LAAS-CNRS, Airbus, University of Edinburgh
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
8 
9 #ifndef CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
10 #define CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
11 
12 #include <stdexcept>
13 #include <pinocchio/utils/static-if.hpp>
14 #include "crocoddyl/core/fwd.hpp"
15 #include "crocoddyl/core/activation-base.hpp"
16 #include "crocoddyl/core/utils/exception.hpp"
17 
18 namespace crocoddyl {
19 
33 template <typename _Scalar>
34 class ActivationModel2NormBarrierTpl : public ActivationModelAbstractTpl<_Scalar> {
35  public:
36  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
37 
38  typedef _Scalar Scalar;
39  typedef MathBaseTpl<Scalar> MathBase;
40  typedef ActivationModelAbstractTpl<Scalar> Base;
41  typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
42  typedef ActivationData2NormBarrierTpl<Scalar> Data;
43  typedef typename MathBase::VectorXs VectorXs;
44 
55  explicit ActivationModel2NormBarrierTpl(const std::size_t nr, const Scalar alpha = Scalar(0.1),
56  const bool true_hessian = false)
57  : Base(nr), alpha_(alpha), true_hessian_(true_hessian) {
58  if (alpha < Scalar(0.)) {
59  throw_pretty("Invalid argument: "
60  << "alpha should be a positive value");
61  }
62  };
63  virtual ~ActivationModel2NormBarrierTpl(){};
64 
71  virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data, const Eigen::Ref<const VectorXs>& r) {
72  if (static_cast<std::size_t>(r.size()) != nr_) {
73  throw_pretty("Invalid argument: "
74  << "r has wrong dimension (it should be " + std::to_string(nr_) + ")");
75  }
76  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
77 
78  d->d = r.norm();
79  if (d->d < alpha_) {
80  data->a_value = Scalar(0.5) * (d->d - alpha_) * (d->d - alpha_);
81  } else {
82  data->a_value = Scalar(0.0);
83  }
84  };
85 
92  virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data, const Eigen::Ref<const VectorXs>& r) {
93  if (static_cast<std::size_t>(r.size()) != nr_) {
94  throw_pretty("Invalid argument: "
95  << "r has wrong dimension (it should be " + std::to_string(nr_) + ")");
96  }
97  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
98 
99  if (d->d < alpha_) {
100  data->Ar = (d->d - alpha_) / d->d * r;
101  if (true_hessian_) {
102  data->Arr.diagonal() = alpha_ * r.array().square() / std::pow(d->d, 3); // True Hessian
103  data->Arr.diagonal().array() += (d->d - alpha_) / d->d;
104  } else {
105  data->Arr.diagonal() = r.array().square() / std::pow(d->d, 2); // GN Hessian approximation
106  }
107  } else {
108  data->Ar.setZero();
109  data->Arr.setZero();
110  }
111  };
112 
118  virtual boost::shared_ptr<ActivationDataAbstract> createData() {
119  return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
120  };
121 
126  const Scalar& get_alpha() const { return alpha_; };
127  void set_alpha(const Scalar& alpha) { alpha_ = alpha; };
128 
134  virtual void print(std::ostream& os) const {
135  os << "ActivationModel2NormBarrier {nr=" << nr_ << ", alpha=" << alpha_ << ", hessian=" << true_hessian_ << "}";
136  }
137 
138  protected:
139  using Base::nr_;
140  Scalar alpha_;
141  bool true_hessian_;
142 };
143 
144 template <typename _Scalar>
145 struct ActivationData2NormBarrierTpl : public ActivationDataAbstractTpl<_Scalar> {
146  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
147 
148  typedef _Scalar Scalar;
149  typedef ActivationDataAbstractTpl<Scalar> Base;
150 
151  template <typename Activation>
152  explicit ActivationData2NormBarrierTpl(Activation* const activation) : Base(activation), d(Scalar(0)) {}
153 
154  Scalar d;
155 
156  using Base::a_value;
157  using Base::Ar;
158  using Base::Arr;
159 };
160 
161 } // namespace crocoddyl
162 
163 #endif // CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_