crocoddyl  1.7.0
Contact RObot COntrol by Differential DYnamic programming Library (Crocoddyl)
quadratic-barrier.hpp
1 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2021, LAAS-CNRS, University of Edinburgh, University of Oxford
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
8 
9 #ifndef CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_
10 #define CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_
11 
12 #include <stdexcept>
13 #include <math.h>
14 
15 #include "crocoddyl/core/fwd.hpp"
16 #include "crocoddyl/core/utils/exception.hpp"
17 #include "crocoddyl/core/activation-base.hpp"
18 
19 #include <pinocchio/utils/static-if.hpp>
20 
21 namespace crocoddyl {
22 
23 template <typename _Scalar>
25  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
26 
27  typedef _Scalar Scalar;
29  typedef typename MathBase::VectorXs VectorXs;
30  typedef typename MathBase::MatrixXs MatrixXs;
31 
32  ActivationBoundsTpl(const VectorXs& lower, const VectorXs& upper, const Scalar b = (Scalar)1.)
33  : lb(lower), ub(upper), beta(b) {
34  if (lb.size() != ub.size()) {
35  throw_pretty("Invalid argument: "
36  << "The lower and upper bounds don't have the same dimension (lb,ub dimensions equal to " +
37  std::to_string(lb.size()) + "," + std::to_string(ub.size()) + ", respectively)");
38  }
39  if (beta < Scalar(0) || beta > Scalar(1.)) {
40  throw_pretty("Invalid argument: "
41  << "The range of beta is between 0 and 1");
42  }
43  using std::isfinite;
44  for (std::size_t i = 0; i < static_cast<std::size_t>(lb.size()); ++i) {
45  if (isfinite(lb(i)) && isfinite(ub(i))) {
46  if (lb(i) - ub(i) > 0) {
47  throw_pretty("Invalid argument: "
48  << "The lower and upper bounds are badly defined; ub has to be bigger / equals to lb");
49  }
50  }
51  }
52 
53  if (beta >= Scalar(0) && beta <= Scalar(1.)) {
54  VectorXs m = Scalar(0.5) * (lower + upper);
55  VectorXs d = Scalar(0.5) * (upper - lower);
56  lb = m - beta * d;
57  ub = m + beta * d;
58  } else {
59  beta = Scalar(1.);
60  }
61  }
62  ActivationBoundsTpl(const ActivationBoundsTpl& other) : lb(other.lb), ub(other.ub), beta(other.beta) {}
63  ActivationBoundsTpl() : beta(Scalar(1.)) {}
64 
65  ActivationBoundsTpl& operator=(const ActivationBoundsTpl& other) {
66  if (this != &other) {
67  lb = other.lb;
68  ub = other.ub;
69  beta = other.beta;
70  }
71  return *this;
72  }
73 
74  VectorXs lb;
75  VectorXs ub;
76  Scalar beta;
77 };
78 
79 template <typename _Scalar>
81  public:
82  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
83 
84  typedef _Scalar Scalar;
90  typedef typename MathBase::VectorXs VectorXs;
91  typedef typename MathBase::MatrixXs MatrixXs;
92 
93  explicit ActivationModelQuadraticBarrierTpl(const ActivationBounds& bounds)
94  : Base(bounds.lb.size()), bounds_(bounds){};
96 
97  virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data, const Eigen::Ref<const VectorXs>& r) {
98  if (static_cast<std::size_t>(r.size()) != nr_) {
99  throw_pretty("Invalid argument: "
100  << "r has wrong dimension (it should be " + std::to_string(nr_) + ")");
101  }
102 
103  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
104 
105  d->rlb_min_ = (r - bounds_.lb).array().min(Scalar(0.));
106  d->rub_max_ = (r - bounds_.ub).array().max(Scalar(0.));
107  data->a_value =
108  Scalar(0.5) * d->rlb_min_.matrix().squaredNorm() + Scalar(0.5) * d->rub_max_.matrix().squaredNorm();
109  };
110 
111  virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data, const Eigen::Ref<const VectorXs>& r) {
112  if (static_cast<std::size_t>(r.size()) != nr_) {
113  throw_pretty("Invalid argument: "
114  << "r has wrong dimension (it should be " + std::to_string(nr_) + ")");
115  }
116 
117  boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
118  data->Ar = (d->rlb_min_ + d->rub_max_).matrix();
119 
120  using pinocchio::internal::if_then_else;
121  for (Eigen::Index i = 0; i < data->Arr.cols(); i++) {
122  data->Arr.diagonal()[i] = if_then_else(
123  pinocchio::internal::LE, r[i] - bounds_.lb[i], Scalar(0.), Scalar(1.),
124  if_then_else(pinocchio::internal::GE, r[i] - bounds_.ub[i], Scalar(0.), Scalar(1.), Scalar(0.)));
125  }
126  };
127 
128  virtual boost::shared_ptr<ActivationDataAbstract> createData() {
129  return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
130  };
131 
132  const ActivationBounds& get_bounds() const { return bounds_; };
133  void set_bounds(const ActivationBounds& bounds) { bounds_ = bounds; };
134 
135  protected:
136  using Base::nr_;
137 
138  private:
139  ActivationBounds bounds_;
140 };
141 
142 template <typename _Scalar>
144  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
145 
146  typedef _Scalar Scalar;
148  typedef typename MathBase::ArrayXs ArrayXs;
150 
151  template <typename Activation>
152  explicit ActivationDataQuadraticBarrierTpl(Activation* const activation)
153  : Base(activation), rlb_min_(activation->get_nr()), rub_max_(activation->get_nr()) {
154  rlb_min_.setZero();
155  rub_max_.setZero();
156  }
157 
158  ArrayXs rlb_min_;
159  ArrayXs rub_max_;
160  using Base::a_value;
161  using Base::Ar;
162  using Base::Arr;
163 };
164 
165 } // namespace crocoddyl
166 
167 #endif // CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_