moveit2
The MoveIt Motion Planning Framework for ROS 2.
default_constraint_samplers.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Ioan Sucan */
36 
38 #include <rclcpp/logger.hpp>
39 #include <rclcpp/logging.hpp>
40 #include <cassert>
41 #include <functional>
42 
43 namespace constraint_samplers
44 {
45 static const rclcpp::Logger LOGGER = rclcpp::get_logger("moveit_constraint_samplers.default_constraint_samplers");
46 
47 bool JointConstraintSampler::configure(const moveit_msgs::msg::Constraints& constr)
48 {
49  // construct the constraints
50  std::vector<kinematic_constraints::JointConstraint> jc;
51  for (const moveit_msgs::msg::JointConstraint& joint_constraint : constr.joint_constraints)
52  {
54  if (j.configure(joint_constraint))
55  jc.push_back(j);
56  }
57 
58  return jc.empty() ? false : configure(jc);
59 }
60 
61 bool JointConstraintSampler::configure(const std::vector<kinematic_constraints::JointConstraint>& jc)
62 {
63  clear();
64 
65  if (!jmg_)
66  {
67  RCLCPP_ERROR(LOGGER, "nullptr group specified for constraint sampler");
68  return false;
69  }
70 
71  // find and keep the constraints that operate on the group we sample
72  // also keep bounds for joints as convenient
73  std::map<std::string, JointInfo> bound_data;
74  bool some_valid_constraint = false;
75  for (const kinematic_constraints::JointConstraint& joint_constraint : jc)
76  {
77  if (!joint_constraint.enabled())
78  continue;
79 
80  const moveit::core::JointModel* jm = joint_constraint.getJointModel();
81  if (!jmg_->hasJointModel(jm->getName()))
82  continue;
83 
84  some_valid_constraint = true;
85 
86  const moveit::core::VariableBounds& joint_bounds = jm->getVariableBounds(joint_constraint.getJointVariableName());
87  JointInfo ji;
88  std::map<std::string, JointInfo>::iterator it = bound_data.find(joint_constraint.getJointVariableName());
89  if (it != bound_data.end())
90  {
91  ji = it->second;
92  }
93  else
94  {
95  ji.index_ = jmg_->getVariableGroupIndex(joint_constraint.getJointVariableName());
96  }
98  std::max(joint_bounds.min_position_,
99  joint_constraint.getDesiredJointPosition() - joint_constraint.getJointToleranceBelow()),
100  std::min(joint_bounds.max_position_,
101  joint_constraint.getDesiredJointPosition() + joint_constraint.getJointToleranceAbove()));
102 
103  RCLCPP_DEBUG(LOGGER, "Bounds for %s JointConstraint are %g %g", joint_constraint.getJointVariableName().c_str(),
104  ji.min_bound_, ji.max_bound_);
105 
106  if (ji.min_bound_ > ji.max_bound_ + std::numeric_limits<double>::epsilon())
107  {
108  std::stringstream cs;
109  joint_constraint.print(cs);
110  RCLCPP_ERROR(LOGGER,
111  "The constraints for joint '%s' are such that "
112  "there are no possible values for the joint: min_bound: %g, max_bound: %g. Failing.\n",
113  jm->getName().c_str(), ji.min_bound_, ji.max_bound_);
114  clear();
115  return false;
116  }
117  bound_data[joint_constraint.getJointVariableName()] = ji;
118  }
119 
120  if (!some_valid_constraint)
121  {
122  RCLCPP_WARN(LOGGER, "No valid joint constraints");
123  return false;
124  }
125 
126  for (std::pair<const std::string, JointInfo>& it : bound_data)
127  bounds_.push_back(it.second);
128 
129  // get a separate list of joints that are not bounded; we will sample these randomly
130  const std::vector<const moveit::core::JointModel*>& joints = jmg_->getJointModels();
131  for (const moveit::core::JointModel* joint : joints)
132  {
133  if (bound_data.find(joint->getName()) == bound_data.end() && joint->getVariableCount() > 0 &&
134  joint->getMimic() == nullptr)
135  {
136  // check if all the vars of the joint are found in bound_data instead
137  const std::vector<std::string>& vars = joint->getVariableNames();
138  if (vars.size() > 1)
139  {
140  bool all_found = true;
141  for (const std::string& var : vars)
142  {
143  if (bound_data.find(var) == bound_data.end())
144  {
145  all_found = false;
146  break;
147  }
148  }
149  if (all_found)
150  continue;
151  }
152  unbounded_.push_back(joint);
153  // Get the first variable name of this joint and find its index position in the planning group
154  uindex_.push_back(jmg_->getVariableGroupIndex(vars[0]));
155  }
156  }
157  values_.resize(jmg_->getVariableCount());
158  is_valid_ = true;
159  return true;
160 }
161 
163  const moveit::core::RobotState& /* reference_state */,
164  unsigned int /* max_attempts */)
165 {
166  if (!is_valid_)
167  {
168  RCLCPP_WARN(LOGGER, "JointConstraintSampler not configured, won't sample");
169  return false;
170  }
171 
172  // sample the unbounded joints first (in case some joint variables are bounded)
173  std::vector<double> v;
174  for (std::size_t i = 0; i < unbounded_.size(); ++i)
175  {
176  v.resize(unbounded_[i]->getVariableCount());
177  unbounded_[i]->getVariableRandomPositions(random_number_generator_, &v[0]);
178  for (std::size_t j = 0; j < v.size(); ++j)
179  values_[uindex_[i] + j] = v[j];
180  }
181 
182  // enforce the constraints for the constrained components (could be all of them)
183  for (const JointInfo& bound : bounds_)
184  values_[bound.index_] = random_number_generator_.uniformReal(bound.min_bound_, bound.max_bound_);
185 
187 
188  // we are always successful
189  return true;
190 }
191 
193 {
195  bounds_.clear();
196  unbounded_.clear();
197  uindex_.clear();
198  values_.clear();
199 }
200 
202 {
203 }
204 
206  : position_constraint_(std::make_shared<kinematic_constraints::PositionConstraint>(pc))
207 {
208 }
209 
211  : orientation_constraint_(std::make_shared<kinematic_constraints::OrientationConstraint>(oc))
212 {
213 }
214 
217  : position_constraint_(std::make_shared<kinematic_constraints::PositionConstraint>(pc))
218  , orientation_constraint_(std::make_shared<kinematic_constraints::OrientationConstraint>(oc))
219 {
220 }
221 
222 IKSamplingPose::IKSamplingPose(const kinematic_constraints::PositionConstraintPtr& pc) : position_constraint_(pc)
223 {
224 }
225 
226 IKSamplingPose::IKSamplingPose(const kinematic_constraints::OrientationConstraintPtr& oc) : orientation_constraint_(oc)
227 {
228 }
229 
230 IKSamplingPose::IKSamplingPose(const kinematic_constraints::PositionConstraintPtr& pc,
231  const kinematic_constraints::OrientationConstraintPtr& oc)
232  : position_constraint_(pc), orientation_constraint_(oc)
233 {
234 }
235 
237 {
239  kb_.reset();
240  ik_frame_ = "";
241  transform_ik_ = false;
242  eef_to_ik_tip_transform_ = Eigen::Isometry3d::Identity();
244 }
245 
247 {
248  clear();
250  return false;
251  if ((!sp.orientation_constraint_ && !sp.position_constraint_->enabled()) ||
252  (!sp.position_constraint_ && !sp.orientation_constraint_->enabled()) ||
254  !sp.orientation_constraint_->enabled()))
255  {
256  RCLCPP_WARN(LOGGER, "No enabled constraints in sampling pose");
257  return false;
258  }
259 
260  sampling_pose_ = sp;
263  {
264  if (sampling_pose_.position_constraint_->getLinkModel()->getName() !=
265  sampling_pose_.orientation_constraint_->getLinkModel()->getName())
266  {
267  RCLCPP_ERROR(LOGGER, "Position and orientation constraints need to be specified for the same link "
268  "in order to use IK-based sampling");
269  return false;
270  }
271  }
272 
274  frame_depends_.push_back(sampling_pose_.position_constraint_->getReferenceFrame());
276  frame_depends_.push_back(sampling_pose_.orientation_constraint_->getReferenceFrame());
278  if (!kb_)
279  {
280  RCLCPP_WARN(LOGGER, "No solver instance in setup");
281  is_valid_ = false;
282  return false;
283  }
285  return is_valid_;
286 }
287 
288 bool IKConstraintSampler::configure(const moveit_msgs::msg::Constraints& constr)
289 {
290  for (std::size_t p = 0; p < constr.position_constraints.size(); ++p)
291  {
292  for (std::size_t o = 0; o < constr.orientation_constraints.size(); ++o)
293  {
294  if (constr.position_constraints[p].link_name == constr.orientation_constraints[o].link_name)
295  {
296  kinematic_constraints::PositionConstraintPtr pc(
297  new kinematic_constraints::PositionConstraint(scene_->getRobotModel()));
298  kinematic_constraints::OrientationConstraintPtr oc(
300  if (pc->configure(constr.position_constraints[p], scene_->getTransforms()) &&
301  oc->configure(constr.orientation_constraints[o], scene_->getTransforms()))
302  return configure(IKSamplingPose(pc, oc));
303  }
304  }
305  }
306 
307  for (const moveit_msgs::msg::PositionConstraint& position_constraint : constr.position_constraints)
308  {
309  kinematic_constraints::PositionConstraintPtr pc(
310  new kinematic_constraints::PositionConstraint(scene_->getRobotModel()));
311  if (pc->configure(position_constraint, scene_->getTransforms()))
312  return configure(IKSamplingPose(pc));
313  }
314 
315  for (const moveit_msgs::msg::OrientationConstraint& orientation_constraint : constr.orientation_constraints)
316  {
317  kinematic_constraints::OrientationConstraintPtr oc(
319  if (oc->configure(orientation_constraint, scene_->getTransforms()))
320  return configure(IKSamplingPose(oc));
321  }
322  return false;
323 }
324 
326 {
327  double v = 1.0;
329  {
330  const std::vector<bodies::BodyPtr>& constraint_regions =
331  sampling_pose_.position_constraint_->getConstraintRegions();
332  double vol = 0;
333  for (const bodies::BodyPtr& constraint_region : constraint_regions)
334  vol += constraint_region->computeVolume();
335  if (!constraint_regions.empty())
336  v *= vol;
337  }
338 
340  {
341  v *= sampling_pose_.orientation_constraint_->getXAxisTolerance() *
342  sampling_pose_.orientation_constraint_->getYAxisTolerance() *
343  sampling_pose_.orientation_constraint_->getZAxisTolerance();
344  }
345  return v;
346 }
347 
348 const std::string& IKConstraintSampler::getLinkName() const
349 {
351  return sampling_pose_.orientation_constraint_->getLinkModel()->getName();
352  return sampling_pose_.position_constraint_->getLinkModel()->getName();
353 }
354 
356 {
357  if (!kb_)
358  {
359  RCLCPP_ERROR(LOGGER, "No IK solver");
360  return false;
361  }
362 
363  // check if we need to transform the request into the coordinate frame expected by IK
364  ik_frame_ = kb_->getBaseFrame();
366  if (!ik_frame_.empty() && ik_frame_[0] == '/')
367  ik_frame_.erase(ik_frame_.begin());
368  if (transform_ik_)
369  {
371  {
372  RCLCPP_ERROR(LOGGER,
373  "The IK solver expects requests in frame '%s' but this frame is not known to the sampler. "
374  "Ignoring transformation (IK may fail)",
375  ik_frame_.c_str());
376  transform_ik_ = false;
377  }
378  }
379 
380  // check if IK is performed for the desired link
381  bool wrong_link = false;
383  {
384  const moveit::core::LinkModel* lm = sampling_pose_.position_constraint_->getLinkModel();
385  if (!moveit::core::Transforms::sameFrame(kb_->getTipFrame(), lm->getName()))
386  {
387  wrong_link = true;
389  for (const std::pair<const moveit::core::LinkModel* const, Eigen::Isometry3d>& fixed_link : fixed_links)
390  {
391  if (moveit::core::Transforms::sameFrame(fixed_link.first->getName(), kb_->getTipFrame()))
392  {
393  eef_to_ik_tip_transform_ = fixed_link.second; // valid isometry by contract
395  wrong_link = false;
396  break;
397  }
398  }
399  }
400  }
401 
402  if (!wrong_link && sampling_pose_.orientation_constraint_)
403  {
405  if (!moveit::core::Transforms::sameFrame(kb_->getTipFrame(), lm->getName()))
406  {
407  wrong_link = true;
409  for (const std::pair<const moveit::core::LinkModel* const, Eigen::Isometry3d>& fixed_link : fixed_links)
410  {
411  if (moveit::core::Transforms::sameFrame(fixed_link.first->getName(), kb_->getTipFrame()))
412  {
413  eef_to_ik_tip_transform_ = fixed_link.second; // valid isometry by contract
415  wrong_link = false;
416  break;
417  }
418  }
419  }
420  }
421 
422  if (wrong_link)
423  {
424  RCLCPP_ERROR(LOGGER, "IK cannot be performed for link '%s'. The solver can report IK solutions for link '%s'.",
426  sampling_pose_.position_constraint_->getLinkModel()->getName().c_str() :
427  sampling_pose_.orientation_constraint_->getLinkModel()->getName().c_str(),
428  kb_->getTipFrame().c_str());
429  return false;
430  }
431  return true;
432 }
433 
434 bool IKConstraintSampler::samplePose(Eigen::Vector3d& pos, Eigen::Quaterniond& quat, const moveit::core::RobotState& ks,
435  unsigned int max_attempts)
436 {
437  if (ks.dirtyLinkTransforms())
438  {
439  // samplePose below requires accurate transforms
440  RCLCPP_ERROR(LOGGER, "IKConstraintSampler received dirty robot state, but valid transforms are required. "
441  "Failing.");
442  return false;
443  }
444 
446  {
447  const std::vector<bodies::BodyPtr>& b = sampling_pose_.position_constraint_->getConstraintRegions();
448  if (!b.empty())
449  {
450  bool found = false;
451  std::size_t k = random_number_generator_.uniformInteger(0, b.size() - 1);
452  for (std::size_t i = 0; i < b.size(); ++i)
453  {
454  if (b[(i + k) % b.size()]->samplePointInside(random_number_generator_, max_attempts, pos))
455  {
456  found = true;
457  break;
458  }
459  }
460  if (!found)
461  {
462  RCLCPP_ERROR(LOGGER, "Unable to sample a point inside the constraint region");
463  return false;
464  }
465  }
466  else
467  {
468  RCLCPP_ERROR(LOGGER, "Unable to sample a point inside the constraint region. "
469  "Constraint region is empty when it should not be.");
470  return false;
471  }
472 
473  // if this constraint is with respect a mobile frame, we need to convert this rotation to the root frame of the
474  // model
475  if (sampling_pose_.position_constraint_->mobileReferenceFrame())
476  pos = ks.getFrameTransform(sampling_pose_.position_constraint_->getReferenceFrame()) * pos;
477  }
478  else
479  {
480  // do FK for rand state
481  moveit::core::RobotState temp_state(ks);
482  temp_state.setToRandomPositions(jmg_);
483  pos = temp_state.getGlobalLinkTransform(sampling_pose_.orientation_constraint_->getLinkModel()).translation();
484  }
485 
487  {
488  // sample a rotation matrix within the allowed bounds
489  double angle_x =
490  2.0 * (random_number_generator_.uniform01() - 0.5) *
491  (sampling_pose_.orientation_constraint_->getXAxisTolerance() - std::numeric_limits<double>::epsilon());
492  double angle_y =
493  2.0 * (random_number_generator_.uniform01() - 0.5) *
494  (sampling_pose_.orientation_constraint_->getYAxisTolerance() - std::numeric_limits<double>::epsilon());
495  double angle_z =
496  2.0 * (random_number_generator_.uniform01() - 0.5) *
497  (sampling_pose_.orientation_constraint_->getZAxisTolerance() - std::numeric_limits<double>::epsilon());
498 
499  Eigen::Isometry3d diff;
500  if (sampling_pose_.orientation_constraint_->getParameterizationType() ==
501  moveit_msgs::msg::OrientationConstraint::XYZ_EULER_ANGLES)
502  {
503  diff = Eigen::Isometry3d(Eigen::AngleAxisd(angle_x, Eigen::Vector3d::UnitX()) *
504  Eigen::AngleAxisd(angle_y, Eigen::Vector3d::UnitY()) *
505  Eigen::AngleAxisd(angle_z, Eigen::Vector3d::UnitZ()));
506  }
507  else if (sampling_pose_.orientation_constraint_->getParameterizationType() ==
508  moveit_msgs::msg::OrientationConstraint::ROTATION_VECTOR)
509  {
510  Eigen::Vector3d rotation_vector(angle_x, angle_y, angle_z);
511  diff = Eigen::Isometry3d(Eigen::AngleAxisd(rotation_vector.norm(), rotation_vector.normalized()));
512  }
513  else
514  {
515  /* The parameterization type should be validated in configure, so this should never happen. */
516  RCLCPP_ERROR(LOGGER, "The parameterization type for the orientation constraints is invalid.");
517  }
518  // diff is isometry by construction
519  // getDesiredRotationMatrix() returns a valid rotation matrix by contract
520  // reqr has thus to be a valid isometry
521  Eigen::Isometry3d reqr(sampling_pose_.orientation_constraint_->getDesiredRotationMatrix() * diff.linear());
522  quat = Eigen::Quaterniond(reqr.linear()); // reqr is isometry, so quat has to be normalized
523 
524  // if this constraint is with respect a mobile frame, we need to convert this rotation to the root frame of the
525  // model
526  if (sampling_pose_.orientation_constraint_->mobileReferenceFrame())
527  {
528  // getFrameTransform() returns a valid isometry by contract
529  const Eigen::Isometry3d& t = ks.getFrameTransform(sampling_pose_.orientation_constraint_->getReferenceFrame());
530  // rt is isometry by construction
531  Eigen::Isometry3d rt(t.linear() * quat);
532  quat = Eigen::Quaterniond(rt.linear()); // rt is isometry, so quat has to be normalized
533  }
534  }
535  else
536  {
537  // sample a random orientation
538  double q[4];
539  random_number_generator_.quaternion(q);
540  quat = Eigen::Quaterniond(q[3], q[0], q[1], q[2]); // quat is normalized by contract
541  }
542 
543  // if there is an offset, we need to undo the induced rotation in the sampled transform origin (point)
545  {
546  // the rotation matrix that corresponds to the desired orientation
547  pos = pos - quat * sampling_pose_.position_constraint_->getLinkOffset();
548  }
549 
550  return true;
551 }
552 
553 namespace
554 {
555 void samplingIkCallbackFnAdapter(moveit::core::RobotState* state, const moveit::core::JointModelGroup* jmg,
557  const std::vector<double>& ik_sol, moveit_msgs::msg::MoveItErrorCodes& error_code)
558 {
559  const std::vector<size_t>& bij = jmg->getKinematicsSolverJointBijection();
560  std::vector<double> solution(bij.size());
561  for (std::size_t i = 0; i < bij.size(); ++i)
562  solution[i] = ik_sol[bij[i]];
563  if (constraint(state, jmg, &solution[0]))
564  {
565  error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;
566  }
567  else
568  {
569  error_code.val = moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION;
570  }
571 }
572 } // namespace
573 
575  unsigned int max_attempts)
576 {
577  return sampleHelper(state, reference_state, max_attempts);
578 }
579 
581  unsigned int max_attempts)
582 {
583  if (!is_valid_)
584  {
585  RCLCPP_WARN(LOGGER, "IKConstraintSampler not configured, won't sample");
586  return false;
587  }
588 
589  kinematics::KinematicsBase::IKCallbackFn adapted_ik_validity_callback;
591  {
592  adapted_ik_validity_callback = [this, state_ptr = &state](const geometry_msgs::msg::Pose&,
593  const std::vector<double>& joints,
594  moveit_msgs::msg::MoveItErrorCodes& error_code) {
595  return samplingIkCallbackFnAdapter(state_ptr, jmg_, group_state_validity_callback_, joints, error_code);
596  };
597  }
598 
599  for (unsigned int a = 0; a < max_attempts; ++a)
600  {
601  // sample a point in the constraint region
602  Eigen::Vector3d point;
603  Eigen::Quaterniond quat; // quat is normalized by contract
604  if (!samplePose(point, quat, reference_state, max_attempts))
605  {
606  if (verbose_)
607  RCLCPP_INFO(LOGGER, "IK constraint sampler was unable to produce a pose to run IK for");
608  return false;
609  }
610 
611  // we now have the transform we wish to perform IK for, in the planning frame
612  if (transform_ik_)
613  {
614  // we need to convert this transform to the frame expected by the IK solver
615  // both the planning frame and the frame for the IK are assumed to be robot links
616  Eigen::Isometry3d ikq(Eigen::Translation3d(point) * quat); // valid isometry by construction
617  // getFrameTransform() returns a valid isometry by contract
618  ikq = reference_state.getFrameTransform(ik_frame_).inverse() * ikq; // valid isometry * valid isometry
619  point = ikq.translation();
620  quat = Eigen::Quaterniond(ikq.linear()); // ikq is isometry, so quat is normalized
621  }
622 
624  {
625  // After sampling the pose needs to be transformed to the ik chain tip
626  Eigen::Isometry3d ikq(Eigen::Translation3d(point) * quat); // valid isometry by construction
627  ikq = ikq * eef_to_ik_tip_transform_; // eef_to_ik_tip_transform_ is valid isometry (checked in loadIKSolver())
628  point = ikq.translation();
629  quat = Eigen::Quaterniond(ikq.linear()); // ikq is isometry, so quat is normalized
630  }
631 
632  geometry_msgs::msg::Pose ik_query;
633  ik_query.position.x = point.x();
634  ik_query.position.y = point.y();
635  ik_query.position.z = point.z();
636  ik_query.orientation.x = quat.x();
637  ik_query.orientation.y = quat.y();
638  ik_query.orientation.z = quat.z();
639  ik_query.orientation.w = quat.w();
640 
641  if (callIK(ik_query, adapted_ik_validity_callback, ik_timeout_, state, a == 0))
642  return true;
643  }
644  return false;
645 }
646 
648 {
649  state.update();
651  sampling_pose_.orientation_constraint_->decide(state, verbose_).satisfied) &&
653  sampling_pose_.position_constraint_->decide(state, verbose_).satisfied);
654 }
655 
656 bool IKConstraintSampler::callIK(const geometry_msgs::msg::Pose& ik_query,
657  const kinematics::KinematicsBase::IKCallbackFn& adapted_ik_validity_callback,
658  double timeout, moveit::core::RobotState& state, bool use_as_seed)
659 {
660  const std::vector<size_t>& ik_joint_bijection = jmg_->getKinematicsSolverJointBijection();
661  std::vector<double> seed(ik_joint_bijection.size(), 0.0);
662  std::vector<double> vals;
663 
664  if (use_as_seed)
665  {
666  state.copyJointGroupPositions(jmg_, vals);
667  }
668  else
669  {
670  // sample a seed value
672  }
673 
674  assert(vals.size() == ik_joint_bijection.size());
675  for (std::size_t i = 0; i < ik_joint_bijection.size(); ++i)
676  seed[i] = vals[ik_joint_bijection[i]];
677 
678  std::vector<double> ik_sol;
679  moveit_msgs::msg::MoveItErrorCodes error;
680 
681  if (adapted_ik_validity_callback ?
682  kb_->searchPositionIK(ik_query, seed, timeout, ik_sol, adapted_ik_validity_callback, error) :
683  kb_->searchPositionIK(ik_query, seed, timeout, ik_sol, error))
684  {
685  assert(ik_sol.size() == ik_joint_bijection.size());
686  std::vector<double> solution(ik_joint_bijection.size());
687  for (std::size_t i = 0; i < ik_joint_bijection.size(); ++i)
688  solution[ik_joint_bijection[i]] = ik_sol[i];
689  state.setJointGroupPositions(jmg_, solution);
690 
691  return validate(state);
692  }
693  else
694  {
695  if (error.val != moveit_msgs::msg::MoveItErrorCodes::NO_IK_SOLUTION &&
696  error.val != moveit_msgs::msg::MoveItErrorCodes::INVALID_ROBOT_STATE &&
697  error.val != moveit_msgs::msg::MoveItErrorCodes::TIMED_OUT)
698  {
699  RCLCPP_ERROR(LOGGER, "IK solver failed with error %d", error.val);
700  }
701  else if (verbose_)
702  {
703  RCLCPP_INFO(LOGGER, "IK failed");
704  }
705  }
706  return false;
707 }
708 
709 } // end of namespace constraint_samplers
bool is_valid_
Holds the value for validity.
std::vector< std::string > frame_depends_
Holds the set of frames that must exist in the reference state to allow samples to be drawn.
const moveit::core::JointModelGroup *const jmg_
Holds the joint model group associated with this constraint.
virtual void clear()
Clears all data from the constraint.
moveit::core::GroupStateValidityCallbackFn group_state_validity_callback_
Holds the callback for state validity.
bool verbose_
True if verbosity is on.
planning_scene::PlanningSceneConstPtr scene_
Holds the planning scene.
bool configure(const moveit_msgs::msg::Constraints &constr) override
Configures the IK constraint given a constraints message.
double ik_timeout_
Holds the timeout associated with IK.
bool loadIKSolver()
Performs checks and sets various internal values associated with the IK solver.
const std::string & getLinkName() const
Gets the link name associated with this sampler.
bool validate(moveit::core::RobotState &state) const
IKSamplingPose sampling_pose_
Holder for the pose used for sampling.
bool callIK(const geometry_msgs::msg::Pose &ik_query, const kinematics::KinematicsBase::IKCallbackFn &adapted_ik_validity_callback, double timeout, moveit::core::RobotState &state, bool use_as_seed)
Actually calls IK on the given pose, generating a random seed state.
double getSamplingVolume() const
Gets the volume associated with the position and orientation constraints.
Eigen::Isometry3d eef_to_ik_tip_transform_
Holds the transformation from end effector to IK tip frame.
bool need_eef_to_ik_tip_transform_
True if the tip frame of the inverse kinematic is different than the frame of the end effector.
kinematics::KinematicsBaseConstPtr kb_
Holds the kinematics solver.
void clear() override
Clears all data from the constraint.
bool sampleHelper(moveit::core::RobotState &state, const moveit::core::RobotState &reference_state, unsigned int max_attempts)
std::string ik_frame_
Holds the base from of the IK solver.
random_numbers::RandomNumberGenerator random_number_generator_
Random generator used by the sampler.
bool transform_ik_
True if the frame associated with the kinematic model is different than the base frame of the IK solv...
bool sample(moveit::core::RobotState &state, const moveit::core::RobotState &reference_state, unsigned int max_attempts) override
Produces an IK sample.
bool samplePose(Eigen::Vector3d &pos, Eigen::Quaterniond &quat, const moveit::core::RobotState &ks, unsigned int max_attempts)
Returns a pose that falls within the constraint regions.
std::vector< unsigned int > uindex_
The index of the unbounded joints in the joint state vector.
void clear() override
Clears all data from the constraint.
random_numbers::RandomNumberGenerator random_number_generator_
Random number generator used to sample.
std::vector< const moveit::core::JointModel * > unbounded_
The joints that are not bounded except by joint limits.
bool configure(const moveit_msgs::msg::Constraints &constr) override
Configures a joint constraint given a Constraints message.
std::vector< JointInfo > bounds_
The bounds for any joint with bounds that are more restrictive than the joint limits.
bool sample(moveit::core::RobotState &state, const moveit::core::RobotState &ks, unsigned int max_attempts) override
Samples given the constraints, populating state. This function allows the parameter max_attempts to b...
std::vector< double > values_
Values associated with this group to avoid continuously reallocating.
Class for handling single DOF joint constraints.
bool configure(const moveit_msgs::msg::JointConstraint &jc)
Configure the constraint based on a moveit_msgs::msg::JointConstraint.
Class for constraints on the orientation of a link.
Class for constraints on the XYZ position of a link.
std::function< void(const geometry_msgs::msg::Pose &, const std::vector< double > &, moveit_msgs::msg::MoveItErrorCodes &)> IKCallbackFn
Signature for a callback to validate an IK solution. Typically used for collision checking.
double getDefaultIKTimeout() const
Get the default IK timeout.
void getVariableRandomPositions(random_numbers::RandomNumberGenerator &rng, double *values) const
Compute random values for the state of the joint group.
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
const kinematics::KinematicsBaseConstPtr getSolverInstance() const
bool hasJointModel(const std::string &joint) const
Check if a joint is part of this group.
const RobotModel & getParentModel() const
Get the kinematic model this group is part of.
const std::vector< size_t > & getKinematicsSolverJointBijection() const
Return the mapping between the order of the joints in this group and the order of the joints in the k...
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
int getVariableGroupIndex(const std::string &variable) const
Get the index of a variable within the group. Return -1 on error.
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
Definition: joint_model.h:117
const std::string & getName() const
Get the name of the joint.
Definition: joint_model.h:145
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a variable. Throw an exception if the variable was not found.
A link from the robot. Contains the constant transform applied to the link and its geometry.
Definition: link_model.h:72
const LinkTransformMap & getAssociatedFixedTransforms() const
Get the set of links that are attached to this one via fixed transforms. The returned transforms are ...
Definition: link_model.h:199
const std::string & getName() const
The name of this link.
Definition: link_model.h:86
const std::string & getModelFrame() const
Get the frame in which the transforms for this model are computed (when using a RobotState)....
Definition: robot_model.h:94
bool hasLinkModel(const std::string &name) const
Check if a link exists. Return true if it does.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
Definition: robot_state.h:90
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
Definition: robot_state.h:1271
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
Given positions for the variables that make up a group, in the order found in the group (including va...
Definition: robot_state.h:605
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
Definition: robot_state.h:691
const Eigen::Isometry3d & getFrameTransform(const std::string &frame_id, bool *frame_found=nullptr)
Get the transformation matrix from the model frame (root of model) to the frame identified by frame_i...
void setToRandomPositions()
Set all joints to random values. Values will be within default bounds.
bool dirtyLinkTransforms() const
Definition: robot_state.h:1366
void update(bool force=false)
Update all transforms.
static bool sameFrame(const std::string &frame1, const std::string &frame2)
Check if two frames end up being the same once the missing / are added as prefix (if they are missing...
Definition: transforms.cpp:64
The constraint samplers namespace contains a number of methods for generating samples based on a cons...
Vec3fX< details::Vec3Data< double > > Vector3d
Definition: fcl_compat.h:89
Representation and evaluation of kinematic constraints.
std::function< bool(RobotState *robot_state, const JointModelGroup *joint_group, const double *joint_group_variable_values)> GroupStateValidityCallbackFn
Signature for functions that can verify that if the group joint_group in robot_state is set to joint_...
Definition: robot_state.h:70
std::map< const LinkModel *, Eigen::Isometry3d, std::less< const LinkModel * >, Eigen::aligned_allocator< std::pair< const LinkModel *const, Eigen::Isometry3d > > > LinkTransformMap
Map from link model instances to Eigen transforms.
Definition: link_model.h:68
A structure for potentially holding a position constraint and an orientation constraint for use durin...
kinematic_constraints::PositionConstraintPtr position_constraint_
Holds the position constraint for sampling.
kinematic_constraints::OrientationConstraintPtr orientation_constraint_
Holds the orientation constraint for sampling.
An internal structure used for maintaining constraints on a particular joint.
void potentiallyAdjustMinMaxBounds(double min, double max)
Function that adjusts the joints only if they are more restrictive. This means that the min limit is ...