00001
00027 #include <stomp_moveit/utils/polynomial.h>
00028 #include <ros/console.h>
00029
00033 namespace stomp_moveit
00034 {
00035
00039 namespace utils
00040 {
00041
00045 namespace polynomial
00046 {
00047
00048
00049 PolyFitResults polyFit(const PolyFitRequest &request)
00050 {
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 PolyFitResults result;
00067
00068 int num_r = request.d + 1;
00069 Eigen::MatrixXd x_t(num_r, request.xy.cols());
00070 if (!request.hasConstraints())
00071 {
00072 for (auto r = 0; r < num_r; r++)
00073 x_t.row(r) = request.xy.row(0).array().pow(r);
00074
00075 Eigen::MatrixXd mat = x_t * x_t.transpose();
00076 Eigen::VectorXd vec = x_t * request.xy.row(1);
00077
00078 result.p = mat.lu().solve(vec).head(num_r);
00079 }
00080 else
00081 {
00082 int num_constraints = request.xyfp.cols() + request.xyfs.cols();
00083
00084 Eigen::MatrixXd a_t(num_r, num_constraints);
00085 Eigen::MatrixXd a_tp(num_r, request.xyfp.cols());
00086 Eigen::MatrixXd a_ts(num_r, request.xyfs.cols());
00087
00088 for (auto r = 0; r < num_r; r++)
00089 {
00090 x_t.row(r) = request.xy.row(0).array().pow(r);
00091
00092 if (request.hasPositionConstraints())
00093 a_tp.row(r) = request.xyfp.row(0).array().pow(r);
00094
00095 if (request.hasSlopeConstraints())
00096 if (r == 0)
00097 a_ts.row(r) = request.xyfs.row(0).array() * 0.0;
00098 else
00099 a_ts.row(r) = request.xyfs.row(0).array().pow(r - 1) / r;
00100
00101 }
00102
00103 Eigen::MatrixXd top(num_r, num_r + num_constraints);
00104 Eigen::MatrixXd bot(num_constraints, num_r + num_constraints);
00105 Eigen::MatrixXd mat(num_r + num_constraints, num_r + num_constraints);
00106 Eigen::VectorXd vec(num_r + num_constraints);
00107
00108 if (request.hasPositionConstraints() && request.hasSlopeConstraints())
00109 {
00110 a_t << a_tp, a_ts;
00111 vec << 2*x_t*request.xy.row(1).transpose(), request.xyfp.row(1).transpose(), request.xyfs.row(1).transpose();
00112 }
00113 else if (request.hasPositionConstraints())
00114 {
00115 a_t << a_tp;
00116 vec << 2*x_t*request.xy.row(1).transpose(), request.xyfp.row(1).transpose();
00117 }
00118 else if (request.hasSlopeConstraints())
00119 {
00120 a_t << a_ts;
00121 vec << 2*x_t*request.xy.row(1).transpose(), request.xyfs.row(1).transpose();
00122 }
00123
00124 top << 2*x_t*x_t.transpose(), a_t;
00125 bot << a_t.transpose(), Eigen::MatrixXd::Zero(num_constraints, num_constraints);
00126 mat << top,
00127 bot;
00128
00129 result.p = mat.lu().solve(vec).head(num_r);
00130 }
00131
00132 if (request.output_domain.size() == 0)
00133 {
00134 result.x = request.xy.row(0);
00135 result.y = x_t.transpose() * result.p;
00136 result.successful = true;
00137 return result;
00138 }
00139 else
00140 {
00141 result.x = request.output_domain;
00142 fillVandermondeMatrix(result.x, request.d, x_t);
00143 result.y = x_t.transpose() * result.p;
00144 result.successful = true;
00145 return result;
00146 }
00147 }
00148
00149 void fillVandermondeMatrix(const Eigen::ArrayXd &domain_vals, const int &order, Eigen::MatrixXd &v)
00150 {
00151 v = Eigen::MatrixXd::Ones(order+1, domain_vals.size());
00152 for(auto p = 1u; p <= order; p++)
00153 v.row(p) = domain_vals.pow(p);
00154 }
00155
00156 void generateMinimumDomainValues(const std::vector<const moveit::core::JointModel *> joint_models,
00157 const Eigen::MatrixXd ¶meters,Eigen::VectorXd &domain_values)
00158 {
00159 Eigen::VectorXd distance(parameters.rows());
00160 Eigen::VectorXd velocity(parameters.rows());
00161 Eigen::VectorXd t(parameters.rows());
00162 Eigen::VectorXd domain_dist(parameters.cols());
00163 double max_t = 0;
00164
00165 domain_values.resize(parameters.cols());
00166 for(auto r = 0; r < parameters.rows(); r++)
00167 {
00168 moveit::core::VariableBounds bound = joint_models[r]->getVariableBounds()[0];
00169 velocity(r) = bound.max_velocity_;
00170 distance(r) = 0.0;
00171 domain_dist(0) = 0.0;
00172 for(auto c = 1; c < parameters.cols(); c++)
00173 {
00174 distance(r) += std::abs((parameters(r, c)) - (parameters(r, c - 1)));
00175 domain_dist(c) = distance(r);
00176 }
00177
00178 t(r) = distance(r)/velocity(r);
00179 if (t(r) > max_t)
00180 {
00181 max_t = t(r);
00182 domain_values = domain_dist/velocity(r);
00183 }
00184 }
00185 }
00186
00187 bool applyPolynomialSmoothing(moveit::core::RobotModelConstPtr robot_model, const std::string& group_name, Eigen::MatrixXd& parameters,
00188 int poly_order, double joint_limit_margin)
00189 {
00190 using namespace Eigen;
00191 using namespace moveit::core;
00192
00193 const std::vector<const JointModel*> &joint_models = robot_model->getJointModelGroup(group_name)->getActiveJointModels();
00194 PolyFitRequest request;
00195 int num_timesteps = parameters.cols();
00196
00197 VectorXd domain_vals;
00198 domain_vals.setLinSpaced(num_timesteps,0,1);
00199
00200 request.d = poly_order;
00201 request.xy.resize(2, num_timesteps);
00202 request.xy.row(0) = domain_vals;
00203 for(auto r = 0; r < parameters.rows(); r++)
00204 {
00205 request.xy.row(1) = parameters.row(r);
00206 request.xyfp.resize(2, 2);
00207 request.xyfp(0, 0) = request.xy(0, 0);
00208 request.xyfp(1, 0) = request.xy(1, 0);
00209 request.xyfp(0, 1) = request.xy(0, num_timesteps - 1);
00210 request.xyfp(1, 1) = request.xy(1, num_timesteps - 1);
00211
00212 PolyFitResults results;
00213 results = polyFit(request);
00214 for(auto i = 0; i < results.y.size(); ++i)
00215 joint_models[r]->enforcePositionBounds(&results.y[i]);
00216
00217
00218 bool finished;
00219 double min = results.y.minCoeff();
00220 double max = results.y.maxCoeff();
00221 finished = joint_models[r]->satisfiesPositionBounds(&min, joint_limit_margin) &&
00222 joint_models[r]->satisfiesPositionBounds(&max, joint_limit_margin);
00223
00224 if ((results.p.array() != results.p.array()).any())
00225 {
00226 ROS_ERROR("Smoother, joint %s polynomial fit failed!", joint_models[r]->getName().c_str());
00227 return false;
00228 }
00229
00230 if(!finished)
00231 {
00232 ROS_ERROR("Smoother, joint %s not within limits, Min: %f, Max: %f", joint_models[r]->getName().c_str(), min, max);
00233 return false;
00234 }
00235
00236 parameters.row(r) = results.y;
00237 }
00238
00239 return true;
00240 }
00241
00242 }
00243 }
00244 }
00245
00246
00247
00248