GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/activations/2norm-barrier.hpp
Date: 2025-03-26 19:23:43
Exec Total Coverage
Lines: 33 46 71.7%
Branches: 10 91 11.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2021-2025, LAAS-CNRS, Airbus, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifndef CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
11 #define CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
12
13 #include <pinocchio/utils/static-if.hpp>
14 #include <stdexcept>
15
16 #include "crocoddyl/core/activation-base.hpp"
17 #include "crocoddyl/core/fwd.hpp"
18
19 namespace crocoddyl {
20
21 /**
22 * @brief 2-norm barrier activation
23 *
24 * This activation function describes a quadratic barrier of the 2-norm of a
25 * residual vector, i.e.,
26 * \f[
27 * \Bigg\{\begin{aligned}
28 * &\frac{1}{2} (d - \alpha)^2, &\textrm{if} \,\,\, d < \alpha \\
29 * &0, &\textrm{otherwise},
30 * \end{aligned}
31 * \f]
32 * where \f$d = \|r\|\f$ is the norm of the residual, \f$\alpha\f$ the threshold
33 * distance from which the barrier is active, \f$nr\f$ is the dimension of the
34 * residual vector.
35 *
36 * The computation of the function and it derivatives are carried out in
37 * `calc()` and `calcDiff()`, respectively.
38 *
39 * \sa `ActivationModelAbstractTpl`, `calc()`, `calcDiff()`, `createData()`
40 */
41 template <typename _Scalar>
42 class ActivationModel2NormBarrierTpl
43 : public ActivationModelAbstractTpl<_Scalar> {
44 public:
45 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
46 16 CROCODDYL_DERIVED_CAST(ActivationModelBase, ActivationModel2NormBarrierTpl)
47
48 typedef _Scalar Scalar;
49 typedef MathBaseTpl<Scalar> MathBase;
50 typedef ActivationModelAbstractTpl<Scalar> Base;
51 typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
52 typedef ActivationData2NormBarrierTpl<Scalar> Data;
53 typedef typename MathBase::VectorXs VectorXs;
54
55 /**
56 * @brief Initialize the 2-norm barrier activation model
57 *
58 * The default `alpha` value is defined as 0.1.
59 *
60 * @param[in] nr Dimension of the residual vector
61 * @param[in] alpha Threshold factor (default 0.1)
62 * @param[in] true_hessian Boolean indicating whether to use the Gauss-Newton
63 * approximation or true Hessian in computing the derivatives (default: false)
64 */
65 189 explicit ActivationModel2NormBarrierTpl(const std::size_t nr,
66 const Scalar alpha = Scalar(0.1),
67 const bool true_hessian = false)
68 189 : Base(nr), alpha_(alpha), true_hessian_(true_hessian) {
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 189 times.
189 if (alpha < Scalar(0.)) {
70 throw_pretty("Invalid argument: " << "alpha should be a positive value");
71 }
72 189 };
73 390 virtual ~ActivationModel2NormBarrierTpl() = default;
74
75 /**
76 * @brief Compute the 2-norm barrier function
77 *
78 * @param[in] data 2-norm barrier activation data
79 * @param[in] r Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
80 */
81 3797 virtual void calc(const std::shared_ptr<ActivationDataAbstract>& data,
82 const Eigen::Ref<const VectorXs>& r) override {
83
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3797 times.
3797 if (static_cast<std::size_t>(r.size()) != nr_) {
84 throw_pretty(
85 "Invalid argument: " << "r has wrong dimension (it should be " +
86 std::to_string(nr_) + ")");
87 }
88 3797 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
89
90
1/2
✓ Branch 1 taken 3797 times.
✗ Branch 2 not taken.
3797 d->d = r.norm();
91
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3796 times.
3797 if (d->d < alpha_) {
92 1 data->a_value = Scalar(0.5) * (d->d - alpha_) * (d->d - alpha_);
93 } else {
94 3796 data->a_value = Scalar(0.0);
95 }
96 3797 };
97
98 /**
99 * @brief Compute the derivatives of the 2norm-barrier function
100 *
101 * @param[in] data 2-norm barrier activation data
102 * @param[in] r Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
103 */
104 213 virtual void calcDiff(const std::shared_ptr<ActivationDataAbstract>& data,
105 const Eigen::Ref<const VectorXs>& r) override {
106
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
213 if (static_cast<std::size_t>(r.size()) != nr_) {
107 throw_pretty(
108 "Invalid argument: " << "r has wrong dimension (it should be " +
109 std::to_string(nr_) + ")");
110 }
111 213 std::shared_ptr<Data> d = std::static_pointer_cast<Data>(data);
112
113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
213 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() / pow(d->d, Scalar(3)); // True Hessian
118 data->Arr.diagonal().array() += (d->d - alpha_) / d->d;
119 } else {
120 data->Arr.diagonal() =
121 r.array().square() /
122 pow(d->d, Scalar(2)); // GN Hessian approximation
123 }
124 } else {
125
1/2
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
213 data->Ar.setZero();
126
1/2
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
213 data->Arr.setZero();
127 }
128 213 };
129
130 /**
131 * @brief Create the 2norm-barrier activation data
132 *
133 * @return the activation data
134 */
135 4682 virtual std::shared_ptr<ActivationDataAbstract> createData() override {
136
1/2
✓ Branch 2 taken 4682 times.
✗ Branch 3 not taken.
4682 return std::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
137 };
138
139 template <typename NewScalar>
140 4 ActivationModel2NormBarrierTpl<NewScalar> cast() const {
141 typedef ActivationModel2NormBarrierTpl<NewScalar> ReturnType;
142 4 ReturnType res(nr_, scalar_cast<NewScalar>(alpha_), true_hessian_);
143 4 return res;
144 }
145
146 /**
147 * @brief Get and set the threshold factor
148 */
149 const Scalar& get_alpha() const { return alpha_; };
150 void set_alpha(const Scalar& alpha) { alpha_ = alpha; };
151
152 /**
153 * @brief Print relevant information of the 2-norm barrier model
154 *
155 * @param[out] os Output stream object
156 */
157 37 virtual void print(std::ostream& os) const override {
158 37 os << "ActivationModel2NormBarrier {nr=" << nr_ << ", alpha=" << alpha_
159 37 << ", Hessian=" << true_hessian_ << "}";
160 37 }
161
162 protected:
163 using Base::nr_; //!< Dimension of the residual vector
164 Scalar alpha_; //!< Threshold factor
165 bool true_hessian_; //!< Use true Hessian in calcDiff if true, Gauss-Newton
166 //!< approximation if false
167 };
168
169 template <typename _Scalar>
170 struct ActivationData2NormBarrierTpl
171 : public ActivationDataAbstractTpl<_Scalar> {
172 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
173
174 typedef _Scalar Scalar;
175 typedef MathBaseTpl<Scalar> MathBase;
176 typedef typename MathBase::VectorXs VectorXs;
177 typedef typename MathBase::DiagonalMatrixXs DiagonalMatrixXs;
178 typedef ActivationDataAbstractTpl<Scalar> Base;
179
180 template <typename Activation>
181 4682 explicit ActivationData2NormBarrierTpl(Activation* const activation)
182 4682 : Base(activation), d(Scalar(0)) {}
183 9364 virtual ~ActivationData2NormBarrierTpl() = default;
184
185 Scalar d; //!< Norm of the residual
186
187 using Base::a_value;
188 using Base::Ar;
189 using Base::Arr;
190 };
191
192 } // namespace crocoddyl
193
194 CROCODDYL_DECLARE_EXTERN_TEMPLATE_CLASS(
195 crocoddyl::ActivationModel2NormBarrierTpl)
196 CROCODDYL_DECLARE_EXTERN_TEMPLATE_STRUCT(
197 crocoddyl::ActivationData2NormBarrierTpl)
198
199 #endif // CROCODDYL_CORE_ACTIVATIONS_2NORM_BARRIER_HPP_
200