GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/quad-estimator.cpp Lines: 0 158 0.0 %
Date: 2023-06-05 17:45:50 Branches: 0 108 0.0 %

Line Branch Exec Source
1
/*
2
   Oscar Efrain RAMOS PONCE, LAAS-CNRS
3
   Date: 28/10/2014
4
   Object to estimate a polynomial of second order that fits some data.
5
*/
6
7
#include <iostream>
8
#include <sot/torque_control/utils/quad-estimator.hh>
9
10
QuadEstimator::QuadEstimator(const unsigned int& N, const unsigned int& dim,
11
                             const double& dt)
12
    : PolyEstimator(2, N, dt),
13
      dim_(dim),
14
      sum_ti_(0.0),
15
      sum_ti2_(0.0),
16
      sum_ti3_(0.0),
17
      sum_ti4_(0.0) {
18
  /* Number of coefficients for a quadratic estimator: 3 */
19
  coeff_.resize(3);
20
21
  /* Initialize sums for the recursive computation */
22
  sum_xi_.resize(dim);
23
  sum_tixi_.resize(dim);
24
  sum_ti2xi_.resize(dim);
25
  for (unsigned int i = 0; i < dim; ++i) {
26
    sum_xi_.at(i) = 0.0;
27
    sum_tixi_.at(i) = 0.0;
28
    sum_ti2xi_.at(i) = 0.0;
29
  }
30
31
  /* Initialize (pre-compute) pseudo inverse matrix that assumes that the sample
32
     time is constant (only if dt is not zero) */
33
  if (!dt_zero_) {
34
    Eigen::MatrixXd Tmat(N_, 3);
35
    Eigen::MatrixXd pinvTmat(3, N_);
36
    double time = 0.0;
37
    for (unsigned int i = 0; i < N_; ++i) {
38
      Tmat(i, 2) = 0.5 * time * time;
39
      Tmat(i, 1) = time;
40
      Tmat(i, 0) = 1.0;
41
      time += dt_;
42
    }
43
    /* Half time used to estimate velocity and position*/
44
    tmed_ = time * 0.5;
45
46
    /* Pseudo inverse */
47
    pinv(Tmat, pinvTmat);
48
    pinv0_ = new double[N_];
49
    pinv1_ = new double[N_];
50
    pinv2_ = new double[N_];
51
    c0_.resize(dim_);
52
    c1_.resize(dim_);
53
    c2_.resize(dim_);
54
    c0_.assign(dim_, 0.0);
55
    c1_.assign(dim_, 0.0);
56
    c2_.assign(dim_, 0.0);
57
58
    /* Copy the pseudo inverse to an array */
59
    for (unsigned int i = 0; i < N_; ++i) {
60
      pinv2_[i] = pinvTmat(2, i);
61
      pinv1_[i] = pinvTmat(1, i);
62
      pinv0_[i] = pinvTmat(0, i);
63
    }
64
  }
65
}
66
67
double QuadEstimator::getEsteeme() { return coeff_(2); }
68
69
void QuadEstimator::estimateRecursive(std::vector<double>& esteem,
70
                                      const std::vector<double>& el,
71
                                      const double& time) {
72
  /* Feed Data */
73
  elem_list_.at(pt_) = el;
74
  time_list_.at(pt_) = time;
75
76
  double t, x;
77
78
  if (first_run_) {
79
    // Not enough elements in the window
80
    if ((pt_ + 1) < N_) {
81
      // t = time - time_list_.at(0);
82
      t = time;
83
      sum_ti_ += t;
84
      sum_ti2_ += t * t;
85
      sum_ti3_ += t * t * t;
86
      sum_ti4_ += t * t * t * t;
87
88
      for (unsigned int i = 0; i < esteem.size(); ++i) {
89
        // Return a zero vector
90
        esteem.at(i) = 0.0;
91
        x = el.at(i);
92
        // Fill the sumations
93
        sum_xi_.at(i) += x;
94
        sum_tixi_.at(i) += t * x;
95
        sum_ti2xi_.at(i) += t * t * x;
96
      }
97
      pt_++;
98
      return;
99
    } else {
100
      first_run_ = false;
101
    }
102
  }
103
104
  // Increase the 'circular' pointer
105
  pt_ = (pt_ + 1) < N_ ? (pt_ + 1) : 0;
106
  // The pointer now points to the "oldest" element in the vector
107
108
  // Get size of first element: N dof (assuming all elements have same size)
109
  size_t dim = elem_list_.at(0).size();
110
  // TODO: CHECK THAT SIZE OF ESTEEM = DIM
111
112
  // t = time - time_list_.at(pt_);
113
  t = time;
114
  sum_ti_ += t;
115
  sum_ti2_ += t * t;
116
  sum_ti3_ += t * t * t;
117
  sum_ti4_ += t * t * t * t;
118
119
  double den =
120
      0.25 * N_ * sum_ti3_ * sum_ti3_ - 0.5 * sum_ti3_ * sum_ti2_ * sum_ti_ +
121
      0.25 * sum_ti2_ * sum_ti2_ * sum_ti2_ +
122
      0.25 * sum_ti4_ * sum_ti_ * sum_ti_ - 0.25 * N_ * sum_ti4_ * sum_ti2_;
123
  double den2 = 1.0 / (2.0 * den);
124
  // double den4 = 1.0/(4.0*den);
125
126
  double t_old = time_list_.at(pt_);
127
  double a;
128
  // double b;
129
  // unsigned int pt_med;
130
  for (unsigned int i = 0; i < dim; ++i) {
131
    x = el[i];
132
    // Fill the sumations
133
    sum_xi_[i] += x;
134
    sum_tixi_[i] += t * x;
135
    sum_ti2xi_[i] += t * t * x;
136
137
    a = den2 * (sum_ti2xi_[i] * (sum_ti_ * sum_ti_ - N_ * sum_ti2_) +
138
                sum_tixi_[i] * (N_ * sum_ti3_ - sum_ti2_ * sum_ti_) +
139
                sum_xi_[i] * (sum_ti2_ * sum_ti2_ - sum_ti3_ * sum_ti_));
140
    // b = den4*( sum_ti2xi_[i]*(N_*sum_ti3_-sum_ti2_*sum_ti_) +
141
    //            sum_tixi_[i]*(sum_ti2_*sum_ti2_-N_*sum_ti4_) +
142
    //            sum_xi_[i]*(sum_ti4_*sum_ti_-sum_ti3_*sum_ti2_) );
143
144
    esteem[i] = a;  // For acceleration
145
146
    // pt_med = (pt_+((N_-1)/2)) % N_;
147
    // esteem[i] = a*time_list_[pt_med] + b;  // For velocity
148
149
    x = elem_list_[pt_][i];
150
    sum_xi_[i] -= x;
151
    sum_tixi_[i] -= t_old * x;
152
    sum_ti2xi_[i] -= t_old * t_old * x;
153
  }
154
  sum_ti_ -= t_old;
155
  sum_ti2_ -= t_old * t_old;
156
  sum_ti3_ -= t_old * t_old * t_old;
157
  sum_ti4_ -= t_old * t_old * t_old * t_old;
158
159
  return;
160
}
161
162
void QuadEstimator::fit() {
163
  double sum_ti = 0.0;
164
  double sum_ti2 = 0.0;
165
  double sum_ti3 = 0.0;
166
  double sum_ti4 = 0.0;
167
  double sum_xi = 0.0;
168
  double sum_tixi = 0.0;
169
  double sum_ti2xi = 0.0;
170
171
  for (unsigned int i = 0; i < N_; ++i) {
172
    sum_ti += t_[i];
173
    sum_ti2 += t_[i] * t_[i];
174
    sum_ti3 += t_[i] * t_[i] * t_[i];
175
    sum_ti4 += t_[i] * t_[i] * t_[i] * t_[i];
176
    sum_xi += x_[i];
177
    sum_tixi += t_[i] * x_[i];
178
    sum_ti2xi += t_[i] * t_[i] * x_[i];
179
  }
180
181
  double den = 0.25 * N_ * sum_ti3 * sum_ti3 -
182
               0.5 * sum_ti3 * sum_ti2 * sum_ti +
183
               0.25 * sum_ti2 * sum_ti2 * sum_ti2 +
184
               0.25 * sum_ti4 * sum_ti * sum_ti - 0.25 * N_ * sum_ti4 * sum_ti2;
185
  double den4 = 1.0 / (4.0 * den);
186
187
  coeff_(2) = den4 * (sum_ti2xi * (sum_ti * sum_ti - N_ * sum_ti2) +
188
                      sum_tixi * (N_ * sum_ti3 - sum_ti2 * sum_ti) +
189
                      sum_xi * (sum_ti2 * sum_ti2 - sum_ti3 * sum_ti));
190
  coeff_(1) = den4 * (sum_ti2xi * (N_ * sum_ti3 - sum_ti2 * sum_ti) +
191
                      sum_tixi * (sum_ti2 * sum_ti2 - N_ * sum_ti4) +
192
                      sum_xi * (sum_ti4 * sum_ti - sum_ti3 * sum_ti2));
193
  // This has not been computed (because not needed for accel or velocity)
194
  coeff_(0) = 0;
195
196
  return;
197
}
198
199
void QuadEstimator::estimate(std::vector<double>& esteem,
200
                             const std::vector<double>& el) {
201
  if (dt_zero_) {
202
    std::cerr << "Error: dt cannot be zero" << std::endl;
203
    // Return a zero vector
204
    for (unsigned int i = 0; i < esteem.size(); ++i) esteem[i] = 0.0;
205
    return;
206
  }
207
208
  /* Feed Data. Note that the time is not completed since it is assumed to be
209
     constant */
210
  elem_list_[pt_] = el;
211
212
  if (first_run_) {
213
    if ((pt_ + 1) < N_) {
214
      // Return input vector when not enough elements to compute
215
      pt_++;
216
      for (unsigned int i = 0; i < esteem.size(); ++i) esteem[i] = el[i];
217
      return;
218
    } else
219
      first_run_ = false;
220
  }
221
222
  // Next pointer value
223
  pt_ = (pt_ + 1) < N_ ? (pt_ + 1) : 0;
224
225
  unsigned int idx;
226
227
  double x;
228
  // Cycle all the elements in the vector
229
  for (int i = 0; i < dim_; ++i) {
230
    c0_[i] = 0.0;
231
    c1_[i] = 0.0;
232
    c2_[i] = 0.0;
233
    // Retrieve the data in the window
234
    for (unsigned int j = 0; j < N_; ++j) {
235
      idx = (pt_ + j);
236
      if (idx >= N_) idx -= N_;
237
      x = elem_list_[idx][i];
238
      c0_[i] += x * pinv0_[j];
239
      c1_[i] += x * pinv1_[j];
240
      c2_[i] += x * pinv2_[j];
241
    }
242
243
    // Polynomial (position)
244
    esteem[i] = 0.5 * c2_[i] * tmed_ * tmed_ + c1_[i] * tmed_ + c0_[i];
245
  }
246
}
247
248
void QuadEstimator::getEstimateDerivative(
249
    std::vector<double>& estimateDerivative, const unsigned int order) {
250
  switch (order) {
251
    case 0:
252
      for (int i = 0; i < dim_; ++i)
253
        estimateDerivative[i] =
254
            0.5 * c2_[i] * tmed_ * tmed_ + c1_[i] * tmed_ + c0_[i];
255
      return;
256
257
    case 1:
258
      for (int i = 0; i < dim_; ++i)
259
        estimateDerivative[i] = c2_[i] * tmed_ + c1_[i];
260
      return;
261
262
    case 2:
263
      for (int i = 0; i < dim_; ++i) estimateDerivative[i] = c2_[i];
264
      return;
265
266
    default:
267
      for (int i = 0; i < dim_; ++i) estimateDerivative[i] = 0.0;
268
  }
269
}