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: " << "alpha should be a positive value");
70  }
71  };
72  virtual ~ActivationModel2NormBarrierTpl() {};
73 
80  virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data,
81  const Eigen::Ref<const VectorXs>& r) {
82  if (static_cast<std::size_t>(r.size()) != nr_) {
83  throw_pretty(
84  "Invalid argument: " << "r has wrong dimension (it should be " +
85  std::to_string(nr_) + ")");
86  }
87  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
88 
89  d->d = r.norm();
90  if (d->d < alpha_) {
91  data->a_value = Scalar(0.5) * (d->d - alpha_) * (d->d - alpha_);
92  } else {
93  data->a_value = Scalar(0.0);
94  }
95  };
96 
103  virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data,
104  const Eigen::Ref<const VectorXs>& r) {
105  if (static_cast<std::size_t>(r.size()) != nr_) {
106  throw_pretty(
107  "Invalid argument: " << "r has wrong dimension (it should be " +
108  std::to_string(nr_) + ")");
109  }
110  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
111 
112  if (d->d < alpha_) {
113  data->Ar = (d->d - alpha_) / d->d * r;
114  if (true_hessian_) {
115  data->Arr.diagonal() =
116  alpha_ * r.array().square() / std::pow(d->d, 3); // True Hessian
117  data->Arr.diagonal().array() += (d->d - alpha_) / d->d;
118  } else {
119  data->Arr.diagonal() =
120  r.array().square() / std::pow(d->d, 2); // GN Hessian approximation
121  }
122  } else {
123  data->Ar.setZero();
124  data->Arr.setZero();
125  }
126  };
127 
133  virtual boost::shared_ptr<ActivationDataAbstract> createData() {
134  return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
135  };
136 
140  const Scalar& get_alpha() const { return alpha_; };
141  void set_alpha(const Scalar& alpha) { alpha_ = alpha; };
142 
148  virtual void print(std::ostream& os) const {
149  os << "ActivationModel2NormBarrier {nr=" << nr_ << ", alpha=" << alpha_
150  << ", Hessian=" << true_hessian_ << "}";
151  }
152 
153  protected:
154  using Base::nr_;
155  Scalar alpha_;
158 };
159 
160 template <typename _Scalar>
162  : public ActivationDataAbstractTpl<_Scalar> {
163  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
164 
165  typedef _Scalar Scalar;
167 
168  template <typename Activation>
169  explicit ActivationData2NormBarrierTpl(Activation* const activation)
170  : Base(activation), d(Scalar(0)) {}
171 
172  Scalar d;
173 
174  using Base::a_value;
175  using Base::Ar;
176  using Base::Arr;
177 };
178 
179 } // namespace crocoddyl
180 
181 #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.