GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/sot/core/feature-abstract.hh Lines: 10 15 66.7 %
Date: 2023-03-13 12:09:37 Branches: 1 2 50.0 %

Line Branch Exec Source
1
/*
2
 * Copyright 2010,
3
 * François Bleibel,
4
 * Olivier Stasse,
5
 *
6
 * CNRS/AIST
7
 *
8
 */
9
10
#ifndef __SOT_FEATURE_ABSTRACT_H__
11
#define __SOT_FEATURE_ABSTRACT_H__
12
13
/* --------------------------------------------------------------------- */
14
/* --- INCLUDE --------------------------------------------------------- */
15
/* --------------------------------------------------------------------- */
16
17
/* Matrix */
18
#include <dynamic-graph/linear-algebra.h>
19
20
/* SOT */
21
#include <dynamic-graph/all-signals.h>
22
#include <dynamic-graph/entity.h>
23
24
#include <sot/core/flags.hh>
25
#include <sot/core/pool.hh>
26
27
#include "sot/core/api.hh"
28
29
/* STD */
30
#include <string>
31
32
namespace dynamicgraph {
33
namespace sot {
34
35
/* --------------------------------------------------------------------- */
36
/* --- CLASS ----------------------------------------------------------- */
37
/* --------------------------------------------------------------------- */
38
39
/*! \class FeatureAbstract
40
  \ingroup features
41
  \brief This class gives the abstract definition of a feature.
42
43
  \par par_features_definition Definition
44
  In short, a feature is a data evolving according to time.  It is defined
45
  by a vector \f${\bf s}({\bf q}) \in \mathbb{R}^n \f$ where \f$ {\bf q} \f$ is
46
  a robot configuration, which depends on the time \f$ t \f$. By default a
47
  feature has a desired \f${\bf s}^*(t) \f$. \f${\bf s}^*\f$ is provided by
48
  another feature of the same type called reference. The feature is in charge of
49
  collecting its own current state.  A feature is supposed to compute an error
50
  between its current state and the desired one: \f$ E(t) = e({\bf q}(t), t) =
51
  {\bf s}({\bf q}(t)) \ominus {\bf s}^*(t) \f$. Here, \f$ \ominus \f$ is the
52
  difference operator of Lie group in which \f$ {\bf s} \f$ and \f$ {\bf s}^*
53
  \f$ are. The documentation below assumes the Lie group is a vector space and
54
  \f$\ominus\f$ is the usual difference operator.
55
56
  A feature computes:
57
  \li the Jacobian according to the robot state vector \f$ J =
58
      \frac{\partial e}{\partial {\bf q}} = \frac{\partial{\bf s}}{\partial {\bf
59
  q}}\f$. \li the partial derivative of the error \f$ e \f$: \f$ \frac{\partial
60
  e}{\partial t} = - \frac{d{\bf s}^*}{dt}\f$.
61
62
  The task is in general computed from the value of the feature at the
63
  current instant \f$E(t) = e({\bf q},t)\f$. The derivative of \f$ E \f$ is:
64
  \f[
65
    \frac{dE}{dt} = J({\bf q}) \dot{q} + \frac{\partial e}{\partial t}
66
  \f]
67
68
  \image html feature.png "Feature diagram: Feature types derive from
69
  FeatureAbstract. Each feature has a reference of the same type and
70
  compute an error by comparing
71
  errorSIN
72
  signals from itself and from the
73
  reference."
74
75
*/
76
class SOT_CORE_EXPORT FeatureAbstract : public Entity {
77
 public:
78
  /*! \brief Store the name of the class. */
79
  static const std::string CLASS_NAME;
80
81
  /*! \brief Returns the name class. */
82
  virtual const std::string &getClassName(void) const { return CLASS_NAME; }
83
84
  /*! \brief Register the feature in the stack of tasks. */
85
  void featureRegistration(void);
86
87
  void initCommands(void);
88
89
 public:
90
  /*! \brief Default constructor: the name of the class should be given. */
91
  FeatureAbstract(const std::string &name);
92
  /*! \brief Default destructor */
93
16
  virtual ~FeatureAbstract(void){};
94
95
  /*! \name Methods returning the dimension of the feature.
96
    @{ */
97
98
  /*! \brief Verbose method.
99
    \par res: The integer in which the dimension will be return.
100
    \par time: The time at which the feature should be considered.
101
    \return Dimension of the feature.
102
    \note Be careful with features changing their dimension according to time.
103
  */
104
  virtual unsigned int &getDimension(unsigned int &res, int time) = 0;
105
106
  /*! \brief Short method
107
    \par time: The time at which the feature should be considered.
108
    \return Dimension of the feature.
109
    \note Be careful with features changing their dimension according to time.
110
  */
111
  inline unsigned int getDimension(int time) {
112
    unsigned int res;
113
    getDimension(res, time);
114
    return res;
115
  }
116
117
  /*! \brief Shortest method
118
    \return Dimension of the feature.
119
    \note The feature is not changing its dimension according to time.
120
  */
121
  inline unsigned int getDimension(void) const {
122
    return dimensionSOUT.accessCopy();
123
  }
124
  /*! @} */
125
126
  /*! \name Methods to control internal computation.
127
    The main idea is that some feature may have a lower frequency
128
    than the internal control loop. In this case, the methods for
129
    computation are called only when needed.
130
131
    @{*/
132
133
  /*! \brief Compute the error between the desired feature and
134
    the current value of the feature measured or deduced from the robot state.
135
136
    \par[out] res: The error will be set into res.
137
    \par[in] time: The time at which the error is computed.
138
    \return The vector res with the appropriate value.
139
  */
140
  virtual dynamicgraph::Vector &computeError(dynamicgraph::Vector &res,
141
                                             int time) = 0;
142
143
  /*! \brief Compute the Jacobian of the error according the robot state.
144
145
    \par[out] res: The matrix in which the error will be written.
146
    \return The matrix res with the appropriate values.
147
  */
148
  virtual dynamicgraph::Matrix &computeJacobian(dynamicgraph::Matrix &res,
149
                                                int time) = 0;
150
151
  /// Callback for signal errordotSOUT
152
  ///
153
  /// Copy components of the input signal errordotSIN defined by selection
154
  /// flag selectionSIN.
155
  virtual dynamicgraph::Vector &computeErrorDot(dynamicgraph::Vector &res,
156
                                                int time);
157
158
  /*! @} */
159
160
  /* --- SIGNALS ------------------------------------------------------------ */
161
 public:
162
  /*! \name Signals
163
    @{
164
  */
165
166
  /*! \name Input signals:
167
    @{ */
168
  /*! \brief This vector specifies which dimension are used to perform the
169
    computation. For instance let us assume that the feature is a 3D point. If
170
    only the Y-axis should be used for computing error, activation and Jacobian,
171
    then the vector to specify
172
    is \f$ [ 0 1 0] \f$.*/
173
  SignalPtr<Flags, int> selectionSIN;
174
175
  /// Derivative of the reference value.
176
  SignalPtr<dynamicgraph::Vector, int> errordotSIN;
177
178
  /*! @} */
179
180
  /*! \name Output signals:
181
    @{ */
182
183
  /*! \brief This signal returns the error between the desired value and
184
    the current value : \f$ E(t) = {\bf s}(t) - {\bf s}^*(t)\f$ */
185
  SignalTimeDependent<dynamicgraph::Vector, int> errorSOUT;
186
187
  /*! \brief Derivative of the error with respect to time:
188
   * \f$ \frac{\partial e}{\partial t} = - \frac{d{\bf s}^*}{dt} \f$ */
189
  SignalTimeDependent<dynamicgraph::Vector, int> errordotSOUT;
190
191
  /*! \brief Jacobian of the error wrt the robot state:
192
   * \f$ J = \frac{\partial {\bf s}}{\partial {\bf q}}\f$ */
193
  SignalTimeDependent<dynamicgraph::Matrix, int> jacobianSOUT;
194
195
  /*! \brief Returns the dimension of the feature as an output signal. */
196
  SignalTimeDependent<unsigned int, int> dimensionSOUT;
197
198
  /*! \brief This method write a graph description on the file named
199
    FileName. */
200
  virtual std::ostream &writeGraph(std::ostream &os) const;
201
202
135
  virtual SignalTimeDependent<dynamicgraph::Vector, int> &getErrorDot() {
203
135
    return errordotSOUT;
204
  }
205
206
  /*! @} */
207
208
  /* --- REFERENCE VALUE S* ------------------------------------------------- */
209
 public:
210
  /*! \name Reference
211
    @{
212
  */
213
  virtual void setReference(FeatureAbstract *sdes) = 0;
214
  virtual void unsetReference(void) { setReference(NULL); }
215
  virtual const FeatureAbstract *getReferenceAbstract(void) const = 0;
216
  virtual FeatureAbstract *getReferenceAbstract(void) = 0;
217
  virtual bool isReferenceSet(void) const { return false; }
218
219
  virtual void addDependenciesFromReference(void) = 0;
220
  virtual void removeDependenciesFromReference(void) = 0;
221
222
  /* Commands for bindings. */
223
  void setReferenceByName(const std::string &name);
224
  std::string getReferenceByName(void) const;
225
  /*! @} */
226
};
227
228
template <class FeatureSpecialized>
229
class FeatureReferenceHelper {
230
  FeatureSpecialized *ptr;
231
  FeatureAbstract *ptrA;
232
233
 public:
234
8
  FeatureReferenceHelper(void) : ptr(NULL) {}
235
236
  void setReference(FeatureAbstract *sdes);
237
  // void setReferenceByName( const std::string & name );
238
  void unsetReference(void) { setReference(NULL); }
239
36
  bool isReferenceSet(void) const { return ptr != NULL; }
240
48
  FeatureSpecialized *getReference(void) { return ptr; }
241
  const FeatureSpecialized *getReference(void) const { return ptr; }
242
};
243
244
template <class FeatureSpecialized>
245
4
void FeatureReferenceHelper<FeatureSpecialized>::setReference(
246
    FeatureAbstract *sdes) {
247
4
  ptr = dynamic_cast<FeatureSpecialized *>(sdes);
248
4
  ptrA = ptr;
249
4
}
250
251
#define DECLARE_REFERENCE_FUNCTIONS(FeatureSpecialized)             \
252
  typedef FeatureReferenceHelper<FeatureSpecialized> SP;            \
253
  virtual void setReference(FeatureAbstract *sdes) {                \
254
    if (sdes == NULL) {                                             \
255
      /* UNSET */                                                   \
256
      if (SP::isReferenceSet()) removeDependenciesFromReference();  \
257
      SP::unsetReference();                                         \
258
    } else {                                                        \
259
      /* SET */                                                     \
260
      SP::setReference(sdes);                                       \
261
      if (SP::isReferenceSet()) addDependenciesFromReference();     \
262
    }                                                               \
263
  }                                                                 \
264
  virtual const FeatureAbstract *getReferenceAbstract(void) const { \
265
    return SP::getReference();                                      \
266
  }                                                                 \
267
  virtual FeatureAbstract *getReferenceAbstract(void) {             \
268
    return (FeatureAbstract *)SP::getReference();                   \
269
  }                                                                 \
270
  bool isReferenceSet(void) const { return SP::isReferenceSet(); }  \
271
  virtual void addDependenciesFromReference(void);                  \
272
  virtual void removeDependenciesFromReference(void)
273
/* END OF define DECLARE_REFERENCE_FUNCTIONS */
274
275
#define DECLARE_NO_REFERENCE                                           \
276
  virtual void setReference(FeatureAbstract *) {}                      \
277
  virtual const FeatureAbstract *getReferenceAbstract(void) const {    \
278
    return NULL;                                                       \
279
  }                                                                    \
280
  virtual FeatureAbstract *getReferenceAbstract(void) { return NULL; } \
281
  virtual void addDependenciesFromReference(void) {}                   \
282
  virtual void removeDependenciesFromReference(void) {}                \
283
  /* To force a ; */ bool NO_REFERENCE
284
/* END OF define DECLARE_REFERENCE_FUNCTIONS */
285
286
}  // namespace sot
287
}  // namespace dynamicgraph
288
289
#endif  // #ifndef __SOT_FEATURE_ABSTRACT_H__