GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/core/activations/smooth-1norm.hpp Lines: 26 33 78.8 %
Date: 2024-02-13 11:12:33 Branches: 22 90 24.4 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2019-2020, LAAS-CNRS, University of Edinburgh
5
// Copyright note valid unless otherwise stated in individual files.
6
// All rights reserved.
7
///////////////////////////////////////////////////////////////////////////////
8
9
#ifndef CROCODDYL_CORE_ACTIVATIONS_SMOOTH_1NORM_HPP_
10
#define CROCODDYL_CORE_ACTIVATIONS_SMOOTH_1NORM_HPP_
11
12
#include <iostream>
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 Smooth-abs activation
23
 *
24
 * This activation function describes a smooth representation of an absolute
25
 * activation (1-norm) for each element of a residual vector, i.e. \f[
26
 * \begin{equation} sum^nr_{i=0} \sqrt{\epsilon + \|r_i\|^2} \end{equation} \f]
27
 * where \f$\epsilon\f$ defines the smoothing factor, \f$r_i\f$ is the scalar
28
 * residual for the \f$i\f$ constraints, \f$nr\f$ is the dimension of the
29
 * residual vector.
30
 *
31
 * The computation of the function and it derivatives are carried out in
32
 * `calc()` and `caldDiff()`, respectively.
33
 *
34
 * \sa `calc()`, `calcDiff()`, `createData()`
35
 */
36
template <typename _Scalar>
37
class ActivationModelSmooth1NormTpl
38
    : public ActivationModelAbstractTpl<_Scalar> {
39
 public:
40
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
41
42
  typedef _Scalar Scalar;
43
  typedef MathBaseTpl<Scalar> MathBase;
44
  typedef ActivationModelAbstractTpl<Scalar> Base;
45
  typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
46
  typedef ActivationDataSmooth1NormTpl<Scalar> Data;
47
  typedef typename MathBase::VectorXs VectorXs;
48
  typedef typename MathBase::MatrixXs MatrixXs;
49
50
  /**
51
   * @brief Initialize the smooth-abs activation model
52
   *
53
   * The default `eps` value is defined as 1.
54
   *
55
   * @param[in] nr   Dimension of the residual vector
56
   * @param[in] eps  Smoothing factor (default: 1.)
57
   */
58
223
  explicit ActivationModelSmooth1NormTpl(const std::size_t nr,
59
                                         const Scalar eps = Scalar(1.))
60
223
      : Base(nr), eps_(eps) {
61
223
    if (eps < Scalar(0.)) {
62
      throw_pretty("Invalid argument: "
63
                   << "eps should be a positive value");
64
    }
65
223
    if (eps == Scalar(0.)) {
66
      std::cerr << "Warning: eps=0 leads to derivatives discontinuities in the "
67
                   "origin, it becomes the absolute function"
68
                << std::endl;
69
    }
70
223
  };
71
450
  virtual ~ActivationModelSmooth1NormTpl(){};
72
73
  /**
74
   * @brief Compute the smooth-abs function
75
   *
76
   * @param[in] data  Smooth-abs activation data
77
   * @param[in] r     Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
78
   */
79
9675
  virtual void calc(const boost::shared_ptr<ActivationDataAbstract>& data,
80
                    const Eigen::Ref<const VectorXs>& r) {
81

9675
    if (static_cast<std::size_t>(r.size()) != nr_) {
82
      throw_pretty("Invalid argument: "
83
                   << "r has wrong dimension (it should be " +
84
                          std::to_string(nr_) + ")");
85
    }
86
9675
    boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
87
88


9675
    d->a = (r.array().cwiseAbs2().array() + eps_).array().cwiseSqrt();
89
9675
    data->a_value = d->a.sum();
90
9675
  };
91
92
  /**
93
   * @brief Compute the derivatives of the smooth-abs function
94
   *
95
   * @param[in] data  Smooth-abs activation data
96
   * @param[in] r     Residual vector \f$\mathbf{r}\in\mathbb{R}^{nr}\f$
97
   */
98
304
  virtual void calcDiff(const boost::shared_ptr<ActivationDataAbstract>& data,
99
                        const Eigen::Ref<const VectorXs>& r) {
100

304
    if (static_cast<std::size_t>(r.size()) != nr_) {
101
      throw_pretty("Invalid argument: "
102
                   << "r has wrong dimension (it should be " +
103
                          std::to_string(nr_) + ")");
104
    }
105
106
304
    boost::shared_ptr<Data> d = boost::static_pointer_cast<Data>(data);
107

304
    data->Ar = r.cwiseProduct(d->a.cwiseInverse());
108

304
    data->Arr.diagonal() =
109

304
        d->a.cwiseProduct(d->a).cwiseProduct(d->a).cwiseInverse();
110
304
  };
111
112
  /**
113
   * @brief Create the smooth-abs activation data
114
   *
115
   * @return the activation data
116
   */
117
7837
  virtual boost::shared_ptr<ActivationDataAbstract> createData() {
118
7837
    return boost::allocate_shared<Data>(Eigen::aligned_allocator<Data>(), this);
119
  };
120
121
  /**
122
   * @brief Print relevant information of the smooth-1norm model
123
   *
124
   * @param[out] os  Output stream object
125
   */
126
37
  virtual void print(std::ostream& os) const {
127
37
    os << "ActivationModelSmooth1Norm {nr=" << nr_ << ", eps=" << eps_ << "}";
128
37
  }
129
130
 protected:
131
  using Base::nr_;  //!< Dimension of the residual vector
132
  Scalar eps_;      //!< Smoothing factor
133
};
134
135
template <typename _Scalar>
136
struct ActivationDataSmooth1NormTpl
137
    : public ActivationDataAbstractTpl<_Scalar> {
138
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
139
140
  typedef _Scalar Scalar;
141
  typedef ActivationDataAbstractTpl<Scalar> Base;
142
  typedef MathBaseTpl<Scalar> MathBase;
143
  typedef typename MathBase::VectorXs VectorXs;
144
  typedef typename MathBase::MatrixXs MatrixXs;
145
146
  template <typename Activation>
147
7837
  explicit ActivationDataSmooth1NormTpl(Activation* const activation)
148

7837
      : Base(activation), a(VectorXs::Zero(activation->get_nr())) {}
149
150
  VectorXs a;
151
  using Base::Arr;
152
};
153
154
}  // namespace crocoddyl
155
156
#endif  // CROCODDYL_CORE_ACTIVATIONS_SMOOTH_1NORM_HPP_