goal_guided_multivariate_gaussian.cpp
Go to the documentation of this file.
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   // goal kinematics parameters
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     // noise generation parameters
00104     XmlRpcValue stddev_param = params["stddev"];
00105     XmlRpcValue goal_stddev_param = params["goal_stddev"];
00106 
00107     // check  stddev
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     // check goal stddev
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     // parsing parameters
00122     for(auto i = 0u; i < stddev_param.size(); i++)
00123     {
00124       stddev_[i] = static_cast<double>(stddev_param[i]);
00125     }
00126 
00127     // goal stddev
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     // goal constraint parameters
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   // convenience lambda function to fill matrix
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   // creating finite difference acceleration matrix
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   // create and scale covariance matrix
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   // create random generators
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   // preallocating noise data
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   // generating noise
00265   int sign;
00266   for(auto d = 0u; d < parameters.rows() ; d++)
00267   {
00268     traj_noise_generators_[d]->sample(raw_noise_,true);
00269 
00270     // shifting data towards goal
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   // generate noise
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   // applying noise onto tool pose
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 } /* namespace noise_generators */
00315 } /* namespace stomp_moveit */


stomp_plugins
Author(s): Jorge Nicho
autogenerated on Sat Jun 8 2019 19:24:15