Cheetah Software  1.0
BSplineBasic.h
Go to the documentation of this file.
1 #ifndef B_SPLINE_BASIC
2 #define B_SPLINE_BASIC
3 
4 #include <assert.h>
5 #include <stdio.h>
6 #include <iostream>
7 
8 #define SP_IS_EQUAL(x, y) (((x) - (y)) * ((x) - (y)) < 1.e-10)
9 #define SP_SAFE_DELETE_AR(p) \
10  if (p) { \
11  delete[] p; \
12  (p) = NULL; \
13  }
14 
33 template <typename T, int DIM, int DEGREE, int NUM_MIDDLE, int CONST_LEVEL_INI,
34  int CONST_LEVEL_FIN>
35 class BS_Basic {
36  public:
38  : NumKnots_(DEGREE + NUM_MIDDLE + 2 + CONST_LEVEL_INI + CONST_LEVEL_FIN +
39  1),
40  NumCPs_(NUM_MIDDLE + 2 + CONST_LEVEL_INI + CONST_LEVEL_FIN) {
41  for (int i(0); i < NumKnots_; ++i) Knots_[i] = 0.;
42  for (int i(0); i < NumCPs_; ++i) {
43  for (int j(0); j < DIM; ++j) CPoints_[i][j] = 0.;
44  }
45  if (NumKnots_ < 2 * (DEGREE + 1)) {
46  printf("Invalid setup (num_knots, degree): %d, %d\n", NumKnots_, DEGREE);
47  }
48  }
49  ~BS_Basic() {}
50 
63  bool SetParam(T* init, T* fin, T** middle_pt, T fin_time) {
64  _CalcKnot(fin_time);
65  _CalcConstrainedCPoints(init, fin, fin_time);
66  _CalcCPoints(middle_pt);
67 
68  return true;
69  }
70 
78  bool getCurvePoint(T u, T* ret) {
79  int _span;
80 
81  if (u < Knots_[0])
82  u = Knots_[0];
83  else if (u > Knots_[NumKnots_ - 1]) {
84  u = Knots_[NumKnots_ - 1];
85  }
86 
87  if (!_findSpan(_span, u)) return false;
88 
89  T _N[DEGREE + 1];
90  _BasisFuns(_N, _span, u);
91 
92  T _C[DIM];
93 
94  for (int j(0); j < DIM; ++j) {
95  _C[j] = 0.0;
96  for (int i(0); i <= DEGREE; ++i) {
97  _C[j] += _N[i] * CPoints_[_span - DEGREE + i][j];
98  }
99  }
100 
101  for (int i(0); i < DIM; ++i) {
102  ret[i] = _C[i];
103  }
104  return true;
105  }
106 
115  bool getCurveDerPoint(T u, int d, T* ret) {
116  if (d > DEGREE) return 0.0;
117 
118  if (u < Knots_[0])
119  u = Knots_[0];
120  else if (u > Knots_[NumKnots_ - 1]) {
121  u = Knots_[NumKnots_ - 1];
122  }
123 
124  T** _CK = new T*[d + 1];
125  for (int i(0); i < d + 1; ++i) {
126  _CK[i] = new T[DIM];
127  }
128  if (_CurveDerivsAlg1V(_CK, u, d)) {
129  for (int m(0); m < DIM; ++m) ret[m] = _CK[d][m];
130 
131  for (int p(0); p < d + 1; ++p) delete[] _CK[p];
132  SP_SAFE_DELETE_AR(_CK);
133  return true;
134  } else {
135  for (int p(0); p < d + 1; ++p) delete[] _CK[p];
136  SP_SAFE_DELETE_AR(_CK);
137  }
138  return false;
139  }
140 
141  // protected:
142  private:
143  inline void _CalcKnot(T Tf) {
144  int _i(0);
145  int _j(0);
146  int _NumMidKnot(NumKnots_ - 2 * DEGREE - 2);
147  T _TimeStep = Tf / (_NumMidKnot + 1);
148 
149  // augment knot sequence for the initial part, # of order ( degree + 1 )
150  for (_j = 0; _j < DEGREE + 1; ++_j) Knots_[_i++] = 0.0;
151 
152  // uniform knot sequence for the middle part,
153  // #: NumKnot - degree - degree = NumKnot - order - order + 2
154  for (_j = 0; _j < _NumMidKnot; ++_j) {
155  Knots_[_i] = Knots_[_i - 1] + _TimeStep;
156  ++_i;
157  }
158  // augment knot sequence for the final part, # of order ( degree + 1 )
159  for (_j = 0; _j < DEGREE + 1; ++_j) Knots_[_i++] = Tf;
160 
161  // for(int i(0); i< NumKnots_; ++i)
162  // std::cout<<Knots_[i]<<std::endl;
163  }
164 
165  bool _CurveDerivsAlg1V(T** CK, T u, int d) {
166  assert(d <= DEGREE);
167 
168  int _k(0);
169  int _j(0);
170 
171  T** _nders = new T*[d + 1];
172 
173  for (_k = 0; _k < d + 1; ++_k) _nders[_k] = new T[DEGREE + 1];
174 
175  int _span;
176  if (!_findSpan(_span, u)) return false;
177 
178  _BasisFunsDers(_nders, _span, u, d);
179 
180  for (_k = 0; _k <= d; ++_k) {
181  // Clean Up Column
182  for (int m(0); m < DIM; ++m) CK[_k][m] = 0.;
183 
184  for (_j = 0; _j <= DEGREE; ++_j) {
185  for (int m(0); m < DIM; ++m) {
186  CK[_k][m] += _nders[_k][_j] * CPoints_[_span - DEGREE + _j][m];
187  }
188  }
189  }
190  for (_k = 0; _k < d + 1; ++_k) delete[] _nders[_k];
191  delete[] _nders;
192 
193  return true;
194  }
195  bool _BasisFunsDers(T** ders, T u, int n) {
196  // int _span = FindSpan(u);
197  int _span;
198  if (!_findSpan(_span, u)) return false;
199 
200  _BasisFunsDers(ders, _span, u, n);
201  return true;
202  }
203 
204  bool _BasisFunsDers(T** ders, int span, T u, int n) {
205  int _j, _r, _k;
206  int _s1, _s2;
207  int _j1, _j2;
208  int _rk;
209  int _pk;
210 
211  T _saved = 0.0;
212  T _left = 0.0;
213  T _right = 0.0;
214  T _temp = 0.0;
215  T _d = 0.0;
216 
217  // to store the basis functions and knot differences
218  T** _ndu = new T*[DEGREE + 1];
219  for (_j = 0; _j <= DEGREE; ++_j) _ndu[_j] = new T[DEGREE + 1];
220  // to store (in an alternating fashion) the two most recently computed
221  // rows a(k,j) and a(k-1,j)
222  T** _a = new T*[2];
223  for (_j = 0; _j < 2; ++_j) _a[_j] = new T[DEGREE + 1];
224 
225  _ndu[0][0] = 1.0;
226  for (_j = 1; _j <= DEGREE; ++_j) {
227  _saved = 0.0;
228  for (_r = 0; _r < _j; ++_r) {
229  _left = _Left(span, _j - _r, u);
230  _right = _Right(span, _r + 1, u);
231 
232  // Lower triangle
233  _ndu[_j][_r] = _right + _left;
234  _temp = _ndu[_r][_j - 1] / _ndu[_j][_r];
235 
236  // Upper triangle
237  _ndu[_r][_j] = _saved + _right * _temp;
238  _saved = _left * _temp;
239  }
240  _ndu[_j][_j] = _saved;
241  }
242 
243  // Load the basis functions
244  for (_j = 0; _j <= DEGREE; ++_j) ders[0][_j] = _ndu[_j][DEGREE];
245 
246  // This section computes the derivatives (Eq. [2.9])
247  for (_r = 0; _r <= DEGREE; ++_r) {
248  _s1 = 0;
249  _s2 = 1;
250  _a[0][0] = 1.0;
251 
252  // Loop to compute k-th derivative
253  for (_k = 1; _k <= n; ++_k) {
254  _d = 0.0;
255  _rk = _r - _k;
256  _pk = DEGREE - _k;
257 
258  if (_r >= _k) {
259  _a[_s2][0] = _a[_s1][0] / _ndu[_pk + 1][_rk];
260  _d = _a[_s2][0] * _ndu[_rk][_pk];
261  }
262 
263  if (_rk >= -1)
264  _j1 = 1;
265  else
266  _j1 = -_rk;
267 
268  if (_r - 1 <= _pk)
269  _j2 = _k - 1;
270  else
271  _j2 = DEGREE - _r;
272 
273  for (_j = _j1; _j <= _j2; ++_j) {
274  _a[_s2][_j] =
275  (_a[_s1][_j] - _a[_s1][_j - 1]) / _ndu[_pk + 1][_rk + _j];
276  _d += _a[_s2][_j] * _ndu[_rk + _j][_pk];
277  }
278 
279  if (_r <= _pk) {
280  _a[_s2][_k] = -_a[_s1][_k - 1] / _ndu[_pk + 1][_r];
281  _d += _a[_s2][_k] * _ndu[_r][_pk];
282  }
283  ders[_k][_r] = _d;
284 
285  // Switch rows
286  _j = _s1;
287  _s1 = _s2;
288  _s2 = _j;
289  }
290  }
291 
292  // Multiply through by the correct factors
293  // (Eq. [2.9])
294  _r = DEGREE;
295  for (_k = 1; _k <= n; ++_k) {
296  for (_j = 0; _j <= DEGREE; ++_j) ders[_k][_j] *= _r;
297 
298  _r *= (DEGREE - _k);
299  }
300 
301  // Deallocate
302  for (_j = 0; _j <= DEGREE; ++_j) delete[] _ndu[_j];
303  delete[] _ndu;
304 
305  for (_j = 0; _j < 2; ++_j) delete[] _a[_j];
306  delete[] _a;
307 
308  return true;
309  }
310 
311  void _BasisFuns(T* N, T u) {
312  // Original
313  /*int _span = FindSpan(u);
314  BasisFuns(N, _span, u);*/
315 
316  int _span;
317 
318  if (_findSpan(_span, u)) {
319  _BasisFuns(N, _span, u);
320  }
321  }
322 
323  void _BasisFuns(T* N, int span, T u) {
324  int _j, _r;
325  T _left = 0.0;
326  T _right = 0.0;
327  T _saved = 0.0;
328  T _temp = 0.0;
329 
330  N[0] = 1.0;
331  for (_j = 1; _j <= DEGREE; ++_j) {
332  _saved = 0.0;
333  for (_r = 0; _r < _j; ++_r) {
334  _left = _Left(span, _j - _r, u);
335  _right = _Right(span, _r + 1, u);
336 
337  if ((_right + _left) != 0) {
338  _temp = N[_r] / (_right + _left);
339  }
340 
341  N[_r] = _saved + _right * _temp;
342  _saved = _left * _temp;
343  }
344  N[_j] = _saved;
345  }
346  }
347  inline T _Left(int i, int j, T u) { return u - Knots_[i + 1 - j]; }
348 
349  inline T _Right(int i, int j, T u) { return Knots_[i + j] - u; }
350 
351  bool _findSpan(int& ret, T u) {
352  if (u < Knots_[0] || Knots_[NumKnots_ - 1] < u) return false;
353 
354  if (SP_IS_EQUAL(u, Knots_[NumKnots_ - 1])) {
355  for (int i(NumKnots_ - 2); i > -1; --i) {
356  if (Knots_[i] < u && u <= Knots_[i + 1]) {
357  ret = i;
358  return true;
359  }
360  }
361  return false;
362  }
363  // Binary search
364  int _low = 0;
365  int _high = NumKnots_ - 1;
366  int _mid = (_low + _high) >> 1;
367 
368  while (u < Knots_[_mid] || u >= Knots_[_mid + 1]) {
369  if (u < Knots_[_mid])
370  _high = _mid;
371  else
372  _low = _mid;
373  _mid = (_low + _high) >> 1;
374  }
375  ret = _mid;
376  return true;
377  }
378 
379  void _CalcConstrainedCPoints(T* init, T* fin, T Tf) {
380  // Position
381  for (int m(0); m < DIM; ++m) {
382  CPoints_[0][m] = init[m];
383  CPoints_[NumCPs_ - 1][m] = fin[m];
384  }
385  // Initial Constraints
386  T** d_mat = new T*[CONST_LEVEL_INI + 1];
387 
388  for (int i(0); i < CONST_LEVEL_INI + 1; ++i)
389  d_mat[i] = new T[CONST_LEVEL_INI + 2];
390 
391  _BasisFunsDers(d_mat, 0., CONST_LEVEL_INI);
392 
393  T ini_const[DIM];
394  // Vel, Acc, ...
395  for (int j(1); j < CONST_LEVEL_INI + 1; ++j) {
396  for (int k(0); k < DIM; ++k) {
397  ini_const[k] = init[j * DIM + k];
398 
399  for (int h(j); h > 0; --h) {
400  ini_const[k] -= d_mat[j][h - 1] * CPoints_[h - 1][k];
401  }
402  CPoints_[j][k] = ini_const[k] / d_mat[j][j];
403  }
404  }
405 
406  for (int p(0); p < CONST_LEVEL_INI + 1; ++p) delete[] d_mat[p];
407  SP_SAFE_DELETE_AR(d_mat);
408 
409  // Final Constraints
410  T** c_mat = new T*[CONST_LEVEL_FIN + 1];
411 
412  for (int i(0); i < CONST_LEVEL_FIN + 1; ++i)
413  c_mat[i] = new T[CONST_LEVEL_FIN + 2];
414 
415  _BasisFunsDers(c_mat, Tf, CONST_LEVEL_FIN);
416 
417  // Vel, Acc, ...
418  int idx(1);
419  for (int j(NumCPs_ - 2); j > NumCPs_ - 2 - CONST_LEVEL_FIN; --j) {
420  for (int k(0); k < DIM; ++k) {
421  ini_const[k] = fin[idx * DIM + k];
422 
423  for (int h(idx); h > 0; --h) {
424  ini_const[k] -=
425  c_mat[idx][CONST_LEVEL_FIN + 2 - h] * CPoints_[NumCPs_ - h][k];
426  }
427  CPoints_[j][k] = ini_const[k] / c_mat[idx][CONST_LEVEL_FIN + 1 - idx];
428  }
429  ++idx;
430  }
431  for (int p(0); p < CONST_LEVEL_FIN + 1; ++p) delete[] c_mat[p];
432  SP_SAFE_DELETE_AR(c_mat);
433  }
434 
435  void _PrintCP(int i) {
436  printf("%i th CP check:\n", i);
437  for (int m(0); m < DIM; ++m) {
438  for (int j(0); j < NumCPs_; ++j) {
439  printf("%f \t", CPoints_[j][m]);
440  }
441  printf("\n");
442  }
443  printf("\n");
444  }
445 
446  void _CalcCPoints(T** middle_pt) {
447  for (int i(0); i < NUM_MIDDLE; ++i) {
448  for (int m(0); m < DIM; ++m) {
449  CPoints_[CONST_LEVEL_INI + 1 + i][m] = middle_pt[i][m];
450  }
451  }
452  }
453 
456  int NumCPs_;
457 
458  T Knots_[DEGREE + NUM_MIDDLE + 2 + CONST_LEVEL_INI + CONST_LEVEL_FIN + 1];
459  T CPoints_[NUM_MIDDLE + 2 + CONST_LEVEL_INI + CONST_LEVEL_FIN][DIM];
460 };
461 
462 #endif
T _Right(int i, int j, T u)
Definition: BSplineBasic.h:349
bool _findSpan(int &ret, T u)
Definition: BSplineBasic.h:351
void _PrintCP(int i)
Definition: BSplineBasic.h:435
void _CalcConstrainedCPoints(T *init, T *fin, T Tf)
Definition: BSplineBasic.h:379
bool _BasisFunsDers(T **ders, int span, T u, int n)
Definition: BSplineBasic.h:204
void _CalcCPoints(T **middle_pt)
Definition: BSplineBasic.h:446
void _BasisFuns(T *N, int span, T u)
Definition: BSplineBasic.h:323
int NumKnots_
Definition: BSplineBasic.h:455
bool _CurveDerivsAlg1V(T **CK, T u, int d)
Definition: BSplineBasic.h:165
#define SP_IS_EQUAL(x, y)
Definition: BSplineBasic.h:8
void _BasisFuns(T *N, T u)
Definition: BSplineBasic.h:311
bool getCurvePoint(T u, T *ret)
Definition: BSplineBasic.h:78
T _Left(int i, int j, T u)
Definition: BSplineBasic.h:347
bool _BasisFunsDers(T **ders, T u, int n)
Definition: BSplineBasic.h:195
#define SP_SAFE_DELETE_AR(p)
Definition: BSplineBasic.h:9
bool getCurveDerPoint(T u, int d, T *ret)
Definition: BSplineBasic.h:115
bool SetParam(T *init, T *fin, T **middle_pt, T fin_time)
Definition: BSplineBasic.h:63
T Knots_[DEGREE+NUM_MIDDLE+2+CONST_LEVEL_INI+CONST_LEVEL_FIN+1]
Definition: BSplineBasic.h:458
T CPoints_[NUM_MIDDLE+2+CONST_LEVEL_INI+CONST_LEVEL_FIN][DIM]
Definition: BSplineBasic.h:459
void _CalcKnot(T Tf)
Definition: BSplineBasic.h:143