GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/activations/2norm-barrier.hpp
Date: 2025-01-16 08:47:40
Exec Total Coverage
Lines: 32 40 80.0%
Branches: 18 88 20.5%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // 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.
7 ///////////////////////////////////////////////////////////////////////////////
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
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
47 typedef _Scalar Scalar;
48 typedef MathBaseTpl<Scalar> MathBase;
49 typedef ActivationModelAbstractTpl<Scalar> Base;
50 typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
51 typedef ActivationData2NormBarrierTpl<Scalar> Data;
52 typedef typename MathBase::VectorXs VectorXs;
53
54 /**
55 * @brief Initialize the 2-norm barrier activation model
56 *
57 * The default `alpha` value is defined as 0.1.
58 *
59 * @param[in] nr Dimension of the residual vector
60 * @param[in] alpha Threshold factor (default 0.1)
61 * @param[in] true_hessian Boolean indicating whether to use the Gauss-Newton
62 * approximation or true Hessian in computing the derivatives (default: false)
63 */
64 185 explicit ActivationModel2NormBarrierTpl(const std::size_t nr,
65 const Scalar alpha = Scalar(0.1),
66 const bool true_hessian = false)
67 185 : Base(nr), alpha_(alpha), true_hessian_(true_hessian) {
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185 times.
185 if (alpha < Scalar(0.)) {
69 throw_pretty("Invalid argument: " << "alpha should be a positive value");
70 }
71 185 };
72 374 virtual ~ActivationModel2NormBarrierTpl() {};
73
74 /**
75 * @brief Compute the 2-norm barrier function
76 *
77 * @param[in] data 2-norm barrier activation data
78 * @param[in] r Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
79 */
80 3795 virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data,
81 const Eigen::Ref<const VectorXs>& r) {
82
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3795 times.
3795 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 3795 boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
88
89
1/2
✓ Branch 1 taken 3795 times.
✗ Branch 2 not taken.
3795 d->d = r.norm();
90
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 3637 times.
3795 if (d->d < alpha_) {
91 158 data->a_value = Scalar(0.5) * (d->d - alpha_) * (d->d - alpha_);
92 } else {
93 3637 data->a_value = Scalar(0.0);
94 }
95 3795 };
96
97 /**
98 * @brief Compute the derivatives of the 2norm-barrier function
99 *
100 * @param[in] data 2-norm barrier activation data
101 * @param[in] r Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
102 */
103 212 virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data,
104 const Eigen::Ref<const VectorXs>& r) {
105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 212 times.
212 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 212 boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
111
112
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 206 times.
212 if (d->d < alpha_) {
113
2/4
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 data->Ar = (d->d - alpha_) / d->d * r;
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 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
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
6 data->Arr.diagonal() =
120
1/2
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
12 r.array().square() / std::pow(d->d, 2); // GN Hessian approximation
121 }
122 } else {
123
1/2
✓ Branch 2 taken 206 times.
✗ Branch 3 not taken.
206 data->Ar.setZero();
124
1/2
✓ Branch 2 taken 206 times.
✗ Branch 3 not taken.
206 data->Arr.setZero();
125 }
126 212 };
127
128 /**
129 * @brief Create the 2norm-barrier activation data
130 *
131 * @return the activation data
132 */
133 4679 virtual boost::shared_ptr<ActivationDataAbstract> createData() {
134
1/2
✓ Branch 2 taken 4679 times.
✗ Branch 3 not taken.
4679 return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
135 };
136
137 /**
138 * @brief Get and set the threshold factor
139 */
140 const Scalar& get_alpha() const { return alpha_; };
141 void set_alpha(const Scalar& alpha) { alpha_ = alpha; };
142
143 /**
144 * @brief Print relevant information of the 2-norm barrier model
145 *
146 * @param[out] os Output stream object
147 */
148 37 virtual void print(std::ostream& os) const {
149 37 os << "ActivationModel2NormBarrier {nr=" << nr_ << ", alpha=" << alpha_
150 37 << ", Hessian=" << true_hessian_ << "}";
151 37 }
152
153 protected:
154 using Base::nr_; //!< Dimension of the residual vector
155 Scalar alpha_; //!< Threshold factor
156 bool true_hessian_; //!< Use true Hessian in calcDiff if true, Gauss-Newton
157 //!< approximation if false
158 };
159
160 template <typename _Scalar>
161 struct ActivationData2NormBarrierTpl
162 : public ActivationDataAbstractTpl<_Scalar> {
163 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
164
165 typedef _Scalar Scalar;
166 typedef ActivationDataAbstractTpl<Scalar> Base;
167
168 template <typename Activation>
169 4679 explicit ActivationData2NormBarrierTpl(Activation* const activation)
170 4679 : Base(activation), d(Scalar(0)) {}
171
172 Scalar d; //!< Norm of the residual
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_
182