spline_functions.cpp
Go to the documentation of this file.
1 /*
2  * UOS-ROS packages - Robot Operating System code by the University of Osnabrück
3  * Copyright (C) 2010 University of Osnabrück
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * spline_functions.cpp
20  *
21  * Created on: 28.01.2011
22  * Author: Martin Günther <mguenthe@uos.de>
23  */
24 
26 
27 namespace katana
28 {
29 inline void generatePowers(int n, double x, double* powers)
30 {
31  powers[0] = 1.0;
32  for (int i = 1; i <= n; i++)
33  {
34  powers[i] = powers[i - 1] * x;
35  }
36 }
37 
38 void sampleCubicSpline(const std::vector<double>& coefficients, double time, double& position, double& velocity,
39  double& acceleration)
40 {
41  // create powers of time:
42  double t[4];
43  generatePowers(3, time, t);
44 
45  position = t[0] * coefficients[0] + t[1] * coefficients[1] + t[2] * coefficients[2] + t[3] * coefficients[3];
46  velocity = t[0] * coefficients[1] + 2.0 * t[1] * coefficients[2] + 3.0 * t[2] * coefficients[3];
47  acceleration = 2.0 * t[0] * coefficients[2] + 6.0 * t[1] * coefficients[3];
48 }
49 
50 void getCubicSplineCoefficients(double start_pos, double start_vel, double end_pos, double end_vel, double time,
51  std::vector<double>& coefficients)
52 {
53  coefficients.resize(4);
54 
55  if (time == 0.0)
56  {
57  coefficients[0] = end_pos;
58  coefficients[1] = end_vel;
59  coefficients[2] = 0.0;
60  coefficients[3] = 0.0;
61  }
62  else
63  {
64  double T[4];
65  generatePowers(3, time, T);
66 
67  coefficients[0] = start_pos;
68  coefficients[1] = start_vel;
69  coefficients[2] = (-3.0 * start_pos + 3.0 * end_pos - 2.0 * start_vel * T[1] - end_vel * T[1]) / T[2];
70  coefficients[3] = (2.0 * start_pos - 2.0 * end_pos + start_vel * T[1] + end_vel * T[1]) / T[3];
71  }
72 }
73 
74 // copied from KNI
75 void splineCoefficients(int steps, double *timearray, double *encoderarray, double *arr_p1, double *arr_p2,
76  double *arr_p3, double *arr_p4)
77 {
78 
79  int i, j; // counter variables
80 
81  // calculate time differences between points and b-coefficients
82  double deltatime[steps];
83  double b[steps];
84  for (i = 0; i < steps; i++)
85  {
86  deltatime[i] = timearray[i + 1] - timearray[i];
87  b[i] = 1.0 / deltatime[i];
88  }
89 
90  // calculate a-coefficients
91  double a[steps - 1];
92  for (i = 0; i < (steps - 1); i++)
93  {
94  a[i] = (2 / deltatime[i]) + (2 / deltatime[i + 1]);
95  }
96 
97  // build up the right hand side of the linear system
98  double c[steps];
99  double d[steps + 1];
100  d[0] = 0; // f_1' and f_n' equal zero
101  d[steps] = 0;
102  for (i = 0; i < steps; i++)
103  {
104  c[i] = (encoderarray[i + 1] - encoderarray[i]) / (deltatime[i] * deltatime[i]);
105  }
106  for (i = 0; i < (steps - 1); i++)
107  {
108  d[i + 1] = 3 * (c[i] + c[i + 1]);
109  }
110 
111  // compose A * f' = d
112  double Alin[steps - 1][steps]; // last column of Alin is right hand side
113 
114  // fill with zeros
115  for (i = 0; i < (steps - 1); i++)
116  {
117  for (j = 0; j < steps; j++)
118  {
119  Alin[i][j] = 0.0;
120  }
121  }
122  // insert values
123  for (i = 0; i < (steps - 1); i++)
124  {
125  if (i == 0)
126  {
127  Alin[0][0] = a[0];
128  Alin[0][1] = b[1];
129  Alin[0][steps - 1] = d[1];
130  }
131  else
132  {
133  Alin[i][i - 1] = b[i];
134  Alin[i][i] = a[i];
135  Alin[i][i + 1] = b[i + 1];
136  Alin[i][steps - 1] = d[i + 1];
137  }
138  }
139 
140  // solve linear equation
141  boost::numeric::ublas::matrix<double> ublas_A(steps - 1, steps - 1);
142  boost::numeric::ublas::matrix<double> ublas_b(steps - 1, 1);
143  for (i = 0; i < (steps - 1); i++)
144  {
145  for (j = 0; j < (steps - 1); j++)
146  {
147  ublas_A(i, j) = Alin[i][j];
148  }
149  ublas_b(i, 0) = Alin[i][steps - 1];
150  }
151  boost::numeric::ublas::permutation_matrix<unsigned int> piv(steps - 1);
152  lu_factorize(ublas_A, piv);
153  lu_substitute(ublas_A, piv, ublas_b);
154 
155  // save result in derivatives array
156  double derivatives[steps + 1];
157  derivatives[0] = 0;
158  for (i = 0; i < (steps - 1); i++)
159  {
160  derivatives[i + 1] = ublas_b(i, 0);
161  }
162  derivatives[steps] = 0;
163  // build the hermite polynom with difference scheme
164  // Q(t) = a0 + (b0 + (c0 + d0 * t) * (t - 1)) * t = a0 + (b0 - c0) * t +
165  // (c0 - d0) * t^2 + d0 * t^3 = p0 + p1 * t + p2 * t^2 + p3 * t^3
166  double a0, b0, c0, d0;
167  for (i = 0; i < steps; i++)
168  {
169  a0 = encoderarray[i];
170  b0 = encoderarray[i + 1] - a0;
171  c0 = b0 - deltatime[i] * derivatives[i];
172  d0 = deltatime[i] * (derivatives[i + 1] + derivatives[i]) - 2 * b0;
173  arr_p1[i] = a0;
174  arr_p2[i] = b0 - c0;
175  arr_p3[i] = c0 - d0;
176  arr_p4[i] = d0;
177 
178  // added MG: normalize to segment duration (of course we could do some simplifications here)
179  arr_p2[i] = arr_p2[i] / deltatime[i];
180  arr_p3[i] = arr_p3[i] / pow(deltatime[i], 2);
181  arr_p4[i] = arr_p4[i] / pow(deltatime[i], 3);
182  }
183 }
184 
185 void sampleSplineWithTimeBounds(const std::vector<double>& coefficients, double duration, double time,
186  double& position, double& velocity, double& acceleration)
187 {
188  if (time < 0)
189  {
190  double _;
191  sampleCubicSpline(coefficients, 0.0, position, _, _);
192  velocity = 0;
193  acceleration = 0;
194  }
195  else if (time > duration)
196  {
197  double _;
198  sampleCubicSpline(coefficients, duration, position, _, _);
199  velocity = 0;
200  acceleration = 0;
201  }
202  else
203  {
204  sampleCubicSpline(coefficients, time, position, velocity, acceleration);
205  }
206 }
207 
208 } // namespace katana
d
void sampleCubicSpline(const std::vector< double > &coefficients, double time, double &position, double &velocity, double &acceleration)
Samples a cubic spline segment at a particular time.
void getCubicSplineCoefficients(double start_pos, double start_vel, double end_pos, double end_vel, double time, std::vector< double > &coefficients)
void splineCoefficients(int steps, double *timearray, double *encoderarray, double *arr_p1, double *arr_p2, double *arr_p3, double *arr_p4)
void generatePowers(int n, double x, double *powers)
FloatVector FloatVector * a
void sampleSplineWithTimeBounds(const std::vector< double > &coefficients, double duration, double time, double &position, double &velocity, double &acceleration)


katana
Author(s): Martin Günther
autogenerated on Fri Jun 7 2019 22:06:58