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 <pinocchio/utils/static-if.hpp>
13 #include <stdexcept>
14 
15 #include "crocoddyl/core/activation-base.hpp"
16 #include "crocoddyl/core/fwd.hpp"
17 #include "crocoddyl/core/utils/exception.hpp"
18 
19 namespace crocoddyl {
20 
41 template <typename _Scalar>
43  : public ActivationModelAbstractTpl<_Scalar> {
44  public:
45  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
46 
47  typedef _Scalar Scalar;
52  typedef typename MathBase::VectorXs VectorXs;
53 
64  explicit ActivationModel2NormBarrierTpl(const std::size_t nr,
65  const Scalar alpha = Scalar(0.1),
66  const bool true_hessian = false)
67  : Base(nr), alpha_(alpha), true_hessian_(true_hessian) {
68  if (alpha < Scalar(0.)) {
69  throw_pretty("Invalid argument: "
70  << "alpha should be a positive value");
71  }
72  };
73  virtual ~ActivationModel2NormBarrierTpl(){};
74 
81  virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data,
82  const Eigen::Ref<const VectorXs>& r) {
83  if (static_cast<std::size_t>(r.size()) != nr_) {
84  throw_pretty("Invalid argument: "
85  << "r has wrong dimension (it should be " +
86  std::to_string(nr_) + ")");
87  }
88  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
89 
90  d->d = r.norm();
91  if (d->d < alpha_) {
92  data->a_value = Scalar(0.5) * (d->d - alpha_) * (d->d - alpha_);
93  } else {
94  data->a_value = Scalar(0.0);
95  }
96  };
97 
104  virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data,
105  const Eigen::Ref<const VectorXs>& r) {
106  if (static_cast<std::size_t>(r.size()) != nr_) {
107  throw_pretty("Invalid argument: "
108  << "r has wrong dimension (it should be " +
109  std::to_string(nr_) + ")");
110  }
111  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
112 
113  if (d->d < alpha_) {
114  data->Ar = (d->d - alpha_) / d->d * r;
115  if (true_hessian_) {
116  data->Arr.diagonal() =
117  alpha_ * r.array().square() / std::pow(d->d, 3); // True Hessian
118  data->Arr.diagonal().array() += (d->d - alpha_) / d->d;
119  } else {
120  data->Arr.diagonal() =
121  r.array().square() / std::pow(d->d, 2); // GN Hessian approximation
122  }
123  } else {
124  data->Ar.setZero();
125  data->Arr.setZero();
126  }
127  };
128 
134  virtual boost::shared_ptr<ActivationDataAbstract> createData() {
135  return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
136  };
137 
141  const Scalar& get_alpha() const { return alpha_; };
142  void set_alpha(const Scalar& alpha) { alpha_ = alpha; };
143 
149  virtual void print(std::ostream& os) const {
150  os << "ActivationModel2NormBarrier {nr=" << nr_ << ", alpha=" << alpha_
151  << ", Hessian=" << true_hessian_ << "}";
152  }
153 
154  protected:
155  using Base::nr_;
156  Scalar alpha_;
159 };
160 
161 template <typename _Scalar>
163  : public ActivationDataAbstractTpl<_Scalar> {
164  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
165 
166  typedef _Scalar Scalar;
168 
169  template <typename Activation>
170  explicit ActivationData2NormBarrierTpl(Activation* const activation)
171  : Base(activation), d(Scalar(0)) {}
172 
173  Scalar d;
174 
175  using Base::a_value;
176  using Base::Ar;
177  using Base::Arr;
178 };
179 
180 } // namespace crocoddyl
181 
182 #endif // CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
virtual boost::shared_ptr< ActivationDataAbstract > createData()
Create the 2norm-barrier activation data.
Scalar alpha_
< Dimension of the residual vector
virtual void calc(const boost::shared_ptr< ActivationDataAbstract > &data, const Eigen::Ref< const VectorXs > &r)
Compute the 2-norm barrier function.
virtual void print(std::ostream &os) const
Print relevant information of the 2-norm barrier model.
ActivationModel2NormBarrierTpl(const std::size_t nr, const Scalar alpha=Scalar(0.1), const bool true_hessian=false)
Initialize the 2-norm barrier activation model.
virtual void calcDiff(const boost::shared_ptr< ActivationDataAbstract > &data, const Eigen::Ref< const VectorXs > &r)
Compute the derivatives of the 2norm-barrier function.
const Scalar & get_alpha() const
Get and set the threshold factor.