31 #include <eigen3/Eigen/Core> 35 using namespace Eigen;
39 Trajectory::Trajectory(
void)
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)
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());
51 misc_ = MatrixXd(n_time_steps,0);
52 assert(n_time_steps==misc_.rows());
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());
64 if (misc.rows()==ts_.size())
69 else if (misc.rows()==1)
73 misc_ = misc.replicate(ts_.size(),1);
77 cerr << __FILE__ <<
":" << __LINE__ <<
":";
78 cerr <<
"misc must have 1 or " << ts_.size() <<
" rows, but it has " << misc.rows() << endl;
85 assert(
dim() == trajectory.
dim());
87 assert(ts_[
length() - 1] == trajectory.
ts()[0]);
89 if (ys_.row(
length() - 1).isZero() || trajectory.
ys().row(0).isZero())
90 assert(ys_.row(
length() - 1).isZero() && trajectory.
ys().row(0).isZero());
92 assert(ys_.row(
length() - 1).isApprox(trajectory.
ys().row(0)));
94 if (yds_.row(
length() - 1).isZero() || trajectory.
yds().row(0).isZero())
95 assert(yds_.row(
length() - 1).isZero() && trajectory.
yds().row(0).isZero());
97 assert(yds_.row(
length() - 1).isApprox(trajectory.
yds().row(0)));
99 if (ydds_.row(
length() - 1).isZero() || trajectory.
ydds().row(0).isZero())
100 assert(ydds_.row(
length() - 1).isZero() && trajectory.
ydds().row(0).isZero());
102 assert(ydds_.row(
length() - 1).isApprox(trajectory.
ydds().row(0)));
106 VectorXd new_ts(new_size);
107 new_ts << ts_, trajectory.
ts().segment(1, trajectory.
length() - 1);
110 MatrixXd new_ys(new_size,
dim());
111 new_ys << ys_, trajectory.
ys().block(1, 0, trajectory.
length() - 1,
dim());
114 MatrixXd new_yds(new_size,
dim());
115 new_yds << yds_, trajectory.
yds().block(1, 0, trajectory.
length() - 1,
dim());
118 MatrixXd new_ydds(new_size,
dim());
119 new_ydds << ydds_, trajectory.
ydds().block(1, 0, trajectory.
length() - 1,
dim());
125 misc_.resize(new_size,0);
129 MatrixXd new_misc(new_size,
dim_misc());
130 new_misc << misc_, trajectory.
misc().block(1, 0, trajectory.
length() - 1,
dim_misc());
137 return ys_.colwise().maxCoeff().array()-ys_.colwise().minCoeff().array();
142 int n_time_steps = ts.size();
143 int n_dims = y_from.size();
145 MatrixXd
ys(n_time_steps,n_dims),
yds(n_time_steps,n_dims),
ydds(n_time_steps,n_dims);
147 double D = ts[n_time_steps-1];
148 ArrayXd tss = (ts/D).array();
151 ArrayXd A = y_to.array()-y_from.array();
153 for (
int i_dim=0; i_dim<n_dims; i_dim++)
158 ys.col(i_dim) = y_from[i_dim] + A[i_dim]*( 6*tss.pow(5) -15*tss.pow(4) +10*tss.pow(3));
160 yds.col(i_dim) = (A[i_dim]/D)*( 30*tss.pow(4) -60*tss.pow(3) +30*tss.pow(2));
162 ydds.col(i_dim) = (A[i_dim]/(D*D))*(120*tss.pow(3) -180*tss.pow(2) +60*tss );
171 const VectorXd& y_to,
const VectorXd& yd_to,
const VectorXd& ydd_to)
173 VectorXd a0 = y_from;
174 VectorXd a1 = yd_from;
175 VectorXd a2 = ydd_from / 2;
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;
181 int n_time_steps = ts.size();
182 int n_dims = y_from.size();
184 MatrixXd
ys(n_time_steps,n_dims),
yds(n_time_steps,n_dims),
ydds(n_time_steps,n_dims);
186 for (
int i = 0; i < ts.size(); i++)
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);
194 yds /= (ts[n_time_steps - 1] - ts[0]);
195 ydds /= pow(ts[n_time_steps - 1] - ts[0], 2);
203 int n_dims = y_from.size();
204 assert(n_dims==y_to.size());
205 assert(3*n_dims==y_yd_ydd_viapoint.size());
207 int n_time_steps = ts.size();
209 int viapoint_time_step = 0;
210 while (viapoint_time_step<n_time_steps && ts[viapoint_time_step]<viapoint_time)
211 viapoint_time_step++;
213 if (viapoint_time_step>=n_time_steps)
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;
220 VectorXd yd_from = VectorXd::Zero(n_dims);
221 VectorXd ydd_from = VectorXd::Zero(n_dims);
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);
227 VectorXd yd_to = VectorXd::Zero(n_dims);
228 VectorXd ydd_to = VectorXd::Zero(n_dims);
239 as_matrix << ts_, ys_, yds_, ydds_, misc_;
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;
251 MatrixXd traj_matrix;
253 return saveMatrix(directory, filename, traj_matrix, overwrite);
258 MatrixXd traj_matrix;
261 cerr << __FILE__ <<
":" << __LINE__ <<
":";
262 cerr <<
"Cannot open filename '"<< filename <<
"'." << endl;
266 int n_dims = (traj_matrix.cols()-1-n_dims_misc)/3;
267 int n_time_steps = traj_matrix.rows();
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);
const Eigen::VectorXd & ts(void) const
Accessor function for the times at which measurements were made.
static Trajectory readFromFile(std::string filename, int n_dims_misc=0)
Read a trajectory from a file.
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.
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.
A class for storing trajectories: positions, velocities and accelerations of variables over time...
const Eigen::MatrixXd & ydds(void) const
Accessor function for the accelerations at different times.
void set_misc(const Eigen::MatrixXd &misc)
Set miscellaneous variables included in the trajectory.
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.
void append(const Trajectory &trajectory)
Append another trajectory at the end.
Eigen::VectorXd getRangePerDim(void) const
Get the range of ys per dimension.
int dim(void) const
Get the dimensionality of the trajectory.
const Eigen::MatrixXd & misc(void) const
Return miscellaneous variables included in the trajectory.
Trajectory(void)
Default constructor.
const Eigen::MatrixXd & yds(void) const
Accessor function for the velocities at different times.
friend std::ostream & operator<<(std::ostream &output, const Trajectory &trajectory)
Write object to an output stream.
void asMatrix(Eigen::MatrixXd &as_matrix) const
Return the trajectory as one large matrix.
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.
bool loadMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > &m)
Load an Eigen matrix from an ASCII file.
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.
bool saveToFile(std::string directory, std::string filename, bool overwrite=false) const
Save a trajectory to a file.
int dim_misc(void) const
Get the dimensionality of the misc variables.