param_func_spline0_dist.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Software License Agreement (BSD License) *
3  * Copyright (C) 2016 by Horatiu George Todoran <todorangrg@gmail.com> *
4  * *
5  * Redistribution and use in source and binary forms, with or without *
6  * modification, are permitted provided that the following conditions *
7  * are met: *
8  * *
9  * 1. Redistributions of source code must retain the above copyright *
10  * notice, this list of conditions and the following disclaimer. *
11  * 2. Redistributions in binary form must reproduce the above copyright *
12  * notice, this list of conditions and the following disclaimer in *
13  * the documentation and/or other materials provided with the *
14  * distribution. *
15  * 3. Neither the name of the copyright holder nor the names of its *
16  * contributors may be used to endorse or promote products derived *
17  * from this software without specific prior written permission. *
18  * *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY *
29  * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
30  * POSSIBILITY OF SUCH DAMAGE. *
31  ***************************************************************************/
32 
34 #include <tuw_control/utils.h>
35 
36 #include <float.h>
37 #include <math.h>
38 #include <algorithm>
39 
40 #include <iostream>
41 
42 using namespace tuw;
43 using namespace std;
44 
46 
47 void ParamFuncsSpline0Dist::setDistCfMode(TraveledDistCfMode _distCfMode, const vector<std::size_t>& _distRelFuncIdx)
48 {
49  distCfMode_ = _distCfMode;
50  distRelFuncIdx_ = _distRelFuncIdx;
51  switch (distCfMode_)
52  {
53  case TDM::NONE:
54  break;
55  case TDM::V:
56  distLinkedFuncIdx_.resize(1, _distRelFuncIdx[0]);
57  distEvalCache_.resize(funcCtrlPt_[_distRelFuncIdx[0]].size(), 0);
58  computeSFuncPtr_ = &ParamFuncsSpline0Dist::computeS_V;
59  computeDs2DtPtr_ = &ParamFuncsSpline0Dist::computeT_V;
60  distLinkedArcIdx_ = func2Arc_[_distRelFuncIdx[0]];
61  break;
62  case TDM::AV:
63  distLinkedFuncIdx_.resize(1, _distRelFuncIdx[0]);
64  distEvalCache_.resize(funcCtrlPt_[_distRelFuncIdx[0]].size(), 0);
65  computeSFuncPtr_ = &ParamFuncsSpline0Dist::computeS_AV;
66  computeDs2DtPtr_ = &ParamFuncsSpline0Dist::computeT_AV;
67  distLinkedArcIdx_ = func2Arc_[_distRelFuncIdx[0]];
68  break;
69  }
70 }
71 
73 {
74  initImpl();
75  setDistCfMode(_other.distCfMode_, _other.distRelFuncIdx_);
76 }
77 ParamFuncsSpline0Dist& ParamFuncsSpline0Dist::operator=(const ParamFuncsSpline0Dist& _other)
78 {
79  ParamFuncsDist::operator=(_other);
80  setDistCfMode(_other.distCfMode_, _other.distRelFuncIdx_);
81  return *this;
82 }
83 
84 void ParamFuncsSpline0Dist::precomputeDist()
85 {
86  if (distCfMode_ == TDM::NONE)
87  {
88  return;
89  }
90 
91  const size_t& func0Idx = distLinkedFuncIdx_[0];
92  const size_t ctrlPtSize = funcCtrlPt_[func0Idx].size() - 1;
93  distEvalCache_[0] = 0;
94  for (size_t funcCtrlPtIdx = 0; funcCtrlPtIdx < ctrlPtSize; ++funcCtrlPtIdx)
95  {
96  funcsArcEval_ = ctrlPtVal(func0Idx, funcCtrlPtIdx + 1, CtrlPtDim::ARC);
97  funcEvalArcCacheIdxUnder_[distLinkedArcIdx_] = funcCtrlPtIdx;
98  distEvalCache_[funcCtrlPtIdx + 1] = computeS();
99  }
100  setEvalArc(funcsArcBegin_, EvalArcGuarantee::AT_BEGIN);
101 }
102 
103 double ParamFuncsSpline0Dist::computeS() const
104 {
105  return (this->*computeSFuncPtr_)();
106 }
107 double ParamFuncsSpline0Dist::computeS_V() const
108 {
109  const size_t& funcIdx = distLinkedFuncIdx_[0];
110  const FuncCacheData& cacheData =
111  funcEvalCache_[funcIdx][funcEvalArcCacheIdxUnder_[func2Arc_[funcIdx]]]; //*funcEvalCacheIter_[funcIdx];
112  return distEvalCache_[funcEvalArcCacheIdxUnder_[distLinkedArcIdx_]] +
113  computeDeltaS_V_AV(funcsArcEval_ - cacheData.arc, cacheData.val, computeFuncDiff1(funcIdx));
114 }
115 
116 double ParamFuncsSpline0Dist::computeS_AV() const
117 {
118  const size_t& funcIdx = distLinkedFuncIdx_[0];
119  const FuncCacheData& cacheData =
120  funcEvalCache_[funcIdx][funcEvalArcCacheIdxUnder_[func2Arc_[funcIdx]]]; //*funcEvalCacheIter_[funcIdx];
121  return distEvalCache_[funcEvalArcCacheIdxUnder_[distLinkedArcIdx_]] +
122  computeDeltaS_V_AV(funcsArcEval_ - cacheData.arc, computeFuncInt1(funcIdx), cacheData.val);
123 }
124 
125 void ParamFuncsSpline0Dist::computeS2TLattice(const double& _arc0, const double& _ds, vector<double>& _tLattice)
126 {
127  setEvalArc(_arc0, EvalArcGuarantee::NONE);
128  size_t iEnd = distEvalCache_.back() / _ds;
129  if (((double)iEnd < distEvalCache_.back() / _ds))
130  {
131  iEnd++;
132  }
133  _tLattice.clear();
134  _tLattice.reserve(iEnd + 2);
135  const int idxBeforeStart = static_cast<int>(computeS() / _ds);
136 
137  setEvalDist(_ds * (idxBeforeStart), EvalArcGuarantee::AFTER_LAST);
138  _tLattice.emplace_back(fmin(funcsArcEval_, funcsArcEnd_));
139  for (size_t i = idxBeforeStart + 1; i < iEnd; ++i)
140  {
141  setEvalDist(_ds * (i), EvalArcGuarantee::AFTER_LAST);
142  _tLattice.emplace_back(
143  fmin(fmax(funcsArcEval_, nextafterf(_tLattice.back(), FLT_MAX)), nextafterf(funcsArcEnd_, -FLT_MAX)));
144  }
145  if (_tLattice.back() < funcsArcEnd_)
146  {
147  _tLattice.emplace_back(funcsArcEnd_);
148  }
149  setEvalArc(funcsArcBegin_, EvalArcGuarantee::AT_BEGIN);
150 }
151 
152 void ParamFuncsSpline0Dist::computeS2TLattice(const vector<double>& _sLattice, vector<double>& _tLattice)
153 {
154  const size_t slSize = _sLattice.size();
155  _tLattice.clear();
156  _tLattice.reserve(_sLattice.size());
157 
158  if (slSize > 0)
159  {
160  size_t i = 0;
161  setEvalDist(_sLattice[i], EvalArcGuarantee::NONE);
162  while ((funcsArcEval_ < funcsArcEnd_) && (i + 1 < slSize))
163  {
164  _tLattice.emplace_back(funcsArcEval_);
165  setEvalDist(_sLattice[++i], EvalArcGuarantee::AFTER_LAST);
166  }
167  }
168  _tLattice.emplace_back(funcsArcEnd_);
169  setEvalArc(funcsArcBegin_, EvalArcGuarantee::AT_BEGIN);
170 }
171 void ParamFuncsSpline0Dist::setEvalDist(const double& _funcsDistEval, const EvalArcGuarantee& _evalArcGuarantee)
172 {
173  setEvalArc(computeTImpl(_funcsDistEval, _evalArcGuarantee), _evalArcGuarantee);
174 }
175 
176 double ParamFuncsSpline0Dist::computeT(const double& _s, const EvalArcGuarantee& _evalArcGuarantee)
177 {
178  size_t& arcIdx = funcEvalArcCacheIdxUnder_[distLinkedArcIdx_];
179 
180  const size_t cacheCtrlPtIdxRestore = arcIdx;
181  const size_t cacheArcEvalRestore = funcsArcEval_;
182 
183  double resultT = computeTImpl(_s, _evalArcGuarantee);
184 
185  arcIdx = cacheCtrlPtIdxRestore;
186  funcsArcEval_ = cacheArcEvalRestore;
187 
188  return resultT;
189 }
190 
191 double ParamFuncsSpline0Dist::computeTImpl(const double& _s, const EvalArcGuarantee& _evalArcGuarantee)
192 {
193  using eag = EvalArcGuarantee;
194  size_t& arcCacheIdx = funcEvalArcCacheIdxUnder_[distLinkedArcIdx_];
195  const size_t ctrlPtSize = funcCtrlPt_[distLinkedFuncIdx_[0]].size();
196 
197  switch (_evalArcGuarantee)
198  {
199  case eag::AFTER_LAST:
200  while (distEvalCache_[arcCacheIdx] <= _s)
201  {
202  if (++arcCacheIdx >= ctrlPtSize)
203  {
204  break;
205  }
206  }
207  --arcCacheIdx;
208  break;
209  case eag::AT_BEGIN:
210  arcCacheIdx = 0;
211  break;
212  case eag::AT_END:
213  arcCacheIdx = funcCtrlPt_[distLinkedFuncIdx_[0]].size() - 1;
214  break;
215  case eag::NONE:
216  arcCacheIdx = distance(distEvalCache_.begin(), upper_bound(distEvalCache_.begin(), distEvalCache_.end(), _s)) - 1;
217  break;
218  case eag::BEFORE_LAST:
219  while (distEvalCache_[arcCacheIdx] > _s)
220  {
221  if (arcCacheIdx == 0)
222  {
223  break;
224  }
225  --arcCacheIdx;
226  }
227  break;
228  }
229  funcsArcEval_ = ctrlPtVal(distLinkedFuncIdx_[0], arcCacheIdx, CtrlPtDim::ARC);
230  const double ds = _s - distEvalCache_[arcCacheIdx];
231  const double retVal = funcsArcEval_ + (this->*computeDs2DtPtr_)(ds);
232  return retVal;
233 }
234 double ParamFuncsSpline0Dist::computeT_V(const double& _ds) const
235 {
236  const size_t& funcIdx = distLinkedFuncIdx_[0];
237  return computeDeltaT_V_AV(_ds, computeFuncVal(funcIdx), computeFuncDiff1(funcIdx));
238 }
239 double ParamFuncsSpline0Dist::computeT_AV(const double& _ds) const
240 {
241  const size_t& funcIdx = distLinkedFuncIdx_[0];
242  return computeDeltaT_V_AV(_ds, computeFuncInt1(funcIdx), computeFuncVal(funcIdx));
243 }
244 
245 double ParamFuncsSpline0Dist::computeDeltaS_V_AV(const double& _dt, const double& _v0, const double& _av)
246 {
247  const double dtAbs = fabs(_dt);
248  if (dtAbs < 10 * FLT_MIN)
249  {
250  return 0;
251  }
252  const double vAbs = fabs(_v0);
253  if (fabs(_av) < 10 * FLT_MIN)
254  {
255  return vAbs * _dt;
256  }
257  const double v1 = _v0 + _av * dtAbs;
258  if (signum(v1) == signum(_v0))
259  {
260  return fabs(_v0 + v1) * _dt / 2.;
261  }
262  else
263  {
264  int retSign = 1;
265  if (_dt < 0)
266  {
267  retSign = -1;
268  }
269  double dt1 = -_v0 / _av;
270  return retSign * (vAbs * dt1 + fabs(v1) * (dtAbs - dt1)) / 2.;
271  }
272 }
273 double ParamFuncsSpline0Dist::computeDeltaT_V_AV(const double& _ds, const double& _v0, const double& _av)
274 {
275  double v0 = _v0, av = _av;
276  if (v0 < 0)
277  {
278  av *= -1;
279  v0 *= -1;
280  }
281  if (fabs(av) < 10 * FLT_MIN)
282  {
283  return _ds / v0;
284  }
285 
286  int retSign = -1;
287  if (_ds < 0)
288  {
289  retSign = +1;
290  }
291  const double v0v0 = v0 * v0;
292 
293  double delta = v0v0 + 2. * av * fabs(_ds);
294  if (delta < 0)
295  {
296  return retSign * (+v0 + sqrt(-delta)) / av;
297  }
298  else
299  {
300  return retSign * (+v0 - sqrt(delta)) / av;
301  }
302 }
TraveledDistCfMode distCfMode_
Closed form distance computation mode.
TraveledDistCfMode
Required type of traveled distance computation relative to the parametric function.
double computeS_V() const
Computes distance on a piecewise linear function describing the center linear velocity.
void setDistCfMode(TraveledDistCfMode _distCfMode, const std::vector< std::size_t > &_distRelFuncIdx) override
double computeT_V(const double &_ds) const
Computes arc parametrization on a piecewise linear function describing the center linear velocity at ...
Helper function needed to upgrade c++ 2011.
Definition: utils.h:193
double computeT_AV(const double &_ds) const
Computes arc parametrization on a piecewise linear function describing the center linear acceleration...
EvalArcGuarantee
Flags if any guarantees about evaluation arc relative to last evaluation arc are present.
Definition: param_func.h:80
agent base center linear velocity is parametric function
agent base center linear acceleration is parametric function
ParamFuncsSpline0Dist::TraveledDistCfMode TDM
EvalArcGuarantee
Flags if any guarantees about evaluation arc relative to last evaluation arc are present.
Definition: param_func.hpp:61
Extends manipulation of parametric functions collection with closed-form arc length (distance) comput...
constexpr int signum(T x, std::false_type is_signed)
Definition: utils.h:45
double computeS_AV() const
Computes distance on a piecewise linear function describing the center linear acceleration.
std::vector< std::size_t > distRelFuncIdx_


tuw_control
Author(s): George Todoran
autogenerated on Mon Feb 28 2022 23:52:16