ocra-recipes
Doxygen documentation for the ocra-recipes repository
ExperimentalTrajectory.cpp
Go to the documentation of this file.
1 
3 #include <math.h>
4 
5 #ifndef ALPHA_L
6 #define ALPHA_L 1.0
7 #endif
8 
9 namespace ocra
10 {
11 
13 {
14  numberOfKernels = nWaypoints;
15 
16  maxCovariance = ( waypoints - waypoints.rowwise().mean().replicate(1, waypoints.cols()) ).array().square().rowwise().sum() / (waypoints.cols() - 1) ;
17 
18 
19  kernelCenters = Eigen::VectorXd::Zero(numberOfKernels);
20  for(int i=0; i<numberOfKernels-1; i++){
21  kernelCenters(i+1) = kernelCenters(i) + pointToPointDurationVector(i);
22  }
23 
24  designMatrix = kernelFunction(kernelCenters);
25  designMatrixInv = designMatrix.inverse();
26 
27 
28 
29  calculateRbfnWeights();
30  varianceStartTrigger = true;
31 
32  // std::cout << "rbfn weights: " << rbfnWeights << std::endl;
33  // std::cout << "maxCovariance\n" << maxCovariance << std::endl;
34  // std::cout << "kernelLengthParameter\n" << kernelLengthParameter << std::endl;
35  // std::cout << "kernelCenters\n" << kernelCenters << std::endl;
36 
37 }
38 
40 {
41  Eigen::MatrixXd dataMat = Eigen::MatrixXd::Zero(nWaypoints, nDoF+1);
42 
43  dataMat.col(0) = kernelCenters;
44  dataMat.rightCols(nDoF) = waypoints.transpose();
45 
46  return dataMat;
47 }
48 
49 
50 Eigen::MatrixXd ExperimentalTrajectory::kernelFunction(double m)
51 {
52  int nC = kernelCenters.rows();
53  int nS = maxCovariance.rows();
54 
55  Eigen::VectorXd kern = ((-(m - kernelCenters.array()).array().square()) / kernelLengthParameter).array().exp();
56 
57  Eigen::MatrixXd result = (maxCovariance.transpose().replicate(nC, 1)).array() * kern.replicate(1, nS).array();
58 
59  Eigen::MatrixXd blockDiagonalResult = Eigen::MatrixXd::Zero(nS, (nS*nC));
60 
61  for(int i=0; i<result.rows(); i++)
62  {
63  blockDiagonalResult.block(0, i*nS, nS, nS) = result.row(i).asDiagonal();
64  }
65 
66  return blockDiagonalResult;
67 
68 }
69 
70 Eigen::MatrixXd ExperimentalTrajectory::kernelFunction(Eigen::VectorXd& evalVec)
71 {
72  int sizeVec = evalVec.rows();
73  int nC = kernelCenters.rows();
74  int nS = maxCovariance.rows();
75 
76  Eigen::MatrixXd blockDiagonalResult = Eigen::MatrixXd::Zero((nS*sizeVec), (nS*nC));
77 
78  for(int i=0; i<sizeVec; i++)
79  {
80  blockDiagonalResult.middleRows(i*nS, nS) = kernelFunction(evalVec(i));
81  }
82 
83  return blockDiagonalResult;
84 
85 }
86 
87 
88 Eigen::VectorXd ExperimentalTrajectory::rbfnKernelFunction(double m)
89 {
90  return ((-(m - kernelCenters.array()).array().square()).array() / kernelLengthParameter).array().exp();
91 }
92 
93 Eigen::MatrixXd ExperimentalTrajectory::rbfnKernelFunction(Eigen::VectorXd& evalVec)
94 {
95  int sizeVec = evalVec.rows();
96  int nC = kernelCenters.rows();
97 
98  Eigen::MatrixXd centersMat = kernelCenters.transpose().replicate(sizeVec,1);
99  Eigen::MatrixXd evalMat = evalVec.replicate(1,nC);
100 
101  return ((-(evalMat - centersMat).array().square()).array() / kernelLengthParameter).array().exp();
102 }
103 
104 
105 void ExperimentalTrajectory::calculateRbfnWeights()
106 {
107  int nC = kernelCenters.rows();
108  Eigen::MatrixXd rbfnDesignMatrix = rbfnKernelFunction(kernelCenters);
109  // rbfnWeights = Eigen::MatrixXd::Zero(nDoF, nC);
110  Eigen::MatrixXd wayTrans = waypoints.transpose();
111 
112  // std::cout << "phi = " << rbfnDesignMatrix.rows() << " x " << rbfnDesignMatrix.cols() << std::endl;
113  // std::cout << "way = " << wayTrans.rows()<< " x " << wayTrans.cols() << std::endl;
114  Eigen::MatrixXd A = rbfnDesignMatrix * rbfnDesignMatrix.transpose();
115  // std::cout << "A = " << A.rows()<< " x " << A.cols() << std::endl;
116 
117  Eigen::MatrixXd b = rbfnDesignMatrix * wayTrans;
118 
119  // std::cout << "b = " << b.rows()<< " x " << b.cols() << std::endl;
120 
121 
122  // rbfnWeights = (A.inverse() * b).transpose(); // the transpose makes weights = nDoF x nCenters which is better for the output function.
123 
124  // rbfnWeights = A.fullPivLu().solve(b).transpose();
125  rbfnWeights = rbfnDesignMatrix.fullPivLu().solve(wayTrans).transpose();
126  // std::cout << "rbfn weights:\n" << rbfnWeights << std::endl;
127 
128 }
129 
130 Eigen::VectorXd ExperimentalTrajectory::getRbfnOutput(double m)
131 {
132  Eigen::VectorXd phi = rbfnKernelFunction(m);
133  return rbfnWeights * phi;
134 }
135 
136 Eigen::MatrixXd ExperimentalTrajectory::getRbfnOutput(Eigen::VectorXd& evalVec)
137 {
138  Eigen::MatrixXd phi = rbfnKernelFunction(evalVec);
139  return rbfnWeights * phi;
140 }
141 
142 
143 
144 void ExperimentalTrajectory::precalculateTrajectory(double DT, Eigen::MatrixXd& _path, Eigen::VectorXd& _timeline)
145 {
146  double currentTime = 0.0;
147 
148  int numberOfDataPoints = ceil((pointToPointDurationVector.sum() / DT)*2);
149 
150  Eigen::MatrixXd path(numberOfDataPoints, nDoF);
151  Eigen::VectorXd timeline(numberOfDataPoints);
152 
153 
154  int index = 0;
155  startTrigger = true;
157  while (!trajectoryFinished)
158  {
159  path.row(index) = getDesiredValues(currentTime).col(POS_INDEX).transpose();
160  timeline(index) = currentTime;
161  currentTime += DT;
162  index++;
163  }
164  // reset values to their original state
165  startTrigger = true;
167  trajectoryFinished = false;
168 
169  _path = path.topRows(index);
170  _timeline = timeline.head(index);
171 
172 
173 }
174 
175 Eigen::MatrixXd ExperimentalTrajectory::getDesiredValues(double _time)
176 {
182  Eigen::MatrixXd desiredValue = Eigen::MatrixXd::Zero(nDoF, TRAJ_DIM);
183 
184  if (startTrigger)
185  {
186  startTrigger = false;
187  t0 = _time;
188  desiredValue.col(POS_INDEX) = waypoints.col(0);
189  desiredValue.col(VEL_INDEX) = Eigen::VectorXd::Zero(nDoF);
190  desiredValue.col(ACC_INDEX) = Eigen::VectorXd::Zero(nDoF);
191 
192  posOld = desiredValue.col(POS_INDEX);
193  velOld = desiredValue.col(VEL_INDEX);
194 
195  // posOld = waypoints.col(0);
196  // velOld =Eigen::VectorXd::Zero(nDoF);
197  t_old = t0;
198 
199  // return desiredValue;
200  }
201 
202  else
203  {
204  double t = _time - t0;
205 
206  if (t<=kernelCenters.maxCoeff())
207  {
208  desiredValue.col(POS_INDEX) = getRbfnOutput(t);
209  }
210  else
211  {
212  desiredValue.col(POS_INDEX) = waypoints.rightCols(1);
213  }
214 
215  double delta_t = t-t_old;
216  desiredValue.col(VEL_INDEX) = (desiredValue.col(POS_INDEX) - posOld) / delta_t;
217  desiredValue.col(ACC_INDEX) = (desiredValue.col(VEL_INDEX) - velOld) / delta_t;
218 
219  posOld = desiredValue.col(POS_INDEX);
220  velOld = desiredValue.col(VEL_INDEX);
221  t_old = t;
222  }
223 
224 
225 
226  return desiredValue;
227 }
228 
229 Eigen::VectorXd ExperimentalTrajectory::getVariance(double time)
230 {
231  if (varianceStartTrigger) {
232  t0_variance = time;
233  varianceStartTrigger = false;
234  }
235 
236 
237  double t = time - t0_variance;
238 
239 
240  Eigen::VectorXd variance;
241 
242  if (t<=pointToPointDurationVector.sum()) {
243  Eigen::MatrixXd Ks = kernelFunction(t);
244  variance = maxCovariance - (Ks * designMatrixInv * Ks.transpose()).diagonal();
245  }
246  else{
247  variance = Eigen::VectorXd::Zero(maxCovariance.rows());
248  }
249 
250  return variance;
251 }
252 
253 void ExperimentalTrajectory::getDesiredValues(double time, Eigen::MatrixXd& desiredValues, Eigen::VectorXd& variance)
254 {
255  desiredValues = getDesiredValues(time);
256  variance = getVariance(time);
257 
258 }
259 
260 void ExperimentalTrajectory::getDesiredValues(double _time, Eigen::Displacementd& _position, Eigen::Twistd& _velocity, Eigen::Twistd& _acceleration)
261 {
262 
263 
264 }
265 
266 
268 {
269  originalWaypoints = waypoints;
270  kernelLengthParameter = pointToPointDurationVector.mean();
271  // Add a waypoint to the end.
272  int extraWaypoints = 1;
273  int nStartWp = extraWaypoints;
274  int nEndWp = extraWaypoints;
275 
276  int nWpNew = nWaypoints + nStartWp + nEndWp;
277 
278  Eigen::MatrixXd waypointsTmp = Eigen::MatrixXd::Zero(nDoF, nWpNew);
279 
280  waypointsTmp.leftCols(nStartWp) = waypoints.leftCols(1).replicate(1,nStartWp);
281  waypointsTmp.middleCols(nStartWp, nWaypoints) = waypoints;
282  waypointsTmp.rightCols(nEndWp) = waypoints.rightCols(1).replicate(1,nEndWp);
283 
284  waypoints.resize(nDoF, nWaypoints);
285  waypoints = waypointsTmp;
286  // std::cout << pointToPointDurationVector << std::endl;
287 
288 
289  Eigen::VectorXd durationVectorTmp = Eigen::VectorXd::Zero(nWpNew-1);
290 
291  double extraWpDt = 0.01 * kernelLengthParameter;
292  // double extraWpDt = 0.01 * pointToPointDurationVector.sum();
293  // std::cout << "extraWpDt: " << extraWpDt << std::endl;
294 
295  durationVectorTmp.head(nStartWp) = Eigen::VectorXd::Constant(nStartWp, extraWpDt);
296  durationVectorTmp.segment(nStartWp, nWaypoints-1) = pointToPointDurationVector;
297  durationVectorTmp.tail(nEndWp) = Eigen::VectorXd::Constant(nEndWp, extraWpDt);
298 
299  pointToPointDurationVector.resize(durationVectorTmp.size());
300  pointToPointDurationVector = durationVectorTmp;
301 
302  nWaypoints = nWpNew;
303 
304  std::cout << pointToPointDurationVector << std::endl;
306 }
307 
308 
310 {
311  return maxCovariance.maxCoeff();
312 }
313 void ExperimentalTrajectory::reinitialize()
314 {
315  nWaypoints = waypoints.cols();
316  startTrigger = true;
317 
318  kernelLengthParameter = pointToPointDurationVector.segment(1,pointToPointDurationVector.rows()-2).mean();
319  pointToPointDurationVector(0) = 0.01 * kernelLengthParameter;
320  pointToPointDurationVector.tail(1) << 0.01 * kernelLengthParameter;
321 
322 
324 }
325 
326 
327 void ExperimentalTrajectory::addNewWaypoint(Eigen::VectorXd newWaypoint, double waypointTime)
328 {
329  std::cout << "Adding waypoint at: " << waypointTime << " seconds..." << std::endl;
330 
331  if ( (newWaypoint.rows() == nDoF) && (waypointTime>=0.0) && (waypointTime<=kernelCenters.maxCoeff()) )
332  {
333  //Find out where the new T falls...
334  for (int i=0; i<kernelCenters.size(); i++)
335  {
336  std::cout << "i = " << i << std::endl;
337  if (kernelCenters(i)>waypointTime) {
338  youngestWaypointIndex=i;
339  std::cout << "youngestWaypointIndex" << youngestWaypointIndex << std::endl;
340  i = kernelCenters.size();
341  }
342  }
343 
344 
345  Eigen::MatrixXd newWaypointsMat = Eigen::MatrixXd::Zero(nDoF, nWaypoints+1);
346  newWaypointsMat.leftCols(youngestWaypointIndex) = waypoints.leftCols(youngestWaypointIndex);
347  newWaypointsMat.col(youngestWaypointIndex) = newWaypoint;
348  newWaypointsMat.rightCols(nWaypoints - youngestWaypointIndex) = waypoints.rightCols(nWaypoints - youngestWaypointIndex);
349 
350  waypoints.resize(nDoF, nWaypoints+1);
351  waypoints = newWaypointsMat;
352 
353  Eigen::VectorXd durationVectorTmp = Eigen::VectorXd::Zero(nWaypoints);
354 
355  std::cout << "\npointToPointDurationVector\n " << pointToPointDurationVector << std::endl;
356 
357  durationVectorTmp.head(youngestWaypointIndex-1) = pointToPointDurationVector.head(youngestWaypointIndex-1);
358  durationVectorTmp.row(youngestWaypointIndex-1) << waypointTime - kernelCenters(youngestWaypointIndex-1);
359  durationVectorTmp.tail(nWaypoints - youngestWaypointIndex) = pointToPointDurationVector.tail(nWaypoints - youngestWaypointIndex);
360 
361  pointToPointDurationVector.resize(durationVectorTmp.size());
362  pointToPointDurationVector = durationVectorTmp;
363 
364  std::cout << "\npointToPointDurationVector\n " << pointToPointDurationVector << std::endl;
365 
366 
367  reinitialize();
368 
369 
370  }
371  else{
372  if (newWaypoint.rows() != nDoF){
373  std::cout << "[ERROR] (ExperimentalTrajectory::addNewWaypoint): New waypoint is not the right size. Should have dim = " <<nDoF << "x1." << std::endl;
374  }
375  if ((waypointTime<=0.0) || (waypointTime>=kernelCenters.maxCoeff())){
376  std::cout << "[ERROR] (ExperimentalTrajectory::addNewWaypoint): New waypoint time is out of time bounds. Should have fall between 0.0 and " << kernelCenters.maxCoeff() << " seconds." << std::endl;
377  }
378  }
379 
380 
381 }
382 
384 {
385  removeWaypoint(youngestWaypointIndex);
386 }
387 
389 {
390  std::cout << "Removing waypoint index: " << index << "..." << std::endl;
391  if ( (index>=0) && (index<nWaypoints) )
392  {
393  Eigen::MatrixXd newWaypointsMat = Eigen::MatrixXd::Zero(nDoF, nWaypoints-1);
394 
395  newWaypointsMat.leftCols(index) = waypoints.leftCols(index);
396  newWaypointsMat.rightCols(nWaypoints-1-index) = waypoints.rightCols(nWaypoints-1-index);
397 
398  waypoints.resize(nDoF, nWaypoints-1);
399  waypoints = newWaypointsMat;
400 
401  Eigen::VectorXd durationVectorTmp = Eigen::VectorXd::Zero(nWaypoints-2);
402 
403  int durVecIndex = index;
404  durationVectorTmp.head(durVecIndex) = pointToPointDurationVector.head(durVecIndex);
405  durationVectorTmp.tail(nWaypoints -1 -durVecIndex) = pointToPointDurationVector.tail(nWaypoints -1 -durVecIndex);
406 
407  pointToPointDurationVector.resize(durationVectorTmp.size());
408  pointToPointDurationVector = durationVectorTmp;
409 
410 
411  reinitialize();
412  }
413  else{
414  std::cout << "[ERROR] (ExperimentalTrajectory::addNewWaypoint): New waypoint time is out of index bounds. Should have fall between 0 and " << nWaypoints-1 << "." << std::endl;
415  }
416 
417 }
418 
419 
420 
422 {
423  int nSteps = 1000;
424  int nC = kernelCenters.rows();
425  double startTime = kernelCenters(0);
426  double endTime = kernelCenters.tail(1)(0);
427  Eigen::VectorXd timeVec = Eigen::VectorXd::LinSpaced(nSteps, startTime, endTime);
428 
429  Eigen::MatrixXd res(timeVec.rows(), nC+1);
430  res.col(0) = timeVec;
431  res.rightCols(nC) = rbfnKernelFunction(timeVec);
432 
433  return res;
434 }
435 
436 
437 
438 
439 } //namespace ocra
bool trajectoryFinished
Definition: Trajectory.h:130
Eigen::VectorXd getVariance(double time)
int currentWaypointIndex
Definition: Trajectory.h:122
#define VEL_INDEX
Definition: Trajectory.h:21
#define TRAJ_DIM
Definition: Trajectory.h:24
Eigen::MatrixXd waypoints
Definition: Trajectory.h:117
Eigen::VectorXd pointToPointDurationVector
Definition: Trajectory.h:126
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
#define ACC_INDEX
Definition: Trajectory.h:22
Eigen::MatrixXd getDesiredValues(double time)
#define POS_INDEX
Definition: Trajectory.h:20
void addNewWaypoint(Eigen::VectorXd newWaypoint, double waypointTime)