goal_guided_multivariate_gaussian.cpp
Go to the documentation of this file.
1 
28 #include <stomp_moveit/utils/multivariate_gaussian.h>
29 #include <XmlRpcException.h>
31 #include <ros/package.h>
32 #include <ros/console.h>
33 #include <boost/filesystem.hpp>
34 #include <fstream>
35 
38 
39 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};
40 static const std::vector<int> ACC_MATRIX_DIAGONAL_INDICES = {-2, -1, 0 ,1, 2};
41 static const int CARTESIAN_DOF_SIZE = 6;
42 static const double DEFAULT_POS_TOLERANCE = 0.001;
43 static const double DEFAULT_ROT_TOLERANCE = 0.01;
44 
45 
46 namespace stomp_moveit
47 {
48 namespace noise_generators
49 {
50 
52  name_("GoalGuidedMultivariateGaussian"),
53  goal_rand_generator_(new RandomGenerator(RGNType(),boost::uniform_real<>(-1,1)))
54 {
55 
56 }
57 
59 {
60 
61 }
62 
63 bool GoalGuidedMultivariateGaussian::initialize(moveit::core::RobotModelConstPtr robot_model_ptr,
64  const std::string& group_name,const XmlRpc::XmlRpcValue& config)
65 {
66  using namespace moveit::core;
67 
68  // robot model details
69  group_ = group_name;
70  robot_model_ = robot_model_ptr;
71  const JointModelGroup* joint_group = robot_model_ptr->getJointModelGroup(group_name);
72  if(!joint_group)
73  {
74  ROS_ERROR("Invalid joint group %s",group_name.c_str());
75  return false;
76  }
77 
78  // kinematics
79  ik_solver_.reset(new stomp_moveit::utils::kinematics::IKSolver(robot_model_ptr,group_name));
80 
81  // trajectory noise generation
82  stddev_.resize(joint_group->getActiveJointModelNames().size());
83 
84  return configure(config);
85 }
86 
88 {
89  using namespace XmlRpc;
90 
91  try
92  {
93  XmlRpcValue params = config;
94 
95  // noise generation parameters
96  XmlRpcValue stddev_param = params["stddev"];
97 
98  // check stddev
99  if(stddev_param.size() < stddev_.size())
100  {
101  ROS_ERROR("%s the 'stddev' parameter has fewer elements than the number of joints",getName().c_str());
102  return false;
103  }
104 
105  // parsing parameters
106  for(auto i = 0u; i < stddev_param.size(); i++)
107  {
108  stddev_[i] = static_cast<double>(stddev_param[i]);
109  }
110 
111 
112  }
113  catch(XmlRpc::XmlRpcException& e)
114  {
115  ROS_ERROR("%s failed to load parameters",getName().c_str());
116  return false;
117  }
118 
119  return true;
120 }
121 
122 bool GoalGuidedMultivariateGaussian::setMotionPlanRequest(const planning_scene::PlanningSceneConstPtr& planning_scene,
123  const moveit_msgs::MotionPlanRequest &req,
124  const stomp_core::StompConfiguration &config,
125  moveit_msgs::MoveItErrorCodes& error_code)
126 {
127  bool succeed = setupNoiseGeneration(planning_scene,req,config,error_code) &&
128  setupGoalConstraints(planning_scene,req,config,error_code);
129 
130  return succeed;
131 }
132 
133 bool GoalGuidedMultivariateGaussian::setupNoiseGeneration(const planning_scene::PlanningSceneConstPtr& planning_scene,
134  const moveit_msgs::MotionPlanRequest &req,
135  const stomp_core::StompConfiguration &config,
136  moveit_msgs::MoveItErrorCodes& error_code)
137 {
138  using namespace Eigen;
139 
140  // convenience lambda function to fill matrix
141  auto fill_diagonal = [](Eigen::MatrixXd& m,double coeff,int diag_index)
142  {
143  std::size_t size = m.rows() - std::abs(diag_index);
144  m.diagonal(diag_index) = VectorXd::Constant(size,coeff);
145  };
146 
147  // creating finite difference acceleration matrix
148  std::size_t num_timesteps = config.num_timesteps;
149  Eigen::MatrixXd A = MatrixXd::Zero(num_timesteps,num_timesteps);
150  int num_elements = (int((ACC_MATRIX_DIAGONAL_INDICES.size() -1)/2.0) + 1)* num_timesteps ;
151  for(auto i = 0u; i < ACC_MATRIX_DIAGONAL_INDICES.size() ; i++)
152  {
154  }
155 
156  // create and scale covariance matrix
157  Eigen::MatrixXd covariance = MatrixXd::Identity(num_timesteps,num_timesteps);
158  covariance = A.transpose() * A;
159  covariance = covariance.fullPivLu().inverse();
160  double max_val = covariance.array().abs().matrix().maxCoeff();
161  covariance /= max_val;
162 
163  // create random generators
164  traj_noise_generators_.resize(stddev_.size());
165  for(auto& r: traj_noise_generators_)
166  {
167  r.reset(new utils::MultivariateGaussian(VectorXd::Zero(num_timesteps),covariance));
168  }
169 
170  // preallocating noise data
171  raw_noise_.resize(config.num_timesteps);
172  raw_noise_.setZero();
173 
174  error_code.val = error_code.SUCCESS;
175 
176  return true;
177 }
178 
179 
180 bool GoalGuidedMultivariateGaussian::setupGoalConstraints(const planning_scene::PlanningSceneConstPtr& planning_scene,
181  const moveit_msgs::MotionPlanRequest &req,
182  const stomp_core::StompConfiguration &config,
183  moveit_msgs::MoveItErrorCodes& error_code)
184 {
185  using namespace Eigen;
186  using namespace moveit::core;
187  using namespace utils::kinematics;
188 
189  // robot state
190  const JointModelGroup* joint_group = robot_model_->getJointModelGroup(group_);
191  int num_joints = joint_group->getActiveJointModels().size();
192  tool_link_ = joint_group->getLinkModelNames().back();
193  state_.reset(new RobotState(robot_model_));
194  robotStateMsgToRobotState(req.start_state,*state_);
195 
196  // update kinematic model
197  ik_solver_->setKinematicState(*state_);
198 
199  // storing cartesian goal tolerance from motion plan request
200  const std::vector<moveit_msgs::Constraints>& goals = req.goal_constraints;
201  if(goals.empty())
202  {
203  ROS_ERROR("A goal constraint was not provided");
204  error_code.val = error_code.INVALID_GOAL_CONSTRAINTS;
205  return false;
206  }
207  bool found_valid = false;
208  for(const auto& g: goals)
209  {
211  {
212  // decoding goal
213  state_->updateLinkTransforms();
214  Eigen::Affine3d start_tool_pose = state_->getGlobalLinkTransform(tool_link_);
215  boost::optional<moveit_msgs::Constraints> cartesian_constraints = utils::kinematics::curateCartesianConstraints(g,start_tool_pose);
216  if(cartesian_constraints.is_initialized())
217  {
218  Eigen::Affine3d tool_goal_pose;
219  found_valid = utils::kinematics::decodeCartesianConstraint(robot_model_,cartesian_constraints.get(),
220  tool_goal_pose,tool_goal_tolerance_,robot_model_->getRootLinkName());
221  }
222  }
223 
224  if(found_valid)
225  {
226  ROS_DEBUG_STREAM(getName()<< " using tool tolerances of "<< tool_goal_tolerance_.transpose());
227  break;
228  }
229  }
230 
231  if(!found_valid)
232  {
233  ROS_DEBUG("%s a cartesian goal pose in MotionPlanRequest was not provided,using default cartesian tolerance",getName().c_str());
234 
235  // creating default cartesian tolerance
237  double ptol = DEFAULT_POS_TOLERANCE;
238  double rtol = DEFAULT_ROT_TOLERANCE;
239  tool_goal_tolerance_ << ptol, ptol, ptol, rtol, rtol, rtol;
240  }
241 
242  error_code.val = error_code.SUCCESS;
243 
244  return true;
245 }
246 
247 bool GoalGuidedMultivariateGaussian::generateNoise(const Eigen::MatrixXd& parameters,
248  std::size_t start_timestep,
249  std::size_t num_timesteps,
250  int iteration_number,
251  int rollout_number,
252  Eigen::MatrixXd& parameters_noise,
253  Eigen::MatrixXd& noise)
254 {
255  using namespace Eigen;
256  using namespace stomp_moveit::utils;
257 
258  VectorXd goal_joint_pose, goal_joint_noise;
259  if(parameters.rows() != stddev_.size())
260  {
261  ROS_ERROR("%s Number of rows in parameters %i differs from expected number of joints",getName().c_str(),int(parameters.rows()));
262  return false;
263  }
264 
265  if(generateRandomGoal(parameters.rightCols(1),goal_joint_pose))
266  {
267  goal_joint_noise = goal_joint_pose - parameters.rightCols(1);
268  }
269  else
270  {
271  ROS_DEBUG("%s failed to generate random goal pose in the task space, not applying noise at goal",getName().c_str());
272  goal_joint_noise = VectorXd::Zero(parameters.rows());
273  }
274 
275  // generating noise
276  int sign;
277  for(auto d = 0u; d < parameters.rows() ; d++)
278  {
279  traj_noise_generators_[d]->sample(raw_noise_,true);
280 
281  // shifting data towards goal
282  sign = goal_joint_noise(d) > 0 ? 1 : -1;
283  noise.row(d).transpose() = stddev_[d] * raw_noise_+ sign*Eigen::VectorXd::LinSpaced(
284  raw_noise_.size(),0,std::abs(goal_joint_noise(d)));
285  }
286 
287  parameters_noise = parameters + noise;
288 
289  return true;
290 }
291 
292 bool GoalGuidedMultivariateGaussian::generateRandomGoal(const Eigen::VectorXd& reference_joint_pose,Eigen::VectorXd& goal_joint_pose)
293 {
294  using namespace Eigen;
295  using namespace moveit::core;
296  using namespace stomp_moveit::utils;
297 
298  // generate noise
299  Eigen::VectorXd noise = Eigen::VectorXd::Zero(CARTESIAN_DOF_SIZE);
300  for(auto d = 0u; d < noise.size(); d++)
301  {
302  noise(d) = tool_goal_tolerance_(d)*(*goal_rand_generator_)();
303  }
304 
305  // applying noise onto tool pose
306  state_->setJointGroupPositions(group_,reference_joint_pose);
307  state_->updateLinkTransforms();
308  Affine3d tool_pose = state_->getGlobalLinkTransform(tool_link_);
309  auto& n = noise;
310  Affine3d noisy_tool_pose = tool_pose * Translation3d(Vector3d(n(0),n(1),n(2)))*
311  AngleAxisd(n(3),Vector3d::UnitX())*AngleAxisd(n(4),Vector3d::UnitY())*AngleAxisd(n(5),Vector3d::UnitZ());
312 
313  if(!ik_solver_->solve(reference_joint_pose,noisy_tool_pose,goal_joint_pose,tool_goal_tolerance_))
314  {
315  ROS_DEBUG("%s could not solve ik, returning noiseless goal pose",getName().c_str());
316  goal_joint_pose= reference_joint_pose;
317  return false;
318  }
319 
320  return true;
321 }
322 
323 
324 } /* namespace noise_generators */
325 } /* namespace stomp_moveit */
d
virtual bool configure(const XmlRpc::XmlRpcValue &config) override
Sets internal members of the plugin from the configuration data.
virtual bool generateRandomGoal(const Eigen::VectorXd &reference_joint_pose, Eigen::VectorXd &goal_joint_pose)
Genereates a random tool pose by apply noise on the redundant axis to a reference tool pose;...
bool decodeCartesianConstraint(moveit::core::RobotModelConstPtr model, const moveit_msgs::Constraints &constraints, Eigen::Affine3d &tool_pose, std::vector< double > &tolerance, std::string target_frame="")
static const double DEFAULT_POS_TOLERANCE
virtual bool setupNoiseGeneration(const planning_scene::PlanningSceneConstPtr &planning_scene, const moveit_msgs::MotionPlanRequest &req, const stomp_core::StompConfiguration &config, moveit_msgs::MoveItErrorCodes &error_code)
virtual bool setMotionPlanRequest(const planning_scene::PlanningSceneConstPtr &planning_scene, const moveit_msgs::MotionPlanRequest &req, const stomp_core::StompConfiguration &config, moveit_msgs::MoveItErrorCodes &error_code) override
Stores the planning details.
static const std::vector< int > ACC_MATRIX_DIAGONAL_INDICES
virtual bool initialize(moveit::core::RobotModelConstPtr robot_model_ptr, const std::string &group_name, const XmlRpc::XmlRpcValue &config) override
Initializes and configures.
double sign(double arg)
static const int CARTESIAN_DOF_SIZE
virtual bool generateNoise(const Eigen::MatrixXd &parameters, std::size_t start_timestep, std::size_t num_timesteps, int iteration_number, int rollout_number, Eigen::MatrixXd &parameters_noise, Eigen::MatrixXd &noise) override
Generates a noisy trajectory from the parameters.
int size() const
const std::vector< std::string > & getLinkModelNames() const
boost::variate_generator< RGNType, boost::uniform_real<> > RandomGenerator
boost::optional< moveit_msgs::Constraints > curateCartesianConstraints(const moveit_msgs::Constraints &c, const Eigen::Affine3d &ref_pose, double default_pos_tol=0.0005, double default_rot_tol=M_PI)
This class generates noisy trajectories to an under-constrained cartesian goal pose.
std::vector< double > stddev_
The standard deviations applied to each joint, [num_dimensions x 1.
const std::vector< std::string > & getActiveJointModelNames() const
bool robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::RobotState &robot_state, RobotState &state, bool copy_attached_bodies=true)
std::vector< utils::MultivariateGaussianPtr > traj_noise_generators_
Randomized numerical distribution generators, [6 x 1].
#define ROS_DEBUG_STREAM(args)
This class generates noisy trajectories to an under-constrained cartesian goal pose.
bool isCartesianConstraints(const moveit_msgs::Constraints &c)
static const double DEFAULT_ROT_TOLERANCE
static const std::vector< double > ACC_MATRIX_DIAGONAL_VALUES
const std::vector< const JointModel * > & getActiveJointModels() const
r
#define ROS_ERROR(...)
PLUGINLIB_EXPORT_CLASS(stomp_moveit::noise_generators::GoalGuidedMultivariateGaussian, stomp_moveit::noise_generators::StompNoiseGenerator)
virtual bool setupGoalConstraints(const planning_scene::PlanningSceneConstPtr &planning_scene, const moveit_msgs::MotionPlanRequest &req, const stomp_core::StompConfiguration &config, moveit_msgs::MoveItErrorCodes &error_code)
#define ROS_DEBUG(...)


stomp_plugins
Author(s): Jorge Nicho
autogenerated on Fri May 8 2020 03:35:53