ADORe
ADORe is a modular open source software library and toolkit for decision making, planning, control and simulation of automated vehicles
baseline.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  * Daniel Heß - initial API and implementation
13  ********************************************************************************/
14 #pragma once
15 #include <vector>
17 #include <adore/mad/adoremath.h>
18 #include "csaps.h"
20 
21 namespace adore
22 {
23 namespace env
24 {
25 namespace BorderBased
26 {
30 class Baseline
31 {
32  private:
35  double fit_smoothness_;
36  double lookbehind_;
37  double lookahead_;
38  double min_length_;
39  bool valid_;
40  public:
41  csaps::DoubleArray breaks_s_;
42  csaps::DoubleArray breaks_x_;
43  csaps::DoubleArray breaks_y_;
44  csaps::DoubleArray breaks_z_;
45  csaps::DoubleArray samples_s_;
46  csaps::DoubleArray samples_x_;
47  csaps::DoubleArray samples_dx_;
48  csaps::DoubleArray samples_ddx_;
49  csaps::DoubleArray samples_dddx_;
50  csaps::DoubleArray samples_y_;
51  csaps::DoubleArray samples_dy_;
52  csaps::DoubleArray samples_ddy_;
53  csaps::DoubleArray samples_dddy_;
54  csaps::DoubleArray samples_z_;
55  csaps::DoubleArray samples_dz_;
56  csaps::DoubleArray samples_ddz_;
57  csaps::DoubleArray samples_dddz_;
58  csaps::DoubleArray base_L_;
59  csaps::DoubleArray base_nx_;
60  csaps::DoubleArray base_ny_;
61  csaps::DoubleArray base_kappa_;
62  csaps::DoubleArray base_dkappa_;
70 
71  public:
73  {
74  nFitPoints_ = 100;
75  nSamplesPoints_ = 200;
76  fit_smoothness_ = 0.05;
77  lookbehind_ = 100.0;
78  lookahead_ = 100.0;
79  min_length_ = 1.0;
80  valid_ = false;
81  resize();
82  }
83  void resize()
84  {
85  breaks_s_.resize(nFitPoints_);
86  breaks_x_.resize(nFitPoints_);
87  breaks_y_.resize(nFitPoints_);
88  breaks_z_.resize(nFitPoints_);
102  base_L_.resize(nSamplesPoints_);
103  base_nx_.resize(nSamplesPoints_);
104  base_ny_.resize(nSamplesPoints_);
107  position_fct_.setData(dlib::zeros_matrix<double>(4, nSamplesPoints_));
108  normal_fct_.setData(dlib::zeros_matrix<double>(3, nSamplesPoints_));
109  curvature_fct_.setData(dlib::zeros_matrix<double>(2, nSamplesPoints_));
110  curvatureDerivative_fct_.setData(dlib::zeros_matrix<double>(2, nSamplesPoints_));
111  }
112  void setSmoothness(double value){fit_smoothness_=value;}
113  bool isValid()const{return valid_;}
114  double getLookAhead()const{return lookahead_;}
115  double getLookBehind()const{return lookbehind_;}
116  void setLookAhead(double value){lookahead_ = value;}
117  void setLookBehind(double value){lookbehind_ = value;}
118  int getNSamplePoints()const{return nSamplesPoints_;}
119  int getNFitPoints()const{return nFitPoints_;}
125  void update(BorderSequence& borderSequence,double soffset)
126  {
127  valid_ = false;
128  const double total_length = borderSequence.getLength();
129  const double s0 = adore::mad::bound(0.0,soffset-lookbehind_,total_length);
130  const double s1 = adore::mad::bound(s0,soffset+lookahead_,total_length);
131  if(s1-s0<min_length_)return;
132  adore::mad::linspace(s0,s1,breaks_s_,nFitPoints_);//poly breaks
134  double shift = -breaks_s_[0];//start the baseline function at 0
135  for(int i=0;i<nFitPoints_;i++)breaks_s_[i] = breaks_s_[i] + shift;
136  csaps::UnivariateCubicSmoothingSpline fx(breaks_s_,breaks_x_,fit_smoothness_);
137  csaps::UnivariateCubicSmoothingSpline fy(breaks_s_,breaks_y_,fit_smoothness_);
138  csaps::UnivariateCubicSmoothingSpline fz(breaks_s_,breaks_z_,fit_smoothness_);
139  adore::mad::linspace(breaks_s_[0], breaks_s_[nFitPoints_-1], samples_s_, nSamplesPoints_);//samples between poly breaks
143  if(!computeDerivatives())return;
144  for(int i=0;i<nSamplesPoints_;i++)
145  {
146  position_fct_.getData()(0,i) = base_L_[i];
147  normal_fct_.getData()(0,i) = base_L_[i];
148  curvature_fct_.getData()(0,i) = base_L_[i];
150  position_fct_.getData()(1,i) = samples_x_[i];
151  position_fct_.getData()(2,i) = samples_y_[i];
152  position_fct_.getData()(3,i) = samples_z_[i];
153  normal_fct_.getData()(1,i) = base_nx_[i];
154  normal_fct_.getData()(2,i) = base_ny_[i];
155  curvature_fct_.getData()(1,i) = base_kappa_[i];
157  }
158  valid_ = true;
159  }
160 
162  {
163  base_L_[0] = 0.0;
164  for(int i=0;i<nSamplesPoints_-1;i++)
165  {
166  const double dx = samples_x_[i+1]-samples_x_[i];
167  const double dy = samples_y_[i+1]-samples_y_[i];
168  const double dL = std::sqrt(dx*dx+dy*dy);
169  base_L_[i+1] = base_L_[i] + dL;//use for x(s(L))
170  }
171  for(int i=0;i<nSamplesPoints_;i++)
172  {
173  const double dxds = samples_dx_[i];
174  const double dyds = samples_dy_[i];
175  const double ddxdss = samples_ddx_[i];
176  const double ddydss = samples_ddy_[i];
177  const double dddxdsss = samples_dddx_[i];
178  const double dddydsss = samples_dddy_[i];
179  const double v = std::sqrt(dxds*dxds+dyds*dyds);//v=dL/ds
180  if(v<1.0e-10)return false;//there is a kink in the poly
181  const double dvds = (ddxdss*dxds+ddydss*dyds) / v;
182  const double nx = -dyds/v;
183  const double ny = dxds/v;
184  const double kappa = (ddydss*dxds-ddxdss*dyds)/(v*v*v);
185  const double dkappads = kappa * dvds/v + (dddydsss*dxds-dddxdsss*dyds)/(v*v*v);
186  const double dkappadL = dkappads/v;
187  base_nx_[i] = nx;
188  base_ny_[i] = ny;
189  base_kappa_[i] = kappa;
190  base_dkappa_[i] = dkappadL;
191  }
192  return true;
193  }
194 
199  int defineOffset(BorderSequence& borderSequence,function_type_scalar* offset,double maximum_offset=10.0)
200  {
201  if((int)offset->getData().nc()!=nSamplesPoints_)
202  {
203  offset->setData(dlib::zeros_matrix<double>(2, nSamplesPoints_));
204  }
205  bool allow_backwards_steps = false;//@TODO if allowing backwards steps: slower computation but able to handle curve center in lane
206  double x0,y0,z0,x1,y1,z1,xa,xb,nx0,ny0,nx1,ny1;
207  bool xa_inside,xb_inside;
208  auto current_index = borderSequence.beginLines();
209  auto end_index = borderSequence.endLines();
210  int faults = 0;
211  for(int i=0;i<nSamplesPoints_;i++)
212  {
213  bool hit = false;
214  auto it = current_index;
215  for(;!hit && it!=end_index;it++)
216  {
217  it.getValue(x0,y0,z0,x1,y1,z1);
218  nx0 = samples_x_[i]-maximum_offset*base_nx_[i];
219  ny0 = samples_y_[i]-maximum_offset*base_ny_[i];
220  nx1 = samples_x_[i]+maximum_offset*base_nx_[i];
221  ny1 = samples_y_[i]+maximum_offset*base_ny_[i];
222  adore::mad::intersectLines(nx0,ny0,nx1,ny1,x0,y0,x1,y1,
223  xa,xb,xa_inside,xb_inside);
224  hit = xa_inside&&xb_inside;
225  if(hit)break;
226  }
227  offset->getData()(0,i) = base_L_[i];
228  if(hit)
229  {
230  if(!allow_backwards_steps)current_index = it;
231  offset->getData()(1,i) = xa*2.0*maximum_offset-maximum_offset;
232  }
233  else
234  {
235  offset->getData()(1,i) = 0.0;
236  faults++;
237  }
238 
239  }
240  return faults;
241  }
242 };
243 }
244 }
245 }
A local, non-linear, smooth road coordinate system generated from a sequence of borders.
Definition: baseline.h:31
int getNSamplePoints() const
Definition: baseline.h:118
int defineOffset(BorderSequence &borderSequence, function_type_scalar *offset, double maximum_offset=10.0)
define a function, which represents the offset from baseline to the neighboring function
Definition: baseline.h:199
csaps::DoubleArray samples_dx_
Definition: baseline.h:47
void update(BorderSequence &borderSequence, double soffset)
compute fit for borderSequence
Definition: baseline.h:125
csaps::DoubleArray breaks_z_
Definition: baseline.h:44
function_type2d normal_fct_
Definition: baseline.h:67
bool valid_
Definition: baseline.h:39
void resize()
Definition: baseline.h:83
csaps::DoubleArray base_L_
Definition: baseline.h:58
csaps::DoubleArray base_kappa_
Definition: baseline.h:61
csaps::DoubleArray base_nx_
Definition: baseline.h:59
void setSmoothness(double value)
Definition: baseline.h:112
Baseline()
Definition: baseline.h:72
void setLookBehind(double value)
Definition: baseline.h:117
double getLookAhead() const
Definition: baseline.h:114
csaps::DoubleArray breaks_y_
Definition: baseline.h:43
csaps::DoubleArray samples_y_
Definition: baseline.h:50
double getLookBehind() const
Definition: baseline.h:115
csaps::DoubleArray samples_z_
Definition: baseline.h:54
function_type_scalar curvatureDerivative_fct_
Definition: baseline.h:69
double lookahead_
Definition: baseline.h:37
csaps::DoubleArray breaks_s_
Definition: baseline.h:41
csaps::DoubleArray samples_s_
Definition: baseline.h:45
bool computeDerivatives()
Definition: baseline.h:161
csaps::DoubleArray samples_dz_
Definition: baseline.h:55
int getNFitPoints() const
Definition: baseline.h:119
double fit_smoothness_
Definition: baseline.h:35
csaps::DoubleArray samples_dddy_
Definition: baseline.h:53
double min_length_
Definition: baseline.h:38
csaps::DoubleArray samples_ddz_
Definition: baseline.h:56
csaps::DoubleArray samples_dddz_
Definition: baseline.h:57
void setLookAhead(double value)
Definition: baseline.h:116
double lookbehind_
Definition: baseline.h:36
csaps::DoubleArray breaks_x_
Definition: baseline.h:42
int nFitPoints_
Definition: baseline.h:33
int nSamplesPoints_
Definition: baseline.h:34
function_type_xyz position_fct_
Definition: baseline.h:66
csaps::DoubleArray base_dkappa_
Definition: baseline.h:62
csaps::DoubleArray samples_ddx_
Definition: baseline.h:48
csaps::DoubleArray samples_dddx_
Definition: baseline.h:49
bool isValid() const
Definition: baseline.h:113
csaps::DoubleArray samples_dy_
Definition: baseline.h:51
csaps::DoubleArray samples_ddy_
Definition: baseline.h:52
function_type_scalar curvature_fct_
Definition: baseline.h:68
csaps::DoubleArray samples_x_
Definition: baseline.h:46
csaps::DoubleArray base_ny_
Definition: baseline.h:60
A class which augments a vector of Border* with some sampling features.
Definition: bordersequence.h:28
bool sample(TArray1 sample_array, int i0, int i1, TArray2 &outx, TArray2 &outy, TArray2 &outz)
step through border sequence and sample the values along the borders
Definition: bordersequence.h:57
LineIterator beginLines()
Definition: bordersequence.h:203
double getLength() const
returns the total lenght of all contained borders
Definition: bordersequence.h:36
LineIterator endLines()
Definition: bordersequence.h:204
void setData(const adoreMatrix< T, n+1, 0 > &data)
Definition: llinearpiecewisefunction.h:580
adoreMatrix< T, n+1, 0 > & getData()
Definition: llinearpiecewisefunction.h:147
bool intersectLines(T a, T b, T c, T d, T e, T f, T g, T h, T &x0, T &x1, bool &x0_inside, bool &x1_inside)
Definition: adoremath.h:522
adore::mad::LLinearPiecewiseFunctionM< double, 3 > function_type_xyz
Definition: linearfunctiontypedefs.h:22
adore::mad::LLinearPiecewiseFunctionM< double, 1 > function_type_scalar
Definition: linearfunctiontypedefs.h:24
adoreMatrix< T, 1, n > linspace(T x0, T x1)
Definition: adoremath.h:91
T bound(T lb, T value, T ub)
Definition: adoremath.h:569
adore::mad::LLinearPiecewiseFunctionM< double, 2 > function_type2d
Definition: linearfunctiontypedefs.h:23
x0
Definition: adore_set_goal.py:25
y0
Definition: adore_set_goal.py:26
z0
Definition: adore_set_goal.py:27
y1
Definition: adore_set_pose.py:29
x1
Definition: adore_set_pose.py:28
z1
Definition: adore_set_pose.py:30
Definition: areaofeffectconverter.h:20
void getValue(double &x0, double &y0, double &z0, double &x1, double &y1, double &z1)
Definition: bordersequence.h:175