Crocoddyl
Loading...
Searching...
No Matches
quadratic-barrier.hpp
1
2// BSD 3-Clause License
3//
4// Copyright (C) 2019-2026, LAAS-CNRS, University of Edinburgh,
5// University of Oxford, Heriot-Watt University
6// Copyright note valid unless otherwise stated in individual files. All
7// rights reserved.
9
10#ifndef CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_
11#define CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_
12
13#include "crocoddyl/core/activation-base.hpp"
14#include "crocoddyl/core/fwd.hpp"
15#include "crocoddyl/core/utils/conversions.hpp"
16
17namespace crocoddyl {
18
19template <typename _Scalar>
20struct ActivationBoundsTpl {
21 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
22
23 typedef _Scalar Scalar;
24 typedef MathBaseTpl<Scalar> MathBase;
25 typedef typename MathBase::VectorXs VectorXs;
26 typedef typename MathBase::MatrixXs MatrixXs;
27
28 ActivationBoundsTpl(const VectorXs& lower, const VectorXs& upper,
29 const Scalar b = Scalar(1.))
30 : lb(lower), ub(upper), beta(b) {
31 if (lb.size() != ub.size()) {
32 throw_pretty("Invalid argument: "
33 << "The lower and upper bounds don't have the same "
34 "dimension (lb,ub dimensions equal to " +
35 std::to_string(lb.size()) + "," +
36 std::to_string(ub.size()) + ", respectively)");
37 }
38 if (beta < Scalar(0) || beta > Scalar(1.)) {
39 throw_pretty(
40 "Invalid argument: " << "The range of beta is between 0 and 1");
41 }
42 for (std::size_t i = 0; i < static_cast<std::size_t>(lb.size()); ++i) {
43 if (isfinite(lb(i)) && isfinite(ub(i))) {
44 if (lb(i) - ub(i) > Scalar(0)) {
45 throw_pretty("Invalid argument: "
46 << "The lower and upper bounds are badly defined; ub "
47 "has to be bigger / equals to lb");
48 }
49 }
50 // Assign the maximum value for infinity/nan values
51 if (!isfinite(lb(i))) {
52 lb(i) = -std::numeric_limits<Scalar>::max();
53 }
54 if (!isfinite(ub(i))) {
55 ub(i) = std::numeric_limits<Scalar>::max();
56 }
57 }
58
59 if (beta >= Scalar(0) && beta <= Scalar(1.)) {
60 for (std::size_t i = 0; i < static_cast<std::size_t>(lb.size()); ++i) {
61 // do not use beta when one of the bounds is inf
62 if (lb(i) != (-std::numeric_limits<Scalar>::max()) &&
63 ub(i) != (std::numeric_limits<Scalar>::max())) {
64 Scalar m = Scalar(0.5) * (lb(i) + ub(i));
65 Scalar d = Scalar(0.5) * (ub(i) - lb(i));
66 lb(i) = m - beta * d;
67 ub(i) = m + beta * d;
68 }
69 }
70 } else {
71 beta = Scalar(1.);
72 }
73 }
74 ActivationBoundsTpl(const ActivationBoundsTpl& other)
75 : lb(other.lb), ub(other.ub), beta(other.beta) {}
76 ActivationBoundsTpl() : beta(Scalar(1.)) {}
77
78 template <typename NewScalar>
79 ActivationBoundsTpl<NewScalar> cast() const {
80 typedef ActivationBoundsTpl<NewScalar> ReturnType;
81 ReturnType res(lb.template cast<NewScalar>(), ub.template cast<NewScalar>(),
82 scalar_cast<NewScalar>(beta));
83 return res;
84 }
85
86 ActivationBoundsTpl& operator=(const ActivationBoundsTpl& other) {
87 if (this != &other) {
88 lb = other.lb;
89 ub = other.ub;
90 beta = other.beta;
91 }
92 return *this;
93 }
94
98 friend std::ostream& operator<<(std::ostream& os,
99 const ActivationBoundsTpl& bounds) {
100 bounds.print(os);
101 return os;
102 }
103
104 void print(std::ostream& os) const {
105 typedef typename ScalarSelector<Scalar>::type PrintableScalar;
106 os << "ActivationBounds {lb="
107 << lb.template cast<PrintableScalar>().transpose()
108 << ", ub=" << ub.template cast<PrintableScalar>().transpose()
109 << ", beta=" << scalar_cast<PrintableScalar>(beta) << "}";
110 }
111
112 VectorXs lb;
113 VectorXs ub;
114 Scalar beta;
115};
116
117template <typename _Scalar>
118class ActivationModelQuadraticBarrierTpl
119 : public ActivationModelAbstractTpl<_Scalar> {
120 public:
121 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
122 CROCODDYL_DERIVED_CAST(ActivationModelBase,
123 ActivationModelQuadraticBarrierTpl)
124
125 typedef _Scalar Scalar;
126 typedef MathBaseTpl<Scalar> MathBase;
127 typedef ActivationModelAbstractTpl<Scalar> Base;
128 typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
130 typedef ActivationBoundsTpl<Scalar> ActivationBounds;
131 typedef typename MathBase::VectorXs VectorXs;
132 typedef typename MathBase::MatrixXs MatrixXs;
133
134 explicit ActivationModelQuadraticBarrierTpl(const ActivationBounds& bounds)
135 : Base(bounds.lb.size()), bounds_(bounds) {};
136 virtual ~ActivationModelQuadraticBarrierTpl() = default;
137
138 virtual void calc(const std::shared_ptr<ActivationDataAbstract>& data,
139 const Eigen::Ref<const VectorXs>& r) override {
140 if (static_cast<std::size_t>(r.size()) != nr_) {
141 throw_pretty(
142 "Invalid argument: " << "r has wrong dimension (it should be " +
143 std::to_string(nr_) + ")");
144 }
145
146 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
147
148 d->rlb_min = (r - bounds_.lb).array().min(Scalar(0.));
149 d->rub_max = (r - bounds_.ub).array().max(Scalar(0.));
150 data->a_value = Scalar(0.5) * d->rlb_min.matrix().squaredNorm() +
151 Scalar(0.5) * d->rub_max.matrix().squaredNorm();
152 };
153
154 virtual void calcDiff(const std::shared_ptr<ActivationDataAbstract>& data,
155 const Eigen::Ref<const VectorXs>& r) override {
156 if (static_cast<std::size_t>(r.size()) != nr_) {
157 throw_pretty(
158 "Invalid argument: " << "r has wrong dimension (it should be " +
159 std::to_string(nr_) + ")");
160 }
161
162 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
163 data->Ar = (d->rlb_min + d->rub_max).matrix();
164
165 using pinocchio::internal::if_then_else;
166 for (Eigen::Index i = 0; i < data->Arr.cols(); i++) {
167 data->Arr.diagonal()[i] = if_then_else(
168 pinocchio::internal::LE, r[i] - bounds_.lb[i], Scalar(0.), Scalar(1.),
169 if_then_else(pinocchio::internal::GE, r[i] - bounds_.ub[i],
170 Scalar(0.), Scalar(1.), Scalar(0.)));
171 }
172 };
173
174 virtual std::shared_ptr<ActivationDataAbstract> createData() override {
175 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
176 };
177
178 template <typename NewScalar>
179 ActivationModelQuadraticBarrierTpl<NewScalar> cast() const {
180 typedef ActivationModelQuadraticBarrierTpl<NewScalar> ReturnType;
181 ReturnType res(bounds_.template cast<NewScalar>());
182 return res;
183 }
184
185 const ActivationBounds& get_bounds() const { return bounds_; };
186 void set_bounds(const ActivationBounds& bounds) { bounds_ = bounds; };
187
193 virtual void print(std::ostream& os) const override {
194 os << "ActivationModelQuadraticBarrier {nr=" << nr_ << "}";
195 }
196
197 protected:
198 using Base::nr_;
199
200 private:
201 ActivationBounds bounds_;
202};
203
204template <typename _Scalar>
205struct ActivationDataQuadraticBarrierTpl
206 : public ActivationDataAbstractTpl<_Scalar> {
207 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
208
209 typedef _Scalar Scalar;
210 typedef MathBaseTpl<Scalar> MathBase;
211 typedef typename MathBase::ArrayXs ArrayXs;
212 typedef typename MathBase::VectorXs VectorXs;
213 typedef typename MathBase::DiagonalMatrixXs DiagonalMatrixXs;
214 typedef ActivationDataAbstractTpl<Scalar> Base;
215
216 template <typename Activation>
217 explicit ActivationDataQuadraticBarrierTpl(Activation* const activation)
218 : Base(activation),
219 rlb_min(activation->get_nr()),
220 rub_max(activation->get_nr()) {
221 rlb_min.setZero();
222 rub_max.setZero();
223 }
224
225 ArrayXs rlb_min;
226 ArrayXs rub_max;
227
228 using Base::a_value;
229 using Base::Ar;
230 using Base::Arr;
231};
232
233} // namespace crocoddyl
234
235CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(crocoddyl::ActivationBoundsTpl)
236CROCODDYL_DECLARE_EXTERN_TEMPLATE_CLASS(
238CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(
240
241#endif // CROCODDYL_CORE_ACTIVATIONS_QUADRATIC_BARRIER_HPP_
virtual void print(std::ostream &os) const override
Print relevant information of the quadratic barrier model.
friend std::ostream & operator<<(std::ostream &os, const ActivationBoundsTpl &bounds)
Print information on the activation bounds.