00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <katana/spline_functions.h>
00026
00027 namespace katana
00028 {
00029 inline void generatePowers(int n, double x, double* powers)
00030 {
00031 powers[0] = 1.0;
00032 for (int i = 1; i <= n; i++)
00033 {
00034 powers[i] = powers[i - 1] * x;
00035 }
00036 }
00037
00038 void sampleCubicSpline(const std::vector<double>& coefficients, double time, double& position, double& velocity,
00039 double& acceleration)
00040 {
00041
00042 double t[4];
00043 generatePowers(3, time, t);
00044
00045 position = t[0] * coefficients[0] + t[1] * coefficients[1] + t[2] * coefficients[2] + t[3] * coefficients[3];
00046 velocity = t[0] * coefficients[1] + 2.0 * t[1] * coefficients[2] + 3.0 * t[2] * coefficients[3];
00047 acceleration = 2.0 * t[0] * coefficients[2] + 6.0 * t[1] * coefficients[3];
00048 }
00049
00050 void getCubicSplineCoefficients(double start_pos, double start_vel, double end_pos, double end_vel, double time,
00051 std::vector<double>& coefficients)
00052 {
00053 coefficients.resize(4);
00054
00055 if (time == 0.0)
00056 {
00057 coefficients[0] = end_pos;
00058 coefficients[1] = end_vel;
00059 coefficients[2] = 0.0;
00060 coefficients[3] = 0.0;
00061 }
00062 else
00063 {
00064 double T[4];
00065 generatePowers(3, time, T);
00066
00067 coefficients[0] = start_pos;
00068 coefficients[1] = start_vel;
00069 coefficients[2] = (-3.0 * start_pos + 3.0 * end_pos - 2.0 * start_vel * T[1] - end_vel * T[1]) / T[2];
00070 coefficients[3] = (2.0 * start_pos - 2.0 * end_pos + start_vel * T[1] + end_vel * T[1]) / T[3];
00071 }
00072 }
00073
00074
00075 void splineCoefficients(int steps, double *timearray, double *encoderarray, double *arr_p1, double *arr_p2,
00076 double *arr_p3, double *arr_p4)
00077 {
00078
00079 int i, j;
00080
00081
00082 double deltatime[steps];
00083 double b[steps];
00084 for (i = 0; i < steps; i++)
00085 {
00086 deltatime[i] = timearray[i + 1] - timearray[i];
00087 b[i] = 1.0 / deltatime[i];
00088 }
00089
00090
00091 double a[steps - 1];
00092 for (i = 0; i < (steps - 1); i++)
00093 {
00094 a[i] = (2 / deltatime[i]) + (2 / deltatime[i + 1]);
00095 }
00096
00097
00098 double c[steps];
00099 double d[steps + 1];
00100 d[0] = 0;
00101 d[steps] = 0;
00102 for (i = 0; i < steps; i++)
00103 {
00104 c[i] = (encoderarray[i + 1] - encoderarray[i]) / (deltatime[i] * deltatime[i]);
00105 }
00106 for (i = 0; i < (steps - 1); i++)
00107 {
00108 d[i + 1] = 3 * (c[i] + c[i + 1]);
00109 }
00110
00111
00112 double Alin[steps - 1][steps];
00113
00114
00115 for (i = 0; i < (steps - 1); i++)
00116 {
00117 for (j = 0; j < steps; j++)
00118 {
00119 Alin[i][j] = 0.0;
00120 }
00121 }
00122
00123 for (i = 0; i < (steps - 1); i++)
00124 {
00125 if (i == 0)
00126 {
00127 Alin[0][0] = a[0];
00128 Alin[0][1] = b[1];
00129 Alin[0][steps - 1] = d[1];
00130 }
00131 else
00132 {
00133 Alin[i][i - 1] = b[i];
00134 Alin[i][i] = a[i];
00135 Alin[i][i + 1] = b[i + 1];
00136 Alin[i][steps - 1] = d[i + 1];
00137 }
00138 }
00139
00140
00141 boost::numeric::ublas::matrix<double> ublas_A(steps - 1, steps - 1);
00142 boost::numeric::ublas::matrix<double> ublas_b(steps - 1, 1);
00143 for (i = 0; i < (steps - 1); i++)
00144 {
00145 for (j = 0; j < (steps - 1); j++)
00146 {
00147 ublas_A(i, j) = Alin[i][j];
00148 }
00149 ublas_b(i, 0) = Alin[i][steps - 1];
00150 }
00151 boost::numeric::ublas::permutation_matrix<unsigned int> piv(steps - 1);
00152 lu_factorize(ublas_A, piv);
00153 lu_substitute(ublas_A, piv, ublas_b);
00154
00155
00156 double derivatives[steps + 1];
00157 derivatives[0] = 0;
00158 for (i = 0; i < (steps - 1); i++)
00159 {
00160 derivatives[i + 1] = ublas_b(i, 0);
00161 }
00162 derivatives[steps] = 0;
00163
00164
00165
00166 double a0, b0, c0, d0;
00167 for (i = 0; i < steps; i++)
00168 {
00169 a0 = encoderarray[i];
00170 b0 = encoderarray[i + 1] - a0;
00171 c0 = b0 - deltatime[i] * derivatives[i];
00172 d0 = deltatime[i] * (derivatives[i + 1] + derivatives[i]) - 2 * b0;
00173 arr_p1[i] = a0;
00174 arr_p2[i] = b0 - c0;
00175 arr_p3[i] = c0 - d0;
00176 arr_p4[i] = d0;
00177
00178
00179 arr_p2[i] = arr_p2[i] / deltatime[i];
00180 arr_p3[i] = arr_p3[i] / pow(deltatime[i], 2);
00181 arr_p4[i] = arr_p4[i] / pow(deltatime[i], 3);
00182 }
00183 }
00184
00185 void sampleSplineWithTimeBounds(const std::vector<double>& coefficients, double duration, double time,
00186 double& position, double& velocity, double& acceleration)
00187 {
00188 if (time < 0)
00189 {
00190 double _;
00191 sampleCubicSpline(coefficients, 0.0, position, _, _);
00192 velocity = 0;
00193 acceleration = 0;
00194 }
00195 else if (time > duration)
00196 {
00197 double _;
00198 sampleCubicSpline(coefficients, duration, position, _, _);
00199 velocity = 0;
00200 acceleration = 0;
00201 }
00202 else
00203 {
00204 sampleCubicSpline(coefficients, time, position, velocity, acceleration);
00205 }
00206 }
00207
00208 }