ADORe
ADORe is a modular open source software library and toolkit for decision making, planning, control and simulation of automated vehicles
cubicpiecewisefunctionstatic.h
Go to the documentation of this file.
1 /********************************************************************************
2  * Copyright (C) 2017-2020 German Aerospace Center (DLR).
3  * Eclipse ADORe, Automated Driving Open Research https://eclipse.org/adore
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License 2.0 which is available at
7  * http://www.eclipse.org/legal/epl-2.0.
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  * Reza Dariani - initial API and implementation
13  ********************************************************************************/
14 
15 #pragma once
17 
18 #include <dlib/matrix.h>
19 
20 namespace adore
21 {
22  namespace mad
23  {
31  template<int N>//NumberOfBreak==NumberOfInputPoints==NumberOfPolynomials+1
33  {
34  public:
35  double breaks[N];
36  double coef_1[N-1];
37  double coef_2[N-1];
38  double coef_3[N-1];
39  double coef_4[N-1];
40 
41  private:
42  inline void evaluate1(int i,int j,double *input_x,double *output_y,double *output_dy=0,double *output_ddy=0,double *output_dddy=0)
43  {
44  double local_x = (input_x[i]-breaks[j]);
45  output_y[i]=((((coef_1[j]*local_x+coef_2[j])*local_x)+coef_3[j])*local_x)+coef_4[j];
46  if(output_dy)
47  {
48  output_dy[i]=(((3*coef_1[j]*local_x+2*coef_2[j])*local_x)+coef_3[j]);
49  if(output_ddy)
50  {
51  output_ddy[i]=6*coef_1[j]*local_x+2*coef_2[j];
52  if(output_ddy)
53  {
54  output_dddy[i]=6*coef_1[j];
55  }
56  }
57  }
58  }
59  public:
60 
61  void evaluate(int outN,double *input_x,double *output_y,double *output_dy=0,double *output_ddy=0,double *output_dddy=0)
62  {
63  double eps=1e-20;
64  double inf=1.0/eps;
65  //intermediate variables
66  int localIndex[outN];//the poly index for each x value
67  //local search algprithm
68  for ( int i=0;i<outN;i++)
69  {
70  for (int j=0;j<N;j++)
71  {
72  if( input_x[i]+eps >= breaks[j] || j==0 )
73  {
74  if( j==N-1 || input_x[i]+eps < breaks[j+1] )
75  {
76  localIndex[i]=j;
77  }
78  }
79  }
80  }
81 
82  //interplation
83  for (int i=0;i<outN;i++)
84  {
85  evaluate1(i,localIndex[i],input_x,output_y,output_dy,output_ddy,output_dddy);
86  }
87  }
88 
92  void evaluate_ordered(int outN,double *input_x,double *output_y,double *output_dy=0,double *output_ddy=0,double *output_dddy=0)
93  {
94  int j=0;//the break index
95  for (int i=0;i<outN;i++)//the input index
96  {
97  while( j<N-1 && input_x[i] > breaks[j+1] ) j++;
98  evaluate1(i,j,input_x,output_y,output_dy,output_ddy,output_dddy);
99  }
100  }
101 
109  void fit(double *input_x,double *input_y,double *input_w, double smoothingFactor)
110  {
111  //step by step info : /adore/mad/src/cubic_piecewise_function.cpp
112  //intermediate variables
113  double dx[N-1];
114  double oneDivDx[N-1];
115  double dy[N-1];
116  double DyDx[N-1];
117  ArrayMatrixTools::diff(dx,input_x,N);
118  ArrayMatrixTools::diff(dy,input_y,N);
119  for(int i=0;i<N-1;i++){oneDivDx[i]=1.0/dx[i];}
120  ArrayMatrixTools::pointwise_multiply(DyDx,oneDivDx,dy,N-1);//dy/dx
121 
122  double dx1n_2[N-2]; //dx from 1 --> N-2
123  double dx0n_3[N-2]; //dx from 0 --> N-3
124  double dx2x1n_20n_3[N-2]; //2*(dx1n_2+dx0n_3)
125  ArrayMatrixTools::pieceOfArray(dx1n_2,dx,1,N-2);
126  ArrayMatrixTools::pieceOfArray(dx0n_3,dx,0,N-3);
127  for(int i=0;i<N-2;i++){ dx2x1n_20n_3[i]=2*(dx1n_2[i]+dx0n_3[i]);}
128 
129  //sparse matrix intermediate variables
130  double sp_dx1n_2 [(N-2)*(N-2)];
131  double sp_dx0n_3 [(N-2)*(N-2)];
132  double sp_dx2x1n_20n_3 [(N-2)*(N-2)];
133  ArrayMatrixTools::sparseDiagonalMatrix(sp_dx1n_2,dx1n_2,N-2,N-2,N-2,-1);
134  ArrayMatrixTools::sparseDiagonalMatrix(sp_dx0n_3,dx0n_3,N-2,N-2,N-2,1);
135  ArrayMatrixTools::sparseDiagonalMatrix(sp_dx2x1n_20n_3,dx2x1n_20n_3,N-2,N-2,N-2,0);
136 
137  double R[(N-2)*(N-2)];
138  for(int i=0; i<N-2;i++) //data are from 1-->n-2 or 0-->n-3 this is why there is an extrea -2 in i<n-2-2
139  {
140  for(int j=0; j<N-2;j++)
141  {
142  R[i*(N-2)+j]=sp_dx1n_2[i*(N-2)+j]+sp_dx0n_3[i*(N-2)+j]+sp_dx2x1n_20n_3[i*(N-2)+j];
143  }
144  }
145  //intermediate variables
146  double oneDivDx1n_2[N-2];
147  double oneDivDx0n_3[N-2];
148  double oneDivDx_1n_20n_3[N-2];
149 
150  ArrayMatrixTools::pieceOfArray(oneDivDx1n_2,oneDivDx,1,N-2);
151  ArrayMatrixTools::pieceOfArray(oneDivDx0n_3,oneDivDx,0,N-3);
152  for(int i=0;i<N-2;i++){
153  oneDivDx_1n_20n_3[i]=-1*(oneDivDx1n_2[i]+oneDivDx0n_3[i]);}
154 
155  //sparse matrix intermediate variables
156  double sp_oneDivDx1n_2[(N-2)*(N)];
157  double sp_oneDivDx0n_3[(N-2)*(N)];
158  double sp_oneDivDx_1n_20n_3[(N-2)*(N)];
159  ArrayMatrixTools::sparseDiagonalMatrix(sp_oneDivDx1n_2,oneDivDx1n_2,N-2,N,N-2,2);
160  ArrayMatrixTools::sparseDiagonalMatrix(sp_oneDivDx0n_3,oneDivDx0n_3,N-2,N,N-2,0);
161  ArrayMatrixTools::sparseDiagonalMatrix(sp_oneDivDx_1n_20n_3,oneDivDx_1n_20n_3,N-2,N,N-2,1);
162 
163  //Qt and its transpose (see wiki link)
164  double Qt[(N-2)*(N)];
165  double QtT[(N)*(N-2)];
166 
167  for(int i=0; i<N-2;i++) //data are from 1-->n-2 or 0-->n-3 this is why there is an extrea -2 in i<n-2-2
168  {
169  for(int j=0; j<N;j++)
170  {
171  Qt[i*(N)+j]=sp_oneDivDx1n_2[i*(N)+j]+sp_oneDivDx0n_3[i*(N)+j]+sp_oneDivDx_1n_20n_3[i*(N)+j];
172  }
173  }
174 
175  //intermediate variables
176  double D[N];
177  double sp_D[N*N];
178  double QtD[(N-2)*N];
179  double QtDQ[(N-2)*(N-2)];
180  //double temp_M[(N-2)*(N-2)];
181  for(int i=0;i<N;i++) { D[i]=1.0/input_w[i];}
182 
184  ArrayMatrixTools::transpose(QtT,Qt,N-2,N);
185  ArrayMatrixTools::matrixMultiplication(QtD,Qt,N-2,N,sp_D,N,N);
186  ArrayMatrixTools::matrixMultiplication(QtDQ,QtD,N-2,N,QtT,N,N-2);
187 
188  //intermediate matrix definition (dlib will be used to calculated matrix inverse)
189  dlib::matrix<double> M(N-2,N-2);
190  dlib::matrix<double> inv_M;
191  for(int i=0; i<(N-2);i++){
192  for(int j=0; j<(N-2); j++){
193  M(i,j)=6*(1-smoothingFactor)*QtDQ[i*(N-2)+j]+smoothingFactor*R[i*(N-2)+j];
194  }
195  }
196  inv_M=dlib::inv(M);
197 
198  //intermediate variables (dlib matrix ---> array )
199  double temp_invM[(N-2)*(N-2)];
200 
201  for(int i=0; i<(N-2);i++)
202  {
203  for(int j=0; j<(N-2); j++)
204  {
205  temp_invM[i*(N-2)+j]=inv_M(i,j);
206  }
207  }
208  //intermediate variables
209  double diff_DyDx[N-2];
210  double u[N-2];
211  double u_n[N]; //in order to add zero at beginning and at the end
212  double diff_u_n[N-1];
213 
214  ArrayMatrixTools::diff(diff_DyDx,DyDx,N-1);
215  ArrayMatrixTools::matrixMultiplication(u,temp_invM,N-2,N-2,diff_DyDx,N-2,1);
216  u_n[0]=0; //at beggining
217  u_n[N-1]=0; //at end
218  for(int i=0; i<N-2; i++) {u_n[i+1]=u[i];}
219  ArrayMatrixTools::diff(diff_u_n,u_n,N); // matlab equivalent --> diff([zeros(1,yd); u; zeros(1,yd)])
220 
221  //intermediate variables
222  double diff_u_n_oneDivDx [N-1];
223  double diff_unoneDivDx_n1[N+1]; //to add a zero at beggining and the end (needed for diff)
224  double diff2_unoneDivDx_n1[N];
225  ArrayMatrixTools::pointwise_multiply(diff_u_n_oneDivDx,diff_u_n,oneDivDx,N-1); // matlab equivalent -->diff([zeros(1,yd); u; zeros(1,yd)])./dx(:,dd)
226  diff_unoneDivDx_n1[0]=0; //at beginning
227  diff_unoneDivDx_n1[N]=0; //at end
228  for(int i=0; i<N-1; i++) {diff_unoneDivDx_n1[i+1]=diff_u_n_oneDivDx[i];}
229  ArrayMatrixTools::diff(diff2_unoneDivDx_n1,diff_unoneDivDx_n1,N+1);
230 
231  //Finaly calculating smooth y
232  double yi[N];
233  for(int i=0; i<N; i++)
234  {
235  yi[i]=input_y[i]-(6*(1-smoothingFactor))*sp_D[i*N+i]*diff2_unoneDivDx_n1[i];
236  }
237 
238  //Converting y to cubic coeeficients which results is y = coef1*h^3 + coef2*h^2 + coef3*h + coef4
239 
240  //intermediate varialbles
241  double c3[N];
242  double diff_yi[N-1];
243  double diff_c3[N-1];
244  double c2[N-1];
245 
246  c3[0]=0;
247  c3[N-1]=0;
248  for(int i=0; i<N-2; i++) {c3[i+1]=u[i]*smoothingFactor;}
249  ArrayMatrixTools::diff(diff_yi,yi,N);
250  for(int i=0; i<N-1; i++) {c2[i]=diff_yi[i]*oneDivDx[i]-dx[i]*(2*c3[i]+c3[i+1]);}
251  ArrayMatrixTools::diff(diff_c3,c3,N);
252  for(int i=0; i<N-1; i++)
253  {
254  breaks[i] = input_x[i];
255  coef_1[i]=diff_c3[i]*oneDivDx[i];
256  coef_2[i]=3*c3[i];
257  coef_3[i] = c2[i];
258  coef_4[i] = yi[i];
259  }
260  breaks[N-1] = input_x [N-1];
261 
262  }
263 
264 
265 
266  };
267  }
268 }
static void pieceOfArray(T *output, T *input, int start, int end)
Definition: arraymatrixtools.h:360
static void transpose(T *output, T *input, int input_row, int input_column)
Definition: arraymatrixtools.h:298
static void pointwise_multiply(T *output, T *input_1, T *input_2, int inputSize)
Definition: arraymatrixtools.h:345
static void diff(T *output, T *input, int inputSize)
Definition: arraymatrixtools.h:75
static void sparseDiagonalMatrix(T *sparse, T *input, int output_row, int output_column, int inputSize, int StartingReference)
Definition: arraymatrixtools.h:379
static void matrixMultiplication(double *output, double *input_1, int input_1_row, int input_1_column, double *input_2, int input_2_row, int input_2_column)
Definition: arraymatrixtools.h:318
Definition: cubicpiecewisefunctionstatic.h:33
void evaluate1(int i, int j, double *input_x, double *output_y, double *output_dy=0, double *output_ddy=0, double *output_dddy=0)
Definition: cubicpiecewisefunctionstatic.h:42
double coef_4[N-1]
Definition: cubicpiecewisefunctionstatic.h:39
void fit(double *input_x, double *input_y, double *input_w, double smoothingFactor)
Definition: cubicpiecewisefunctionstatic.h:109
double breaks[N]
Definition: cubicpiecewisefunctionstatic.h:35
double coef_1[N-1]
Definition: cubicpiecewisefunctionstatic.h:36
double coef_2[N-1]
Definition: cubicpiecewisefunctionstatic.h:37
void evaluate_ordered(int outN, double *input_x, double *output_y, double *output_dy=0, double *output_ddy=0, double *output_dddy=0)
Definition: cubicpiecewisefunctionstatic.h:92
void evaluate(int outN, double *input_x, double *output_y, double *output_dy=0, double *output_ddy=0, double *output_dddy=0)
Definition: cubicpiecewisefunctionstatic.h:61
double coef_3[N-1]
Definition: cubicpiecewisefunctionstatic.h:38
const double inf
Definition: cubic_piecewise_function.cpp:17
const double eps
Definition: cubic_piecewise_function.cpp:16
Definition: areaofeffectconverter.h:20