DMP_BBO library
Trajectory.cpp
Go to the documentation of this file.
1 
24 #include "dmp/Trajectory.hpp"
25 
27 
28 #include <fstream>
29 #include <iostream>
30 #include <vector>
31 #include <eigen3/Eigen/Core>
32 
33 
34 using namespace std;
35 using namespace Eigen;
36 
37 namespace DmpBbo {
38 
39 Trajectory::Trajectory(void)
40 {
41 }
42 
43 Trajectory::Trajectory(const Eigen::VectorXd& ts, const Eigen::MatrixXd& ys, const Eigen::MatrixXd& yds, const Eigen::MatrixXd& ydds, const Eigen::MatrixXd& misc)
44 : ts_(ts), ys_(ys), yds_(yds), ydds_(ydds), misc_(misc)
45 {
46  int n_time_steps = ts_.rows();
47  assert(n_time_steps==ys_.rows());
48  assert(n_time_steps==yds_.rows());
49  assert(n_time_steps==ydds_.rows());
50  if (misc_.cols()==0)
51  misc_ = MatrixXd(n_time_steps,0);
52  assert(n_time_steps==misc_.rows());
53 
54 #ifndef NDEBUG // Variables below are only required for asserts; check for NDEBUG to avoid warnings.
55  int n_dims = ys_.cols();
56  assert(n_dims==yds_.cols());
57  assert(n_dims==ydds_.cols());
58 #endif
59 
60 }
61 
62 void Trajectory::set_misc(const Eigen::MatrixXd& misc)
63 {
64  if (misc.rows()==ts_.size())
65  {
66  // misc is of size n_time_steps X n_dims_misc
67  misc_ = misc;
68  }
69  else if (misc.rows()==1)
70  {
71  // misc is of size 1 X n_dim_misc
72  // then replicate it so that it becomes of size n_time_steps X n_dims_misc
73  misc_ = misc.replicate(ts_.size(),1);
74  }
75  else
76  {
77  cerr << __FILE__ << ":" << __LINE__ << ":";
78  cerr << "misc must have 1 or " << ts_.size() << " rows, but it has " << misc.rows() << endl;
79  }
80 
81 }
82 
83 void Trajectory::append(const Trajectory& trajectory)
84 {
85  assert(dim() == trajectory.dim());
86 
87  assert(ts_[length() - 1] == trajectory.ts()[0]);
88 
89  if (ys_.row(length() - 1).isZero() || trajectory.ys().row(0).isZero())
90  assert(ys_.row(length() - 1).isZero() && trajectory.ys().row(0).isZero());
91  else
92  assert(ys_.row(length() - 1).isApprox(trajectory.ys().row(0)));
93 
94  if (yds_.row(length() - 1).isZero() || trajectory.yds().row(0).isZero())
95  assert(yds_.row(length() - 1).isZero() && trajectory.yds().row(0).isZero());
96  else
97  assert(yds_.row(length() - 1).isApprox(trajectory.yds().row(0)));
98 
99  if (ydds_.row(length() - 1).isZero() || trajectory.ydds().row(0).isZero())
100  assert(ydds_.row(length() - 1).isZero() && trajectory.ydds().row(0).isZero());
101  else
102  assert(ydds_.row(length() - 1).isApprox(trajectory.ydds().row(0)));
103 
104  int new_size = length() + trajectory.length() - 1;
105 
106  VectorXd new_ts(new_size);
107  new_ts << ts_, trajectory.ts().segment(1, trajectory.length() - 1);
108  ts_ = new_ts;
109 
110  MatrixXd new_ys(new_size, dim());
111  new_ys << ys_, trajectory.ys().block(1, 0, trajectory.length() - 1, dim());
112  ys_ = new_ys;
113 
114  MatrixXd new_yds(new_size, dim());
115  new_yds << yds_, trajectory.yds().block(1, 0, trajectory.length() - 1, dim());
116  yds_ = new_yds;
117 
118  MatrixXd new_ydds(new_size, dim());
119  new_ydds << ydds_, trajectory.ydds().block(1, 0, trajectory.length() - 1, dim());
120  ydds_ = new_ydds;
121 
122  assert(dim_misc() == trajectory.dim_misc());
123  if (dim_misc()==0)
124  {
125  misc_.resize(new_size,0);
126  }
127  else
128  {
129  MatrixXd new_misc(new_size, dim_misc());
130  new_misc << misc_, trajectory.misc().block(1, 0, trajectory.length() - 1, dim_misc());
131  misc_ = new_misc;
132  }
133 }
134 
135 VectorXd Trajectory::getRangePerDim(void) const
136 {
137  return ys_.colwise().maxCoeff().array()-ys_.colwise().minCoeff().array();
138 }
139 
140 Trajectory Trajectory::generateMinJerkTrajectory(const VectorXd& ts, const VectorXd& y_from, const VectorXd& y_to)
141 {
142  int n_time_steps = ts.size();
143  int n_dims = y_from.size();
144 
145  MatrixXd ys(n_time_steps,n_dims), yds(n_time_steps,n_dims), ydds(n_time_steps,n_dims);
146 
147  double D = ts[n_time_steps-1];
148  ArrayXd tss = (ts/D).array();
149 
150 
151  ArrayXd A = y_to.array()-y_from.array();
152 
153  for (int i_dim=0; i_dim<n_dims; i_dim++)
154  {
155 
156  // http://noisyaccumulation.blogspot.fr/2012/02/how-to-decompose-2d-trajectory-data.html
157 
158  ys.col(i_dim) = y_from[i_dim] + A[i_dim]*( 6*tss.pow(5) -15*tss.pow(4) +10*tss.pow(3));
159 
160  yds.col(i_dim) = (A[i_dim]/D)*( 30*tss.pow(4) -60*tss.pow(3) +30*tss.pow(2));
161 
162  ydds.col(i_dim) = (A[i_dim]/(D*D))*(120*tss.pow(3) -180*tss.pow(2) +60*tss );
163  }
164 
165  return Trajectory(ts,ys,yds,ydds);
166 
167 
168 }
169 
170 Trajectory Trajectory::generatePolynomialTrajectory(const VectorXd& ts, const VectorXd& y_from, const VectorXd& yd_from, const VectorXd& ydd_from,
171  const VectorXd& y_to, const VectorXd& yd_to, const VectorXd& ydd_to)
172 {
173  VectorXd a0 = y_from;
174  VectorXd a1 = yd_from;
175  VectorXd a2 = ydd_from / 2;
176 
177  VectorXd a3 = -10 * y_from - 6 * yd_from - 2.5 * ydd_from + 10 * y_to - 4 * yd_to + 0.5 * ydd_to;
178  VectorXd a4 = 15 * y_from + 8 * yd_from + 2 * ydd_from - 15 * y_to + 7 * yd_to - ydd_to;
179  VectorXd a5 = -6 * y_from - 3 * yd_from - 0.5 * ydd_from + 6 * y_to - 3 * yd_to + 0.5 * ydd_to;
180 
181  int n_time_steps = ts.size();
182  int n_dims = y_from.size();
183 
184  MatrixXd ys(n_time_steps,n_dims), yds(n_time_steps,n_dims), ydds(n_time_steps,n_dims);
185 
186  for (int i = 0; i < ts.size(); i++)
187  {
188  double t = (ts[i] - ts[0]) / (ts[n_time_steps - 1] - ts[0]);
189  ys.row(i) = a0 + a1 * t + a2 * pow(t, 2) + a3 * pow(t, 3) + a4 * pow(t, 4) + a5 * pow(t, 5);
190  yds.row(i) = a1 + 2 * a2 * t + 3 * a3 * pow(t, 2) + 4 * a4 * pow(t, 3) + 5 * a5 * pow(t, 4);
191  ydds.row(i) = 2 * a2 + 6 * a3 * t + 12 * a4 * pow(t, 2) + 20 * a5 * pow(t, 3);
192  }
193 
194  yds /= (ts[n_time_steps - 1] - ts[0]);
195  ydds /= pow(ts[n_time_steps - 1] - ts[0], 2);
196 
197  return Trajectory(ts, ys, yds, ydds);
198 }
199 
200 Trajectory Trajectory::generatePolynomialTrajectoryThroughViapoint(const VectorXd& ts, const VectorXd& y_from, const VectorXd& y_yd_ydd_viapoint, double viapoint_time, const VectorXd& y_to)
201 {
202 
203  int n_dims = y_from.size();
204  assert(n_dims==y_to.size());
205  assert(3*n_dims==y_yd_ydd_viapoint.size()); // Contains y, yd and ydd, so *3
206 
207  int n_time_steps = ts.size();
208 
209  int viapoint_time_step = 0;
210  while (viapoint_time_step<n_time_steps && ts[viapoint_time_step]<viapoint_time)
211  viapoint_time_step++;
212 
213  if (viapoint_time_step>=n_time_steps)
214  {
215  cerr << __FILE__ << ":" << __LINE__ << ":";
216  cerr << "ERROR: the time vector does not contain any time smaller than " << viapoint_time << ". Returning min-jerk trajectory WITHOUT viapoint." << endl;
217  return Trajectory();
218  }
219 
220  VectorXd yd_from = VectorXd::Zero(n_dims);
221  VectorXd ydd_from = VectorXd::Zero(n_dims);
222 
223  VectorXd y_viapoint = y_yd_ydd_viapoint.segment(0*n_dims,n_dims);
224  VectorXd yd_viapoint = y_yd_ydd_viapoint.segment(1*n_dims,n_dims);
225  VectorXd ydd_viapoint = y_yd_ydd_viapoint.segment(2*n_dims,n_dims);
226 
227  VectorXd yd_to = VectorXd::Zero(n_dims);
228  VectorXd ydd_to = VectorXd::Zero(n_dims);
229 
230  Trajectory traj = Trajectory::generatePolynomialTrajectory(ts.segment(0, viapoint_time_step + 1), y_from, yd_from, ydd_from, y_viapoint, yd_viapoint, ydd_viapoint);
231  traj.append(Trajectory::generatePolynomialTrajectory(ts.segment(viapoint_time_step, n_time_steps - viapoint_time_step), y_viapoint, yd_viapoint, ydd_viapoint, y_to, yd_to, ydd_to));
232 
233  return traj;
234 }
235 
236 void Trajectory::asMatrix(MatrixXd& as_matrix) const
237 {
238  as_matrix.resize(length(),1+3*dim()+dim_misc());
239  as_matrix << ts_, ys_, yds_, ydds_, misc_;
240 }
241 
242 ostream& operator<<(std::ostream& output, const Trajectory& trajectory) {
243  MatrixXd traj_matrix(trajectory.length(),1+3*trajectory.dim()+trajectory.dim_misc());
244  traj_matrix << trajectory.ts_, trajectory.ys_, trajectory.yds_, trajectory.ydds_, trajectory.misc_;
245  output << traj_matrix << endl;
246  return output;
247 }
248 
249 bool Trajectory::saveToFile(string directory, string filename, bool overwrite) const
250 {
251  MatrixXd traj_matrix;
252  asMatrix(traj_matrix);
253  return saveMatrix(directory, filename, traj_matrix, overwrite);
254 }
255 
256 Trajectory Trajectory::readFromFile(string filename, int n_dims_misc)
257 {
258  MatrixXd traj_matrix;
259  if (!loadMatrix(filename,traj_matrix))
260  {
261  cerr << __FILE__ << ":" << __LINE__ << ":";
262  cerr << "Cannot open filename '"<< filename <<"'." << endl;
263  return Trajectory();
264  }
265 
266  int n_dims = (traj_matrix.cols()-1-n_dims_misc)/3;
267  int n_time_steps = traj_matrix.rows();
268  VectorXd ts;
269  MatrixXd ys, yds, ydds, misc;
270  ts = traj_matrix.block(0,0+0*n_dims,n_time_steps,1);
271  ys = traj_matrix.block(0,1+0*n_dims,n_time_steps,n_dims);
272  yds = traj_matrix.block(0,1+1*n_dims,n_time_steps,n_dims);
273  ydds = traj_matrix.block(0,1+2*n_dims,n_time_steps,n_dims);
274  misc = traj_matrix.block(0,1+3*n_dims,n_time_steps,n_dims_misc);
275 
276  return Trajectory(ts,ys,yds,ydds,misc);
277 
278 }
279 
280 }
const Eigen::VectorXd & ts(void) const
Accessor function for the times at which measurements were made.
Definition: Trajectory.hpp:67
static Trajectory readFromFile(std::string filename, int n_dims_misc=0)
Read a trajectory from a file.
Definition: Trajectory.cpp:256
static Trajectory generatePolynomialTrajectory(const Eigen::VectorXd &ts, const Eigen::VectorXd &y_from, const Eigen::VectorXd &yd_from, const Eigen::VectorXd &ydd_from, const Eigen::VectorXd &y_to, const Eigen::VectorXd &yd_to, const Eigen::VectorXd &ydd_to)
Generate a fifth order polynomial trajectory from an initial to a final state.
Definition: Trajectory.cpp:170
Header file for input/output of Eigen matrices to ASCII files.
Trajectory class header file.
const Eigen::MatrixXd & ys(void) const
Accessor function for the positions at different times.
Definition: Trajectory.hpp:72
A class for storing trajectories: positions, velocities and accelerations of variables over time...
Definition: Trajectory.hpp:48
const Eigen::MatrixXd & ydds(void) const
Accessor function for the accelerations at different times.
Definition: Trajectory.hpp:82
void set_misc(const Eigen::MatrixXd &misc)
Set miscellaneous variables included in the trajectory.
Definition: Trajectory.cpp:62
bool saveMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > matrix, bool overwrite=false)
Save an Eigen matrix to an ASCII file.
int length(void) const
Get the length of the trajectory, i.e.
Definition: Trajectory.hpp:101
void append(const Trajectory &trajectory)
Append another trajectory at the end.
Definition: Trajectory.cpp:83
Eigen::VectorXd getRangePerDim(void) const
Get the range of ys per dimension.
Definition: Trajectory.cpp:135
int dim(void) const
Get the dimensionality of the trajectory.
Definition: Trajectory.hpp:111
const Eigen::MatrixXd & misc(void) const
Return miscellaneous variables included in the trajectory.
Definition: Trajectory.hpp:89
Trajectory(void)
Default constructor.
Definition: Trajectory.cpp:39
const Eigen::MatrixXd & yds(void) const
Accessor function for the velocities at different times.
Definition: Trajectory.hpp:77
friend std::ostream & operator<<(std::ostream &output, const Trajectory &trajectory)
Write object to an output stream.
Definition: Trajectory.cpp:242
void asMatrix(Eigen::MatrixXd &as_matrix) const
Return the trajectory as one large matrix.
Definition: Trajectory.cpp:236
static Trajectory generateMinJerkTrajectory(const Eigen::VectorXd &ts, const Eigen::VectorXd &initial_y, const Eigen::VectorXd &final_y)
Generate a minimum-jerk trajectory from an initial to a final state.
Definition: Trajectory.cpp:140
bool loadMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > &m)
Load an Eigen matrix from an ASCII file.
Definition: EigenFileIO.tpp:33
static Trajectory generatePolynomialTrajectoryThroughViapoint(const Eigen::VectorXd &ts, const Eigen::VectorXd &y_from, const Eigen::VectorXd &y_yd_ydd_viapoint, double viapoint_time, const Eigen::VectorXd &y_to)
Generate a trajectory from an initial to a final state, through a viapoint.
Definition: Trajectory.cpp:200
bool saveToFile(std::string directory, std::string filename, bool overwrite=false) const
Save a trajectory to a file.
Definition: Trajectory.cpp:249
int dim_misc(void) const
Get the dimensionality of the misc variables.
Definition: Trajectory.hpp:116