00001
00027 #include "stomp_plugins/noise_generators/goal_guided_multivariate_gaussian.h"
00028 #include <stomp_moveit/utils/multivariate_gaussian.h>
00029 #include <XmlRpcException.h>
00030 #include <pluginlib/class_list_macros.h>
00031 #include <ros/package.h>
00032 #include <ros/console.h>
00033 #include <boost/filesystem.hpp>
00034 #include <fstream>
00035
00036 PLUGINLIB_EXPORT_CLASS(stomp_moveit::noise_generators::GoalGuidedMultivariateGaussian,
00037 stomp_moveit::noise_generators::StompNoiseGenerator);
00038
00039 static int const IK_ITERATIONS = 40;
00040 static double const JOINT_UPDATE_RATE = 0.5f;
00041 static double const CARTESIAN_POS_CONVERGENCE = 0.01;
00042 static double const CARTESIAN_ROT_CONVERGENCE = 0.01;
00043 static const std::vector<double> ACC_MATRIX_DIAGONAL_VALUES = {-1.0/12.0, 16.0/12.0, -30.0/12.0, 16.0/12.0, -1.0/12.0};
00044 static const std::vector<int> ACC_MATRIX_DIAGONAL_INDICES = {-2, -1, 0 ,1, 2};
00045 static const int CARTESIAN_DOF_SIZE = 6;
00046
00047
00048 namespace stomp_moveit
00049 {
00050 namespace noise_generators
00051 {
00052
00053 GoalGuidedMultivariateGaussian::GoalGuidedMultivariateGaussian():
00054 name_("GoalGuidedMultivariateGaussian"),
00055 goal_rand_generator_(new RandomGenerator(RGNType(),boost::uniform_real<>(-1,1)))
00056 {
00057
00058 }
00059
00060 GoalGuidedMultivariateGaussian::~GoalGuidedMultivariateGaussian()
00061 {
00062
00063 }
00064
00065
00066
00067 bool GoalGuidedMultivariateGaussian::initialize(moveit::core::RobotModelConstPtr robot_model_ptr,
00068 const std::string& group_name,const XmlRpc::XmlRpcValue& config)
00069 {
00070 using namespace moveit::core;
00071
00072 group_ = group_name;
00073 robot_model_ = robot_model_ptr;
00074 const JointModelGroup* joint_group = robot_model_ptr->getJointModelGroup(group_name);
00075 if(!joint_group)
00076 {
00077 ROS_ERROR("Invalid joint group %s",group_name.c_str());
00078 return false;
00079 }
00080
00081 stddev_.resize(joint_group->getActiveJointModelNames().size());
00082 goal_stddev_.resize(CARTESIAN_DOF_SIZE);
00083
00084
00085 kc_.joint_update_rates = JOINT_UPDATE_RATE*Eigen::VectorXd::Ones(stddev_.size());
00086 kc_.cartesian_convergence_thresholds << CARTESIAN_POS_CONVERGENCE, CARTESIAN_POS_CONVERGENCE, CARTESIAN_POS_CONVERGENCE,
00087 CARTESIAN_ROT_CONVERGENCE, CARTESIAN_ROT_CONVERGENCE, CARTESIAN_ROT_CONVERGENCE;
00088 kc_.constrained_dofs << 1, 1, 1, 1, 1, 1;
00089 kc_.max_iterations = IK_ITERATIONS;
00090
00091
00092 return configure(config);
00093 }
00094
00095 bool GoalGuidedMultivariateGaussian::configure(const XmlRpc::XmlRpcValue& config)
00096 {
00097 using namespace XmlRpc;
00098
00099 try
00100 {
00101 XmlRpcValue params = config;
00102
00103
00104 XmlRpcValue stddev_param = params["stddev"];
00105 XmlRpcValue goal_stddev_param = params["goal_stddev"];
00106
00107
00108 if(stddev_param.size() < stddev_.size())
00109 {
00110 ROS_ERROR("%s the 'stddev' parameter has fewer elements than the number of joints",getName().c_str());
00111 return false;
00112 }
00113
00114
00115 if(goal_stddev_param.size() != CARTESIAN_DOF_SIZE)
00116 {
00117 ROS_ERROR("%s the 'goal_stddev' parameter must have 6 entries [x y z rx ry rz] for the tool cartesian goal",getName().c_str());
00118 return false;
00119 }
00120
00121
00122 for(auto i = 0u; i < stddev_param.size(); i++)
00123 {
00124 stddev_[i] = static_cast<double>(stddev_param[i]);
00125 }
00126
00127
00128 for(auto i = 0u; i < goal_stddev_param.size(); i++)
00129 {
00130 goal_stddev_[i] = static_cast<double>(goal_stddev_param[i]);
00131 }
00132
00133
00134 XmlRpcValue dof_nullity_param = params["constrained_dofs"];
00135 if((dof_nullity_param.getType() != XmlRpcValue::TypeArray) ||
00136 dof_nullity_param.size() < CARTESIAN_DOF_SIZE )
00137 {
00138 ROS_ERROR("UnderconstrainedGoal received invalid array parameters");
00139 return false;
00140 }
00141
00142 for(auto i = 0u; i < dof_nullity_param.size(); i++)
00143 {
00144 kc_.constrained_dofs(i) = static_cast<int>(dof_nullity_param[i]);
00145 }
00146
00147 }
00148 catch(XmlRpc::XmlRpcException& e)
00149 {
00150 ROS_ERROR("%s failed to load parameters",getName().c_str());
00151 return false;
00152 }
00153
00154 return true;
00155 }
00156
00157 bool GoalGuidedMultivariateGaussian::setMotionPlanRequest(const planning_scene::PlanningSceneConstPtr& planning_scene,
00158 const moveit_msgs::MotionPlanRequest &req,
00159 const stomp_core::StompConfiguration &config,
00160 moveit_msgs::MoveItErrorCodes& error_code)
00161 {
00162 bool succeed = setNoiseGeneration(planning_scene,req,config,error_code) &&
00163 setGoalConstraints(planning_scene,req,config,error_code);
00164
00165 return succeed;
00166 }
00167
00168 bool GoalGuidedMultivariateGaussian::setNoiseGeneration(const planning_scene::PlanningSceneConstPtr& planning_scene,
00169 const moveit_msgs::MotionPlanRequest &req,
00170 const stomp_core::StompConfiguration &config,
00171 moveit_msgs::MoveItErrorCodes& error_code)
00172 {
00173 using namespace Eigen;
00174
00175
00176 auto fill_diagonal = [](Eigen::MatrixXd& m,double coeff,int diag_index)
00177 {
00178 std::size_t size = m.rows() - std::abs(diag_index);
00179 m.diagonal(diag_index) = VectorXd::Constant(size,coeff);
00180 };
00181
00182
00183 std::size_t num_timesteps = config.num_timesteps;
00184 Eigen::MatrixXd A = MatrixXd::Zero(num_timesteps,num_timesteps);
00185 int num_elements = (int((ACC_MATRIX_DIAGONAL_INDICES.size() -1)/2.0) + 1)* num_timesteps ;
00186 for(auto i = 0u; i < ACC_MATRIX_DIAGONAL_INDICES.size() ; i++)
00187 {
00188 fill_diagonal(A,ACC_MATRIX_DIAGONAL_VALUES[i],ACC_MATRIX_DIAGONAL_INDICES[i]);
00189 }
00190
00191
00192 Eigen::MatrixXd covariance = MatrixXd::Identity(num_timesteps,num_timesteps);
00193 covariance = A.transpose() * A;
00194 covariance = covariance.fullPivLu().inverse();
00195 double max_val = covariance.array().abs().matrix().maxCoeff();
00196 covariance /= max_val;
00197
00198
00199 traj_noise_generators_.resize(stddev_.size());
00200 for(auto& r: traj_noise_generators_)
00201 {
00202 r.reset(new utils::MultivariateGaussian(VectorXd::Zero(num_timesteps),covariance));
00203 }
00204
00205
00206 raw_noise_.resize(config.num_timesteps);
00207 raw_noise_.setZero();
00208
00209 error_code.val = error_code.SUCCESS;
00210
00211 return true;
00212 }
00213
00214
00215 bool GoalGuidedMultivariateGaussian::setGoalConstraints(const planning_scene::PlanningSceneConstPtr& planning_scene,
00216 const moveit_msgs::MotionPlanRequest &req,
00217 const stomp_core::StompConfiguration &config,
00218 moveit_msgs::MoveItErrorCodes& error_code)
00219 {
00220 using namespace Eigen;
00221 using namespace moveit::core;
00222 using namespace utils::kinematics;
00223
00224 const JointModelGroup* joint_group = robot_model_->getJointModelGroup(group_);
00225 int num_joints = joint_group->getActiveJointModels().size();
00226 tool_link_ = joint_group->getLinkModelNames().back();
00227 state_.reset(new RobotState(robot_model_));
00228 robotStateMsgToRobotState(req.start_state,*state_);
00229
00230 ROS_DEBUG("%s using '%s' tool link",getName().c_str(),tool_link_.c_str());
00231 error_code.val = error_code.SUCCESS;
00232
00233 return true;
00234 }
00235
00236 bool GoalGuidedMultivariateGaussian::generateNoise(const Eigen::MatrixXd& parameters,
00237 std::size_t start_timestep,
00238 std::size_t num_timesteps,
00239 int iteration_number,
00240 int rollout_number,
00241 Eigen::MatrixXd& parameters_noise,
00242 Eigen::MatrixXd& noise)
00243 {
00244 using namespace Eigen;
00245 using namespace stomp_moveit::utils;
00246
00247 VectorXd goal_joint_pose, goal_joint_noise;
00248 if(parameters.rows() != stddev_.size())
00249 {
00250 ROS_ERROR("Number of rows in parameters %i differs from expected number of joints",int(parameters.rows()));
00251 return false;
00252 }
00253
00254 if(generateRandomGoal(parameters.rightCols(1),goal_joint_pose))
00255 {
00256 goal_joint_noise = goal_joint_pose - parameters.rightCols(1);
00257 }
00258 else
00259 {
00260 ROS_WARN("%s failed to generate random goal pose in the task space, not applying noise at goal",getName().c_str());
00261 goal_joint_noise = VectorXd::Zero(parameters.rows());
00262 }
00263
00264
00265 int sign;
00266 for(auto d = 0u; d < parameters.rows() ; d++)
00267 {
00268 traj_noise_generators_[d]->sample(raw_noise_,true);
00269
00270
00271 sign = goal_joint_noise(d) > 0 ? 1 : -1;
00272 noise.row(d).transpose() = stddev_[d] * raw_noise_+ sign*Eigen::VectorXd::LinSpaced(
00273 raw_noise_.size(),0,std::abs(goal_joint_noise(d)));
00274 }
00275
00276 parameters_noise = parameters + noise;
00277
00278 return true;
00279 }
00280
00281 bool GoalGuidedMultivariateGaussian::generateRandomGoal(const Eigen::VectorXd& seed_joint_pose,Eigen::VectorXd& goal_joint_pose)
00282 {
00283 using namespace Eigen;
00284 using namespace moveit::core;
00285 using namespace stomp_moveit::utils;
00286
00287
00288 Eigen::VectorXd noise = Eigen::VectorXd::Zero(CARTESIAN_DOF_SIZE);
00289 for(auto d = 0u; d < noise.size(); d++)
00290 {
00291 noise(d) = goal_stddev_[d]*(*goal_rand_generator_)();
00292 }
00293
00294
00295 state_->setJointGroupPositions(group_,seed_joint_pose);
00296 state_->updateLinkTransforms();
00297 Affine3d tool_pose = state_->getGlobalLinkTransform(tool_link_);
00298 auto& n = noise;
00299 kc_.tool_goal_pose = tool_pose * Translation3d(Vector3d(n(0),n(1),n(2)))*
00300 AngleAxisd(n(3),Vector3d::UnitX())*AngleAxisd(n(4),Vector3d::UnitY())*AngleAxisd(n(5),Vector3d::UnitZ());
00301 kc_.init_joint_pose = seed_joint_pose;
00302
00303 if(!kinematics::solveIK(state_,group_,kc_,goal_joint_pose))
00304 {
00305 ROS_DEBUG("%s 'solveIK(...)' failed, returning noiseless goal pose",getName().c_str());
00306 goal_joint_pose= seed_joint_pose;
00307 return false;
00308 }
00309
00310 return true;
00311 }
00312
00313
00314 }
00315 }