EEROS  1.0.0.0
API for the EEROS Real-Time Robotics Framework
PathPlannerTrapezoid.hpp
Go to the documentation of this file.
1 #ifndef ORG_EEROS_CONTROL_PATHPLANNER_TRAPEZOID_HPP_
2 #define ORG_EEROS_CONTROL_PATHPLANNER_TRAPEZOID_HPP_
3 
6 #include <eeros/math/Matrix.hpp>
7 #include <eeros/core/System.hpp>
9 #include <mutex>
10 #include <atomic>
11 #include <iostream>
12 #include <fstream>
13 
14 //typedef eeros::math::Matrix<4,1,double> AxisVector;
15 
16 namespace eeros {
17  namespace control {
18 
19  template < typename T = eeros::math::Matrix<1,1,double> >
21  public:
22  PathPlannerTrapezoid(T velMax, T accMax, T decMax, double dt) : velMax(velMax), accMax(accMax), decMax(decMax), dt(dt), posOut(this), velOut(this), accOut(this), jerkOut(this), log('F') {
23  coefficients.zero();
24  coefficients.transpose();
25  posOut.getSignal().clear();
26  velOut.getSignal().clear();
27  accOut.getSignal().clear();
28  jerkOut.getSignal().clear();
29  finished = true;
30  }
32 
33  virtual eeros::control::Output<T>& getPosOut() {return posOut;}
34  virtual eeros::control::Output<T>& getVelOut() {return velOut;}
35  virtual eeros::control::Output<T>& getAccOut() {return accOut;}
36  virtual eeros::control::Output<T>& getJerkOut() {return jerkOut;}
37 
38  virtual void setInitPos(T initPos) {
39  T z;
40  z.zero();
41  std::vector<T> r = std::vector<T>(4);
42  r[0] = initPos;
43  r[1] = z;
44  r[2] = z;
45  r[3] = z;
46 
47  last = r;
48  finished = true;
49  }
50 
51  virtual bool move(T pos, bool jerkLimit = false) {
52  if (!finished) return false;
53  coefficients.zero();
54  positions[0] = pos;
55  this->jerkLimit = jerkLimit;
56  nofPoints = 1;
57  if (calculateCoefficients_fromPosition()) {
58  finished = false;
59  finish_segment = false;
60  t = 0;
61  dTold = 0;
62  k = 0;
63  } else {
64  finished = true;
65  finish_segment = true;
66  t = 0;
67  dTold = 0;
68  k = 0;
69  }
70  return true;
71  }
72 
73  virtual bool move(std::vector<T> pos, bool jerkLimit = false) {
74  if (!finished) return false;
75  coefficients.zero();
76  positions = pos;
77  this->jerkLimit = jerkLimit;
78 
79  // find end of array
80  T zero;
81  zero.zero();
82  int nofPoints = 0;
83 
84  for (int i = 0; i < pos.size(); i++) {
85  if (pos[i] < zero) i = pos.size(); else nofPoints++;
86  }
87 
88  // Safety check, if -1 at end of array missing, don't calculate trajectory
89  // if(nofPoints == array.size()){
90  // std::cout << "return false" << std::endl;
91  // return false;
92  // }
93  this->nofPoints = nofPoints;
94 
95  if (calculateCoefficients_fromPosition()){
96  finished = false;
97  finish_segment = false;
98  t = 0;
99  dTold = 0;
100  k = 0;
101  } else {
102  finished = true;
103  finish_segment = true;
104  t = 0;
105  dTold = 0;
106  k = 0;
107  }
108  return true;
109  }
110 
111  virtual bool move(std::string filename, double timeTot = 1.0, T end_position = 1.0) {
112  if(!finished) return false;
113  coefficients.zero();
114  jerkLimit = false;
115 
116  std::fstream file;
117  file.open(filename, std::fstream::in);
118  if (!file.is_open()) throw Fault("Path planner cannot open path file");
119 
120  std::vector<double> input_time = std::vector<double>(100);
121  std::vector<double> input_jerk = std::vector<double>(100);
122 
123  // set array dimension, time and jerk values
124  int nofPoints = 0;
125  for(int j = 0; j < input_time.size(); j++){
126  file >> input_time[j];
127  file >> input_jerk[j];
128  if (input_time[j] < 0.0) j = input_time.size(); else nofPoints++;
129  }
130  file.close();
131  this->nofPoints = nofPoints;
132 
133  // Norm and scale curve
134  for(int j = 0; j < nofPoints; j++){
135  input_time[j] = input_time[j] * timeTot;
136  input_jerk[j] = input_jerk[j] * end_position[0] / (timeTot*timeTot*timeTot); // TODO end position universal for axisVectors
137  }
138 
139  // TEST
140  bool test = true;
141  if(test == true){
142  double rounded_points_nr = 0;
143  // std::array<double, 100> rounded_input_time;
144  // std::array<double, 100> rounded_input_jerk;
145  // std::array<double, 100> dT;
146  // std::array<double, 100> rest;
147  // std::array<int , 100> rest2;
148  std::vector<double> rounded_input_time = std::vector<double>(100);
149  std::vector<double> rounded_input_jerk = std::vector<double>(100);
150  std::vector<double> dT = std::vector<double>(100);
151  std::vector<double> rest = std::vector<double>(100);
152  std::vector<int> rest2 = std::vector<int>(100);
153 
154  double timePrev = 0.0;
155  for(int j = 0; j < nofPoints; j++){
156  // check if time intervals are multiple of sample time
157  if(j == 0) {dT[j] = input_time[j]; }
158  else {dT[j] = dT[j-1] + input_time[j];}
159 
160  rest[j] = dT[j] / dt;
161  rest2[j] = static_cast<int>(std::floor(rest[j]));
162 
163 
164  double roundDown;
165  if(rest[j] != rest2[j]) {
166  // calculate variation in "next init values" to be saved
167  roundDown = rest2[j]*dt - timePrev;
168  rounded_input_time[rounded_points_nr] = roundDown;
169  rounded_input_jerk[rounded_points_nr] = input_jerk[j];
170 
171  double t1 = dT[j]-timePrev-roundDown;
172  double t2 = (dt-t1);
173  if(j < nofPoints -1) {
174  rounded_input_time[rounded_points_nr+1] = dt;
175  rounded_input_jerk[rounded_points_nr+1] = (input_jerk[j] * t1 + input_jerk[j+1] * t2)/ dt;
176  }
177 
178  // update indexes
179  timePrev = dT[j] + t2;
180  if(j < nofPoints -1) rounded_points_nr = rounded_points_nr + 2;
181  else rounded_points_nr = rounded_points_nr + 1;
182  }
183  else{
184  rounded_input_time[rounded_points_nr] = dT[j] - timePrev; //input_time[j];
185  rounded_input_jerk[rounded_points_nr] = input_jerk[j];
186 
187  // update indexes
188  timePrev = timePrev + rounded_input_time[rounded_points_nr];
189  rounded_points_nr = rounded_points_nr + 1;
190  }
191  }
192  nofPoints = rounded_points_nr;
193 
194  // final settings
195  for(int j = 0; j < nofPoints; j++){
196  input_time[j] = rounded_input_time[j];
197  input_jerk[j] = rounded_input_jerk[j];
198  }
199  }
200  // END TEST
201 
202  // save time and jerk into coefficients
203  int j = 0;
204  while (j < nofPoints) {
205  coefficients(j,0) = input_time[j]; // dT
206  coefficients(j,1) = input_jerk[j]; // cj1
207  j++;
208  }
209 
210  // Calculate coefficients like matlab program
211  calculateCoefficients_fromJerk();
212  finished = false;
213  finish_segment = false;
214  t = 0;
215  dTold = 0;
216  k = 0;
217  return true;
218  }
219 
220  virtual bool endReached() {return finished;}
221 
222  virtual void setMaxSpeed(T speed) {velMax = speed;}
223  virtual void setMaxAcc(T acc) {accMax = acc;}
224  virtual void setMaxDec(T dec) {decMax = dec;}
225 
226  virtual void reset() {
227  finished = true;
228  coefficients.zero();
229  segment_set = false;
230  }
231 
232  virtual void run() {
233  std::vector<T> y = this->last;
234  t += dt;
235 
236  if (!finished) {
237  if (k < segments_nr) {
238  // define coefficients
239  if (segment_set == false) {
240  dT = coefficients(k,0)(0);
241  j_prev = coefficients(k,1);
242  a_prev = coefficients(k,2);
243  v_prev = coefficients(k,3);
244  p_prev = coefficients(k,4);
245  for (int i=0; i<j_prev.size() ;i++) {
246  j0 = 6.0 * coefficients(k,2)(i) / coefficients(k,0)(i);
247  s0 = -12.0 * coefficients(k,2)(i) / (coefficients(k,0)(i)*coefficients(k,0)(i));
248  }
249  segment_set = true;
250  }
251 
252  // define trajectory
253  if (t >= dTold && t < dT + dTold) { }
254  else {
255  finish_segment = true;
256  segment_set = false;
257  dTold = dTold + dT;
258  k++;
259  }
260 
261  y[0] = p_prev + v_prev * dt + (a_prev/2.0) * pow(dt,2) + (j_prev/6.0) * pow(dt,3);
262  y[1] = v_prev + a_prev * dt + (j_prev/2.0) * pow(dt,2);
263  y[2] = a_prev + j_prev * dt;
264 
265  if (jerkLimit)
266  y[2] = (s0 / 2.0) * (t-dTold) * (t-dTold) + j0 * (t-dTold);
267  else
268  y[2] = a_prev + j_prev * dt;
269 
270  y[3] = j_prev;
271 
272  p_prev = y[0];
273  v_prev = y[1];
274  a_prev = y[2];
275  j_prev = y[3];
276  }
277  if (finish_segment == true && k == segments_nr) finished = true;
278  }
279  // set last value
280  this->last[0] = y[0];
281  this->last[1] = y[1];
282  this->last[2] = y[2];
283  this->last[3] = y[3];
284 
285  posOut.getSignal().setValue( y[0]);
286  velOut.getSignal().setValue( y[1]);
287  accOut.getSignal().setValue( y[2]);
288  jerkOut.getSignal().setValue(y[3]);
289 
290  timestamp_t time = System::getTimeNs();
291  posOut.getSignal().setTimestamp( time);
292  velOut.getSignal().setTimestamp( time);
293  accOut.getSignal().setTimestamp( time);
294  jerkOut.getSignal().setTimestamp(time);
295  }
296 
297  private:
298  virtual bool calculateCoefficients_fromPosition() {
299 
300  T zero; zero = 0;
301  for (int k = 0; k < nofPoints; k++) {
302  std::vector<T> start = std::vector<T>(4);
303  if (k == 0) start = last;
304  else start = {positions[k-1], zero, zero, zero};
305 
306  std::vector<T> end = std::vector<T>{positions[k], zero, zero, zero};
307 
308  T calcVelNorm, calcAccNorm, calcDecNorm;
309  double velNorm, accNorm, decNorm, squareNormVel;
310  T distance = end[0] - start[0];
311 
312  if (distance == zero) return false;
313 
314  // Define speeds and accelerations
315  for(unsigned int i = 0; i < calcVelNorm.size(); i++) {
316  calcVelNorm[i] = fabs(velMax[i] / distance[i]);
317  calcAccNorm[i] = fabs(accMax[i] / distance[i]);
318  calcDecNorm[i] = fabs(decMax[i] / distance[i]);
319  }
320 
321  // Init velNorm, accNorm, decNorm and find minimum
322  velNorm = calcVelNorm[0]; accNorm = calcAccNorm[0]; decNorm = calcDecNorm[0];
323  for(unsigned int i = 0; i < calcVelNorm.size(); i++) {
324  if(calcVelNorm[i] < velNorm) velNorm = calcVelNorm[i];
325  if(calcAccNorm[i] < accNorm) accNorm = calcAccNorm[i];
326  if(calcDecNorm[i] < decNorm) decNorm = calcDecNorm[i];
327  }
328 
329  // Minimize velocity
330  squareNormVel = sqrt(2 * (accNorm * decNorm) / (accNorm + decNorm));
331  if(velNorm > squareNormVel) velNorm = squareNormVel;
332 
333  // Calculate time intervals
334  double dT1 = velNorm / accNorm;
335  double dT3 = velNorm / decNorm;
336  double dT2 = 1 / velNorm - (dT1 + dT3) * 0.5;
337  if (dT2 < 0) dT2 = 0;
338 
339  // Adaptation to timestamps
340  dT1 = ceil(dT1 / dt) * dt;
341  dT2 = ceil(dT2 / dt) * dt;
342  dT3 = ceil(dT3 / dt) * dt;
343  // Adaptation of speed to new timestamps
344  velNorm = 1/((dT2 + (dT1 + dT3)*0.5)*dt);
345 
346  T cj1 = 0.0;
347  T cj2 = 0.0;
348  T cj3 = 0.0;
349 
350  T ca1 = velNorm * dt / dT1 * distance;
351  T ca2 = 0.0;
352  T ca3 = velNorm * dt / dT3 * distance * (-1);
353 
354  T cv1 = 0.0;
355  T cv2 = ca1 * dT1;
356  T cv3 = ca1 * dT1 + ca2 * dT2;
357 
358  T cp1;
359  if (k == 0) cp1 = last[0]; else cp1 = positions[k-1];
360  T cp2 = cp1 + cv1 * dT1 + ca1 * dT1 * dT1 / 2.0;
361  T cp3 = cp2 + cv2 * dT2 + ca2 * dT2 * dT2 / 2.0;
362 
363  coefficients(0+k*3,0) = dT1; coefficients(0+k*3,1) = cj1; coefficients(0+k*3,2) = ca1;
364  coefficients(0+k*3,3) = cv1; coefficients(0+k*3,4) = cp1;
365 
366  coefficients(1+k*3,0) = dT2; coefficients(1+k*3,1) = cj2; coefficients(1+k*3,2) = ca2;
367  coefficients(1+k*3,3) = cv2; coefficients(1+k*3,4) = cp2;
368 
369  coefficients(2+k*3,0) = dT3; coefficients(2+k*3,1) = cj3; coefficients(2+k*3,2) = ca3;
370  coefficients(2+k*3,3) = cv3; coefficients(2+k*3,4) = cp3;
371 
372  }
373  segments_nr = nofPoints * 3.0;
374  return true;
375  }
376 
377  virtual bool calculateCoefficients_fromJerk() {
378  for (int k = 0; k < nofPoints; k++) {
379  T cj1, ca1, cv1, cp1;
380  if(k == 0){
381  cj1 = coefficients(k,1);
382  ca1 = last[2]; //[0];
383  cv1 = last[1]; //[0];
384  cp1 = last[0]; //[0];
385  }
386  else{
387  T t_old = coefficients(k-1,0);
388  T j_old = coefficients(k-1,1);
389  T a_old = coefficients(k-1,2);
390  T v_old = coefficients(k-1,3);
391  T p_old = coefficients(k-1,4);
392 
393  cj1 = coefficients(k,1);
394 
395  for(int i=0; i<ca1.size(); i++){
396  ca1(i) = a_old(i) + j_old(i) * t_old(i);
397  cv1(i) = v_old(i) + a_old(i) * t_old(i) + j_old(i) / 2.0 * t_old(i) * t_old(i);
398  cp1(i) = p_old(i) + v_old(i) * t_old(i) + a_old(i) / 2.0 * t_old(i) * t_old(i) + j_old(i) / 6.0 * t_old(i) * t_old(i) * t_old(i);
399  }
400  }
401  coefficients(k,2) = ca1;
402  coefficients(k,3) = cv1;
403  coefficients(k,4) = cp1;
404  }
405  segments_nr = nofPoints;
406  return true;
407  }
408 
413 
414  std::mutex mtx;
415  double dt; // period of the block running
416  double t; // time integrating up with the path planner
417  double dTold;
418  int k = 0;
419  int nofPoints; // nof of points of a given path
420  int segments_nr;
421 
422  std::atomic<bool> finished;
423  bool finish_segment = true;
424  bool segment_set = false;
425  bool jerkLimit = false;
426 
427  T velMax, accMax, decMax;
428  T a_prev, v_prev, p_prev, j_prev;
429  double dT, j0, s0;
430 
431  std::vector<T> last = std::vector<T>(4);
432  std::vector<T> positions = std::vector<T>(100);
433  eeros::math::Matrix<100,5,T> coefficients;
435  };
436  };
437 };
438 
439 #endif /* ORG_EEROS_CONTROL_PATHPLANNER_TRAPEZOID_HPP_ */
Definition: Logger.hpp:15
Matrix< N, M, T > transpose() const
Definition: Matrix.hpp:428
virtual void reset()
Definition: PathPlannerTrapezoid.hpp:226
PathPlannerTrapezoid(T velMax, T accMax, T decMax, double dt)
Definition: PathPlannerTrapezoid.hpp:22
virtual bool move(std::vector< T > pos, bool jerkLimit=false)
Definition: PathPlannerTrapezoid.hpp:73
Definition: Config.hpp:14
static uint64_t getTimeNs()
Definition: System_POSIX.cpp:41
virtual eeros::control::Output< T > & getVelOut()
Definition: PathPlannerTrapezoid.hpp:34
virtual eeros::control::Output< T > & getAccOut()
Definition: PathPlannerTrapezoid.hpp:35
Definition: PathPlannerTrapezoid.hpp:20
Definition: Block.hpp:10
~PathPlannerTrapezoid()
Definition: PathPlannerTrapezoid.hpp:31
virtual bool move(T pos, bool jerkLimit=false)
Definition: PathPlannerTrapezoid.hpp:51
Definition: Output.hpp:11
virtual void setInitPos(T initPos)
Definition: PathPlannerTrapezoid.hpp:38
virtual eeros::control::Output< T > & getPosOut()
Definition: PathPlannerTrapezoid.hpp:33
virtual void setMaxSpeed(T speed)
Definition: PathPlannerTrapezoid.hpp:222
Definition: Fault.hpp:9
virtual void run()
Definition: PathPlannerTrapezoid.hpp:232
virtual void setMaxDec(T dec)
Definition: PathPlannerTrapezoid.hpp:224
void zero()
Definition: Matrix.hpp:52
virtual void setMaxAcc(T acc)
Definition: PathPlannerTrapezoid.hpp:223
virtual bool endReached()
Definition: PathPlannerTrapezoid.hpp:220
virtual bool move(std::string filename, double timeTot=1.0, T end_position=1.0)
Definition: PathPlannerTrapezoid.hpp:111
uint64_t timestamp_t
Definition: types.hpp:12
virtual eeros::control::Output< T > & getJerkOut()
Definition: PathPlannerTrapezoid.hpp:36