kinematics.cpp
Go to the documentation of this file.
1 
30 #include <math.h>
31 #include <random>
32 
33 static const std::string DEBUG_NS = "stomp_moveit_kinematics";
34 
35 KDL::JntArray toKDLJntArray(const std::vector<double>& vals)
36 {
37  KDL::JntArray jarr(vals.size());
38  for(int i = 0; i < jarr.rows(); i++)
39  {
40  jarr(i) = vals[i];
41  }
42  return std::move(jarr);
43 }
44 
45 KDL::Chain createKDLChain(moveit::core::RobotModelConstPtr robot_model,std::string base_link,std::string tip_link)
46 {
47  KDL::Tree tree;
48  KDL::Chain chain;
49  kdl_parser::treeFromUrdfModel(*robot_model->getURDF(),tree);
50  tree.getChain(base_link,tip_link,chain);
51  return chain;
52 }
53 
54 std::shared_ptr<TRAC_IK::TRAC_IK> createTRACIKSolver(moveit::core::RobotModelConstPtr robot_model,const moveit::core::JointModelGroup* group,double max_time = 0.01)
55 {
56  using namespace moveit::core;
57 
58  std::string base_link = group->getJointModels().front()->getParentLinkModel()->getName();
59  std::string tip_link = group->getLinkModelNames().back();
60  int num_joints = group->getActiveJointModelNames().size();
61 
62  ROS_DEBUG_NAMED(DEBUG_NS,"Creating IK solver with base link '%s' and tip link '%s'",base_link.c_str(),tip_link.c_str());
63 
64  // create chain
65  KDL::Chain kdl_chain = createKDLChain(robot_model,base_link,tip_link);
66 
67  // create joint array limits
68  const JointBoundsVector &bounds = group->getActiveJointModelsBounds();
69  std::vector<double> min_vals, max_vals;
70  for(int i = 0; i < num_joints;i++)
71  {
72  const JointModel::Bounds *jb = bounds[i];
73  for(auto& b: *jb)
74  {
75  max_vals.push_back(b.max_position_);
76  min_vals.push_back(b.min_position_);
77  }
78  }
79 
80  // copying to KDL joint arrays
81  num_joints = min_vals.size();
82  KDL::JntArray jmin = toKDLJntArray(min_vals);
83  KDL::JntArray jmax = toKDLJntArray(max_vals);
84  std::shared_ptr<TRAC_IK::TRAC_IK> solver(new TRAC_IK::TRAC_IK(kdl_chain,jmin,jmax,max_time));
85  return solver;
86 }
87 
88 namespace stomp_moveit
89 {
90 namespace utils
91 {
92 
97 namespace kinematics
98 {
99 
100 IKSolver::IKSolver(const moveit::core::RobotState& robot_state,std::string group_name,double max_time):
101  robot_model_(robot_state.getRobotModel()),
102  group_name_(group_name),
103  robot_state_(new moveit::core::RobotState(robot_state))
104 {
105  setKinematicState(robot_state);
106 
107  // create solver implementation
108  ik_solver_impl_ = createTRACIKSolver(robot_model_,robot_model_->getJointModelGroup(group_name),max_time);
109 }
110 
111 IKSolver::~IKSolver()
112 {
113 
114 }
115 
117 {
118  (*robot_state_) = state;
119  robot_state_->update();
120 
121  // update transform from base to root
122  const moveit::core::JointModelGroup* group = robot_state_->getJointModelGroup(group_name_);
123  std::string base_link = group->getJointModels().front()->getParentLinkModel()->getName();
124  Eigen::Affine3d root_to_base_tf = robot_state_->getFrameTransform(base_link);
125  tf_base_to_root_ = root_to_base_tf.inverse();
126 }
127 
128 bool IKSolver::solve(const Eigen::VectorXd& seed,const Eigen::Affine3d& tool_pose,Eigen::VectorXd& solution,
129  Eigen::VectorXd tol)
130 {
131  using namespace Eigen;
132  std::vector<double> seed_(seed.size(),0);
133  std::vector<double> solution_;
134  std::vector<double> tol_(6,0);
135 
136  // converting to eigen
137  VectorXd::Map(&seed_.front(),seed.size()) = seed;
138  VectorXd::Map(&tol_.front(),tol_.size()) = tol;
139 
140  if(!solve(seed_,tool_pose,solution_,tol_))
141  {
142  return false;
143  }
144 
145  solution.resize(solution_.size());
146  solution = VectorXd::Map(solution_.data(),solution_.size());
147  return true;
148 }
149 
150 bool IKSolver::solve(const std::vector<double>& seed, const Eigen::Affine3d& tool_pose,std::vector<double>& solution,
151  std::vector<double> tol)
152 {
153  using namespace KDL;
154  using namespace Eigen;
155  JntArray seed_kdl = toKDLJntArray(seed);
156  Twist tol_kdl;
157  JntArray solution_kdl;
158  Frame tool_pose_kdl;
159 
160  // converting tolerance to KDL data types
161  for(int i = 0; i < tol.size(); i++)
162  {
163  tol_kdl[i] = tol[i];
164  }
165 
166  // converting transform to kdl data type and transforming to chain base link
167  tf::transformEigenToKDL(tf_base_to_root_ * tool_pose, tool_pose_kdl);
168 
169  // calling solver
170  if(ik_solver_impl_->CartToJnt(seed_kdl,tool_pose_kdl,solution_kdl,tol_kdl) <= 0)
171  {
172  ROS_DEBUG_STREAM_NAMED(DEBUG_NS,"Failed to solve IK for tool pose:\n"<<tool_pose.matrix());
173  ROS_DEBUG_STREAM_NAMED(DEBUG_NS,"Cartesian tolerance used :\n"<<tol_kdl[0]<<" "<<tol_kdl[1]<<" "<<tol_kdl[2]<<" "<<tol_kdl[3]<<" "<<tol_kdl[4]<<" "<<tol_kdl[5]);
174  return false;
175  }
176 
177  solution.resize(solution_kdl.rows());
178  VectorXd::Map(&solution[0],solution.size()) = solution_kdl.data;
179  return true;
180 }
181 
182 bool IKSolver::solve(const std::vector<double>& seed, const moveit_msgs::Constraints& tool_constraints,std::vector<double>& solution)
183 {
184  Eigen::Affine3d tool_pose;
185  std::vector<double> tolerance;
186  if(!decodeCartesianConstraint(robot_model_,tool_constraints,tool_pose,tolerance))
187  {
188  return false;
189  }
190 
191  return solve(seed,tool_pose,solution,tolerance);
192 }
193 
194 bool IKSolver::solve(const Eigen::VectorXd& seed, const moveit_msgs::Constraints& tool_constraints,Eigen::VectorXd& solution)
195 {
196  Eigen::Affine3d tool_pose;
197  std::vector<double> tolerance;
198  if(!decodeCartesianConstraint(robot_model_,tool_constraints,tool_pose,tolerance))
199  {
200  return false;
201  }
202 
203  Eigen::VectorXd tolerance_eigen = Eigen::VectorXd::Zero(6);
204  tolerance_eigen = Eigen::VectorXd::Map(tolerance.data(),tolerance.size());
205  return solve(seed,tool_pose,solution,tolerance_eigen);
206 }
207 
208 bool isCartesianConstraints(const moveit_msgs::Constraints& c)
209 {
210  std::string pos_frame_id, orient_frame_id;
211  bool found_cart = false;
212  if(c.position_constraints.empty() && c.orientation_constraints.empty())
213  {
214  ROS_DEBUG("No cartesian constraints were found, failed validation");
215  return false;
216  }
217 
218  if(!c.position_constraints.empty())
219  {
220  pos_frame_id = c.position_constraints.front().header.frame_id;
221  found_cart = !pos_frame_id.empty();
222  }
223 
224  if(!c.orientation_constraints.empty())
225  {
226  orient_frame_id = c.orientation_constraints.front().header.frame_id;
227  found_cart = !orient_frame_id.empty();
228  }
229 
230  if(!pos_frame_id.empty() && !orient_frame_id.empty() && (pos_frame_id != orient_frame_id))
231  {
232  ROS_ERROR("Position frame id '%s' differs from orientation frame id '%s', invalid Cartesian constraint",
233  pos_frame_id.c_str(), orient_frame_id.c_str());
234  return false;
235  }
236 
237  return found_cart;
238 }
239 
240 boost::optional<moveit_msgs::Constraints> curateCartesianConstraints(const moveit_msgs::Constraints& c,const Eigen::Affine3d& ref_pose,
241  double default_pos_tol , double default_rot_tol)
242 {
243  using namespace moveit_msgs;
244 
245  moveit_msgs::Constraints full_constraint;
246  if(!isCartesianConstraints(c))
247  {
248  return boost::none;
249  }
250 
251  // obtaining defaults
252  int num_pos_constraints = c.position_constraints.size();
253  int num_orient_constraints = c.orientation_constraints.size();
254  int num_entries = num_pos_constraints >= num_orient_constraints ? num_pos_constraints : num_orient_constraints;
255  std::string frame_id = !c.position_constraints.empty() ? c.position_constraints.front().header.frame_id : c.orientation_constraints.front().header.frame_id ;
256 
257 
258  // creating default position constraint
259  PositionConstraint default_pos_constraint;
260  default_pos_constraint.header.frame_id = frame_id;
261  default_pos_constraint.constraint_region.primitive_poses.resize(1);
262  tf::poseEigenToMsg(Eigen::Affine3d::Identity(), default_pos_constraint.constraint_region.primitive_poses[0]);
263  default_pos_constraint.constraint_region.primitive_poses[0].position.x = ref_pose.translation().x();
264  default_pos_constraint.constraint_region.primitive_poses[0].position.y = ref_pose.translation().y();
265  default_pos_constraint.constraint_region.primitive_poses[0].position.z = ref_pose.translation().z();
266  shape_msgs::SolidPrimitive shape;
267  shape.type = shape.SPHERE;
268  shape.dimensions.push_back(default_pos_tol);
269  default_pos_constraint.constraint_region.primitives.push_back(shape);
270 
271  // creating default orientation constraint
272  OrientationConstraint default_orient_constraint;
273  default_orient_constraint.header.frame_id = frame_id;
274  default_orient_constraint.absolute_x_axis_tolerance = default_rot_tol;
275  default_orient_constraint.absolute_y_axis_tolerance = default_rot_tol;
276  default_orient_constraint.absolute_z_axis_tolerance = default_rot_tol;
277  default_orient_constraint.orientation.x = default_orient_constraint.orientation.y = default_orient_constraint.orientation.z = 0;
278  default_orient_constraint.orientation.w = 1;
279 
280 
281  full_constraint.position_constraints.resize(num_entries);
282  full_constraint.orientation_constraints.resize(num_entries);
283  for(int i =0; i < num_entries; i++)
284  {
285  // populating position constraints
286  if(c.position_constraints.size() >= num_entries)
287  {
288  full_constraint.position_constraints[i] = c.position_constraints[i];
289  }
290  else
291  {
292  full_constraint.position_constraints[i] = default_pos_constraint;
293  }
294 
295  // populating orientation constraints
296  if(c.orientation_constraints.size() >= num_entries)
297  {
298  full_constraint.orientation_constraints[i] = c.orientation_constraints[i];
299  }
300  else
301  {
302  full_constraint.orientation_constraints[i] = default_orient_constraint;
303  }
304  }
305 
306  return full_constraint;
307 }
308 
309 bool decodeCartesianConstraint(moveit::core::RobotModelConstPtr model, const moveit_msgs::Constraints& constraints, Eigen::Affine3d& tool_pose,
310  Eigen::VectorXd& tolerance, std::string target_frame)
311 {
312  std::vector<double> tolerance_std;
313  if(!decodeCartesianConstraint(model,constraints,tool_pose,tolerance_std,target_frame))
314  {
315  return false;
316  }
317 
318  tolerance = Eigen::VectorXd::Map(tolerance_std.data(),tolerance_std.size());
319  return true;
320 }
321 
322 bool decodeCartesianConstraint(moveit::core::RobotModelConstPtr model,const moveit_msgs::Constraints& constraints, Eigen::Affine3d& tool_pose,
323  std::vector<double>& tolerance, std::string target_frame)
324 {
325  using namespace Eigen;
326 
327  // declaring result variables
328  tolerance.resize(6,0);
329  geometry_msgs::Point p;
330  Eigen::Quaterniond q = Quaterniond::Identity();
331  const std::vector<moveit_msgs::PositionConstraint>& pos_constraints = constraints.position_constraints;
332  const std::vector<moveit_msgs::OrientationConstraint>& orient_constraints = constraints.orientation_constraints;
333 
334  int num_constraints = pos_constraints.size() > orient_constraints.size() ? pos_constraints.size() : orient_constraints.size();
335  if(num_constraints == 0)
336  {
337  ROS_ERROR("Constraints message is empty");
338  return false;
339  }
340 
341  // position
342  if(pos_constraints.empty())
343  {
344  ROS_ERROR("Position constraint is empty");
345  return false;
346  }
347  else
348  {
349  const moveit_msgs::PositionConstraint& pos_constraint = pos_constraints[0];
350 
351  // tool pose nominal position
352  p = pos_constraint.constraint_region.primitive_poses[0].position;
353 
354  // collecting position tolerances
355  const shape_msgs::SolidPrimitive& bv = pos_constraint.constraint_region.primitives[0];
356  bool valid_constraint = true;
357  switch(bv.type)
358  {
359  case shape_msgs::SolidPrimitive::BOX :
360  {
361  if(bv.dimensions.size() != 3)
362  {
363  ROS_WARN("Position constraint for BOX shape incorrectly defined, only 3 dimensions entries are needed");
364  valid_constraint = false;
365  break;
366  }
367 
368  using SP = shape_msgs::SolidPrimitive;
369  tolerance[0] = bv.dimensions[SP::BOX_X];
370  tolerance[1] = bv.dimensions[SP::BOX_Y];
371  tolerance[2] = bv.dimensions[SP::BOX_Z];
372  }
373  break;
374 
375  case shape_msgs::SolidPrimitive::SPHERE:
376  {
377  if(bv.dimensions.size() != 1)
378  {
379  ROS_WARN("Position constraint for SPHERE shape has no valid dimensions");
380  valid_constraint = false;
381  break;
382  }
383 
384  using SP = shape_msgs::SolidPrimitive;
385  tolerance[0] = bv.dimensions[SP::SPHERE_RADIUS];
386  tolerance[1] = bv.dimensions[SP::SPHERE_RADIUS];
387  tolerance[2] = bv.dimensions[SP::SPHERE_RADIUS];
388  }
389  break;
390 
391  default:
392 
393  ROS_WARN("The Position constraint shape %i isn't supported, defaulting position tolerance to zero",bv.type);
394  break;
395  }
396  }
397 
398  // orientation
399  if(orient_constraints.size() == 0)
400  {
401  // setting tolerance to zero
402  std::fill(tolerance.begin()+3,tolerance.end(),M_PI);
403  }
404  else
405  {
406  const moveit_msgs::OrientationConstraint& orient_constraint = orient_constraints[0];
407 
408  // collecting orientation tolerance
409  tolerance[3] = orient_constraint.absolute_x_axis_tolerance;
410  tolerance[4] = orient_constraint.absolute_y_axis_tolerance;
411  tolerance[5] = orient_constraint.absolute_z_axis_tolerance;
412 
413  // tool pose nominal orientation
414  tf::quaternionMsgToEigen(orient_constraint.orientation,q);
415  }
416 
417  // assembling tool pose
418  tool_pose = Affine3d::Identity()*Eigen::Translation3d(Eigen::Vector3d(p.x,p.y,p.z))*q;
419 
420  // transforming tool pose
421  if(target_frame.empty())
422  {
423  target_frame = model->getModelFrame();
424  }
425 
426  const moveit_msgs::PositionConstraint& pos_constraint = pos_constraints[0];
427  std::string frame_id = pos_constraint.header.frame_id;
428  moveit::core::RobotState state(model);
429  state.update();
430  if(!state.knowsFrameTransform(frame_id))
431  {
432  ROS_ERROR("Frame '%s' is not part of the model",frame_id.c_str());
433  return false;
434  }
435  else if(!state.knowsFrameTransform(target_frame))
436  {
437  ROS_ERROR("Frame '%s' is not part of the model",target_frame.c_str());
438  return false;
439  }
440 
441  if(!frame_id.empty() && target_frame != frame_id)
442  {
443  Eigen::Affine3d root_to_frame = state.getFrameTransform(frame_id);
444  Eigen::Affine3d root_to_target = state.getFrameTransform(target_frame);
445  tool_pose = (root_to_target.inverse()) * root_to_frame * tool_pose;
446  }
447 
448  return true;
449 }
450 
451 EigenSTL::vector_Affine3d sampleCartesianPoses(const moveit_msgs::Constraints& c,const std::vector<double> sampling_resolution,int max_samples)
452 {
453  using namespace Eigen;
455 
456  // random generator
457  std::random_device rd;
458  std::mt19937 gen(rd());
459  auto sample_val_func = [&gen](double min, double max, double intrv) -> double
460  {
461  double length = max - min;
462  if(length <= intrv || length < 1e-6)
463  {
464  return 0.5*(max + min); // return average
465  }
466 
467  int num_intervals = std::ceil(length/intrv);
468  std::uniform_int_distribution<> dis(0, num_intervals);
469  int r = dis(gen);
470  double val = min + r*(intrv);
471  val = val > max ? max : val;
472  return val;
473  };
474 
475  // extracting tolerances from constraints
476  const std::vector<moveit_msgs::PositionConstraint>& pos_constraints = c.position_constraints;
477  const std::vector<moveit_msgs::OrientationConstraint>& orient_constraints = c.orientation_constraints;
478  for(std::size_t k = 0; k < pos_constraints.size(); k++)
479  {
480 
481  const moveit_msgs::PositionConstraint& pos_constraint = pos_constraints[k];
482  const moveit_msgs::OrientationConstraint& orient_constraint = orient_constraints[k];
483 
484  // collecting position tolerances
485  std::vector<double> tolerances(6);
486  const shape_msgs::SolidPrimitive& bv = pos_constraint.constraint_region.primitives[0];
487  bool valid_constraint = true;
488  switch(bv.type)
489  {
490  case shape_msgs::SolidPrimitive::BOX :
491  {
492  if(bv.dimensions.size() != 3)
493  {
494  ROS_WARN("Position constraint for BOX shape incorrectly defined, only 3 dimensions entries are needed");
495  valid_constraint = false;
496  break;
497  }
498 
499  using SP = shape_msgs::SolidPrimitive;
500  tolerances[0] = bv.dimensions[SP::BOX_X];
501  tolerances[1] = bv.dimensions[SP::BOX_Y];
502  tolerances[2] = bv.dimensions[SP::BOX_Z];
503  }
504  break;
505 
506  case shape_msgs::SolidPrimitive::SPHERE:
507  {
508  if(bv.dimensions.size() != 1)
509  {
510  ROS_WARN("Position constraint for SPHERE shape has no valid dimensions");
511  valid_constraint = false;
512  break;
513  }
514 
515  using SP = shape_msgs::SolidPrimitive;
516  tolerances[0] = bv.dimensions[SP::SPHERE_RADIUS];
517  tolerances[1] = bv.dimensions[SP::SPHERE_RADIUS];
518  tolerances[2] = bv.dimensions[SP::SPHERE_RADIUS];
519  }
520  break;
521 
522  default:
523 
524  ROS_ERROR("The Position constraint shape %i isn't supported",bv.type);
525  valid_constraint = false;
526  break;
527  }
528 
529  if(!valid_constraint)
530  {
531  continue;
532  }
533 
534  // collecting orientation tolerance
535  tolerances[3] = orient_constraint.absolute_x_axis_tolerance;
536  tolerances[4] = orient_constraint.absolute_y_axis_tolerance;
537  tolerances[5] = orient_constraint.absolute_z_axis_tolerance;
538 
539  // calculating total number of samples
540  int total_num_samples = 1;
541  for(std::size_t i = 0; i < tolerances.size(); i++)
542  {
543  total_num_samples *= (std::floor((2*tolerances[i]/sampling_resolution[i]) + 1) );
544  }
545  total_num_samples = total_num_samples > max_samples ? max_samples : total_num_samples;
546 
547 
548  // tool pose nominal position
549  auto& p = pos_constraint.constraint_region.primitive_poses[0].position;
550 
551  // tool pose nominal orientation
552  Eigen::Quaterniond q;
553  tf::quaternionMsgToEigen(orient_constraint.orientation,q);
554 
555  // generating samples
556  std::vector<double> vals(6);
557  Affine3d nominal_pos = Affine3d::Identity()*Eigen::Translation3d(Eigen::Vector3d(p.x,p.y,p.z));
558  Affine3d nominal_rot = Affine3d::Identity()*q;
559  for(int i = 0; i < total_num_samples; i++)
560  {
561  for(int j = 0; j < vals.size() ; j++)
562  {
563  vals[j] = sample_val_func(-0.5*tolerances[j],0.5*tolerances[j],sampling_resolution[j]);
564  }
565 
566  Affine3d rot = nominal_rot * AngleAxisd(vals[3],Vector3d::UnitX()) * AngleAxisd(vals[4],Vector3d::UnitY())
567  * AngleAxisd(vals[5],Vector3d::UnitZ());
568  Affine3d pose = nominal_pos * Translation3d(Vector3d(vals[0],vals[1],vals[2])) * rot;
569  poses.push_back(pose);
570  }
571 
572  if(poses.size()>= max_samples)
573  {
574  break;
575  }
576  }
577 
578  return poses;
579 }
580 
581 void computeTwist(const Eigen::Affine3d& p0,
582  const Eigen::Affine3d& pf,
583  const Eigen::ArrayXi& nullity,Eigen::VectorXd& twist)
584 {
585  twist.resize(nullity.size());
586  twist.setConstant(0);
587 
588  // relative transform
589  auto p0_inv = p0.inverse();
590  Eigen::Affine3d t = (p0_inv) * pf;
591 
592  Eigen::Vector3d twist_pos = pf.translation() - p0.translation();
593 
594  // relative rotation -> R = inverse(R0) * Rf
595  Eigen::AngleAxisd relative_rot(t.rotation());
596  double angle = relative_rot.angle();
597  Eigen::Vector3d axis = relative_rot.axis();
598 
599  // forcing angle to range [-pi , pi]
600  while( (angle > M_PI) || (angle < -M_PI))
601  {
602  angle = (angle > M_PI) ? (angle - 2*M_PI) : angle;
603  angle = (angle < -M_PI )? (angle + 2*M_PI) : angle;
604  }
605 
606  // creating twist rotation relative to tool
607  Eigen::Vector3d twist_rot = axis.normalized() * angle;
608 
609  // assigning into full 6dof twist vector
610  twist.head(3) = twist_pos;
611  twist.tail(3) = twist_rot;
612 
613  // zeroing all underconstrained cartesian dofs
614  twist = (nullity == 0).select(0,twist);
615 }
616 
617 void reduceJacobian(const Eigen::MatrixXd& jacb,
618  const std::vector<int>& indices,Eigen::MatrixXd& jacb_reduced)
619 {
620  jacb_reduced.resize(indices.size(),jacb.cols());
621  for(auto i = 0u; i < indices.size(); i++)
622  {
623  jacb_reduced.row(i) = jacb.row(indices[i]);
624  }
625 }
626 
627 
628 void calculateDampedPseudoInverse(const Eigen::MatrixXd &jacb, Eigen::MatrixXd &jacb_pseudo_inv,
629  double eps, double lambda)
630 {
631  using namespace Eigen;
632 
633 
634  //Calculate A+ (pseudoinverse of A) = V S+ U*, where U* is Hermition of U (just transpose if all values of U are real)
635  //in order to solve Ax=b -> x*=A+ b
636  Eigen::JacobiSVD<MatrixXd> svd(jacb, Eigen::ComputeThinU | Eigen::ComputeThinV);
637  const MatrixXd &U = svd.matrixU();
638  const VectorXd &Sv = svd.singularValues();
639  const MatrixXd &V = svd.matrixV();
640 
641  // calculate the reciprocal of Singular-Values
642  // damp inverse with lambda so that inverse doesn't oscillate near solution
643  size_t nSv = Sv.size();
644  VectorXd inv_Sv(nSv);
645  for(size_t i=0; i< nSv; ++i)
646  {
647  if (fabs(Sv(i)) > eps)
648  {
649  inv_Sv(i) = 1/Sv(i);
650  }
651  else
652  {
653  inv_Sv(i) = Sv(i) / (Sv(i)*Sv(i) + lambda*lambda);
654  }
655  }
656 
657  jacb_pseudo_inv = V * inv_Sv.asDiagonal() * U.transpose();
658 }
659 
660 bool computeJacobianNullSpace(moveit::core::RobotStatePtr state,std::string group,std::string tool_link,
661  const Eigen::ArrayXi& constrained_dofs,const Eigen::VectorXd& joint_pose,
662  Eigen::MatrixXd& jacb_nullspace)
663 {
664  using namespace Eigen;
665  using namespace moveit::core;
666 
667  // robot state
668  const JointModelGroup* joint_group = state->getJointModelGroup(group);
669  state->setJointGroupPositions(joint_group,joint_pose);
670  Affine3d tool_pose = state->getGlobalLinkTransform(tool_link);
671 
672  // jacobian calculations
673  static MatrixXd jacb_transform(6,6);
674  MatrixXd jacb, jacb_reduced, jacb_pseudo_inv;
675  jacb_transform.setZero();
676 
677  if(!state->getJacobian(joint_group,state->getLinkModel(tool_link),Vector3d::Zero(),jacb))
678  {
679  ROS_ERROR("Failed to get Jacobian for link %s",tool_link.c_str());
680  return false;
681  }
682 
683  // transform jacobian rotational part to tool coordinates
684  auto rot = tool_pose.inverse().rotation();
685  jacb_transform.setZero();
686  jacb_transform.block(0,0,3,3) = rot;
687  jacb_transform.block(3,3,3,3) = rot;
688  jacb = jacb_transform*jacb;
689 
690  // reduce jacobian and compute its pseudo inverse
691  std::vector<int> indices;
692  for(auto i = 0u; i < constrained_dofs.size(); i++)
693  {
694  if(constrained_dofs(i) != 0)
695  {
696  indices.push_back(i);
697  }
698  }
699  reduceJacobian(jacb,indices,jacb_reduced);
700  calculateDampedPseudoInverse(jacb_reduced,jacb_pseudo_inv,EPSILON,LAMBDA);
701 
702  int num_joints = joint_pose.size();
703  jacb_nullspace = MatrixXd::Identity(num_joints,num_joints) - jacb_pseudo_inv*jacb_reduced;
704 
705  return true;
706 }
707 
708 } // kinematics
709 } // utils
710 } // stomp_moveit
711 
712 
713 
714 
bool decodeCartesianConstraint(moveit::core::RobotModelConstPtr model, const moveit_msgs::Constraints &constraints, Eigen::Affine3d &tool_pose, std::vector< double > &tolerance, std::string target_frame="")
Extracts the cartesian data from the constraint message.
Definition: kinematics.cpp:322
#define ROS_DEBUG_STREAM_NAMED(name, args)
std::vector< Eigen::Affine3d, Eigen::aligned_allocator< Eigen::Affine3d > > vector_Affine3d
KDL_PARSER_PUBLIC bool treeFromUrdfModel(const urdf::ModelInterface &robot_model, KDL::Tree &tree)
unsigned int rows() const
bool knowsFrameTransform(const std::string &id) const
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
bool computeJacobianNullSpace(moveit::core::RobotStatePtr state, std::string group, std::string tool_link, const Eigen::ArrayXi &constrained_dofs, const Eigen::VectorXd &joint_pose, Eigen::MatrixXd &jacb_nullspace)
Convenience function to calculate the Jacobian&#39;s null space matrix for an under constrained tool cart...
Definition: kinematics.cpp:660
const std::vector< std::string > & getLinkModelNames() const
const LinkModel * getLinkModel(const std::string &link) const
EigenSTL::vector_Affine3d sampleCartesianPoses(const moveit_msgs::Constraints &c, const std::vector< double > sampling_resolution={0.05, 0.05, 0.05, M_PI_2, M_PI_2, M_PI_2}, int max_samples=20)
Creates cartesian poses in accordance to the constraint and sampling resolution values.
Definition: kinematics.cpp:451
const Eigen::Affine3d & getFrameTransform(const std::string &id)
void reduceJacobian(const Eigen::MatrixXd &jacb, const std::vector< int > &indices, Eigen::MatrixXd &jacb_reduced)
Convenience function to remove entire rows of the Jacobian matrix.
Definition: kinematics.cpp:617
#define M_PI
#define ROS_WARN(...)
void transformEigenToKDL(const Eigen::Affine3d &e, KDL::Frame &k)
void computeTwist(const Eigen::Affine3d &p0, const Eigen::Affine3d &pf, const Eigen::ArrayXi &nullity, Eigen::VectorXd &twist)
Computes the twist vector [vx vy vz wx wy wz]&#39; relative to the current tool coordinate system...
Definition: kinematics.cpp:581
static const double EPSILON
Used in dampening the matrix pseudo inverse calculation.
Definition: kinematics.h:61
#define ROS_DEBUG_NAMED(name,...)
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)
Populates the missing parts of a Cartesian constraints in order to provide a constraint that can be u...
Definition: kinematics.cpp:240
void update(bool force=false)
static const double LAMBDA
Used in dampening the matrix pseudo inverse calculation.
Definition: kinematics.h:62
Eigen::VectorXd data
std::vector< const JointModel::Bounds * > JointBoundsVector
const std::vector< std::string > & getActiveJointModelNames() const
This defines kinematic related utilities.
double min(double a, double b)
const std::vector< const JointModel * > & getJointModels() const
bool isCartesianConstraints(const moveit_msgs::Constraints &c)
Checks if the constraint structured contains valid data from which a proper cartesian constraint can ...
Definition: kinematics.cpp:208
bool getChain(const std::string &chain_root, const std::string &chain_tip, Chain &chain) const
void quaternionMsgToEigen(const geometry_msgs::Quaternion &m, Eigen::Quaterniond &e)
bool solve(const Eigen::VectorXd &seed, const Eigen::Affine3d &tool_pose, Eigen::VectorXd &solution, Eigen::VectorXd tol=Eigen::VectorXd::Constant(6, 0.005))
Find the joint position that achieves the requested tool pose.
Definition: kinematics.cpp:128
r
double max(double a, double b)
std::vector< VariableBounds > Bounds
#define ROS_ERROR(...)
void setKinematicState(const moveit::core::RobotState &state)
Should be called whenever the robot&#39;s kinematic state has changed.
Definition: kinematics.cpp:116
const JointBoundsVector & getActiveJointModelsBounds() const
#define ROS_DEBUG(...)
void calculateDampedPseudoInverse(const Eigen::MatrixXd &jacb, Eigen::MatrixXd &jacb_pseudo_inv, double eps=0.011, double lambda=0.01)
Calculates the damped pseudo inverse of a matrix using singular value decomposition.
Definition: kinematics.cpp:628


stomp_moveit
Author(s): Jorge Nicho
autogenerated on Fri May 8 2020 03:35:47