39 #include <boost/bind.hpp> 46 std::vector<kinematic_constraints::JointConstraint> jc;
47 for (std::size_t i = 0; i < constr.joint_constraints.size(); ++i)
50 if (j.configure(constr.joint_constraints[i]))
54 return jc.empty() ? false :
configure(jc);
63 ROS_ERROR_NAMED(
"constraint_samplers",
"NULL group specified for constraint sampler");
69 std::map<std::string, JointInfo> bound_data;
70 bool some_valid_constraint =
false;
71 for (std::size_t i = 0; i < jc.size(); ++i)
80 some_valid_constraint =
true;
84 std::map<std::string, JointInfo>::iterator it = bound_data.find(jc[i].getJointVariableName());
85 if (it != bound_data.end())
90 std::max(joint_bounds.
min_position_, jc[i].getDesiredJointPosition() - jc[i].getJointToleranceBelow()),
91 std::min(joint_bounds.
max_position_, jc[i].getDesiredJointPosition() + jc[i].getJointToleranceAbove()));
93 ROS_DEBUG_NAMED(
"constraint_samplers",
"Bounds for %s JointConstraint are %g %g",
101 "The constraints for joint '%s' are such that " 102 "there are no possible values for the joint: min_bound: %g, max_bound: %g. Failing.\n",
107 bound_data[jc[i].getJointVariableName()] = ji;
110 if (!some_valid_constraint)
112 ROS_WARN_NAMED(
"constraint_samplers",
"No valid joint constraints");
116 for (std::map<std::string, JointInfo>::iterator it = bound_data.begin(); it != bound_data.end(); ++it)
121 for (std::size_t i = 0; i < joints.size(); ++i)
122 if (bound_data.find(joints[i]->getName()) == bound_data.end() && joints[i]->getVariableCount() > 0 &&
123 joints[i]->getMimic() ==
nullptr)
126 const std::vector<std::string>& vars = joints[i]->getVariableNames();
129 bool all_found =
true;
130 for (std::size_t j = 0; j < vars.size(); ++j)
131 if (bound_data.find(vars[j]) == bound_data.end())
154 ROS_WARN_NAMED(
"constraint_samplers",
"JointConstraintSampler not configured, won't sample");
159 std::vector<double> v;
160 for (std::size_t i = 0; i <
unbounded_.size(); ++i)
164 for (std::size_t j = 0; j < v.size(); ++j)
169 for (std::size_t i = 0; i <
bounds_.size(); ++i)
180 return sample(state, state, max_attempts);
222 const kinematic_constraints::OrientationConstraintPtr& oc)
232 transform_ik_ =
false;
233 eef_to_ik_tip_transform_ = Eigen::Isometry3d::Identity();
234 need_eef_to_ik_tip_transform_ =
false;
247 ROS_WARN_NAMED(
"constraint_samplers",
"No enabled constraints in sampling pose");
252 ik_timeout_ = jmg_->getDefaultIKTimeout();
253 if (sampling_pose_.position_constraint_ && sampling_pose_.orientation_constraint_)
254 if (sampling_pose_.position_constraint_->getLinkModel()->getName() !=
255 sampling_pose_.orientation_constraint_->getLinkModel()->getName())
258 "Position and orientation constraints need to be specified for the same link " 259 "in order to use IK-based sampling");
263 if (sampling_pose_.position_constraint_ && sampling_pose_.position_constraint_->mobileReferenceFrame())
264 frame_depends_.push_back(sampling_pose_.position_constraint_->getReferenceFrame());
265 if (sampling_pose_.orientation_constraint_ && sampling_pose_.orientation_constraint_->mobileReferenceFrame())
266 frame_depends_.push_back(sampling_pose_.orientation_constraint_->getReferenceFrame());
267 kb_ = jmg_->getSolverInstance();
270 ROS_WARN_NAMED(
"constraint_samplers",
"No solver instance in setup");
274 is_valid_ = loadIKSolver();
280 for (std::size_t p = 0; p < constr.position_constraints.size(); ++p)
281 for (std::size_t o = 0; o < constr.orientation_constraints.size(); ++o)
282 if (constr.position_constraints[p].link_name == constr.orientation_constraints[o].link_name)
284 kinematic_constraints::PositionConstraintPtr pc(
286 kinematic_constraints::OrientationConstraintPtr oc(
288 if (pc->configure(constr.position_constraints[p], scene_->getTransforms()) &&
289 oc->configure(constr.orientation_constraints[o], scene_->getTransforms()))
293 for (std::size_t p = 0; p < constr.position_constraints.size(); ++p)
295 kinematic_constraints::PositionConstraintPtr pc(
297 if (pc->configure(constr.position_constraints[p], scene_->getTransforms()))
301 for (std::size_t o = 0; o < constr.orientation_constraints.size(); ++o)
303 kinematic_constraints::OrientationConstraintPtr oc(
305 if (oc->configure(constr.orientation_constraints[o], scene_->getTransforms()))
314 if (sampling_pose_.position_constraint_)
316 const std::vector<bodies::BodyPtr>& b = sampling_pose_.position_constraint_->getConstraintRegions();
318 for (std::size_t i = 0; i < b.size(); ++i)
319 vol += b[i]->computeVolume();
324 if (sampling_pose_.orientation_constraint_)
325 v *= sampling_pose_.orientation_constraint_->getXAxisTolerance() *
326 sampling_pose_.orientation_constraint_->getYAxisTolerance() *
327 sampling_pose_.orientation_constraint_->getZAxisTolerance();
333 if (sampling_pose_.orientation_constraint_)
334 return sampling_pose_.orientation_constraint_->getLinkModel()->getName();
335 return sampling_pose_.position_constraint_->getLinkModel()->getName();
347 ik_frame_ = kb_->getBaseFrame();
349 if (!ik_frame_.empty() && ik_frame_[0] ==
'/')
350 ik_frame_.erase(ik_frame_.begin());
352 if (!jmg_->getParentModel().hasLinkModel(ik_frame_))
355 "The IK solver expects requests in frame '%s' but this frame is not known to the sampler. " 356 "Ignoring transformation (IK may fail)",
358 transform_ik_ =
false;
362 bool wrong_link =
false;
363 if (sampling_pose_.position_constraint_)
370 for (moveit::core::LinkTransformMap::const_iterator it = fixed_links.begin(); it != fixed_links.end(); ++it)
373 eef_to_ik_tip_transform_ = it->second;
374 need_eef_to_ik_tip_transform_ =
true;
381 if (!wrong_link && sampling_pose_.orientation_constraint_)
388 for (moveit::core::LinkTransformMap::const_iterator it = fixed_links.begin(); it != fixed_links.end(); ++it)
391 eef_to_ik_tip_transform_ = it->second;
392 need_eef_to_ik_tip_transform_ =
true;
402 "IK cannot be performed for link '%s'. The solver can report IK solutions for link '%s'.",
403 sampling_pose_.position_constraint_ ?
404 sampling_pose_.position_constraint_->getLinkModel()->getName().c_str() :
405 sampling_pose_.orientation_constraint_->getLinkModel()->getName().c_str(),
406 kb_->getTipFrame().c_str());
413 unsigned int max_attempts)
419 "IKConstraintSampler received dirty robot state, but valid transforms are required. " 424 if (sampling_pose_.position_constraint_)
426 const std::vector<bodies::BodyPtr>& b = sampling_pose_.position_constraint_->getConstraintRegions();
430 std::size_t k = random_number_generator_.uniformInteger(0, b.size() - 1);
431 for (std::size_t i = 0; i < b.size(); ++i)
432 if (b[(i + k) % b.size()]->samplePointInside(random_number_generator_, max_attempts, pos))
439 ROS_ERROR_NAMED(
"constraint_samplers",
"Unable to sample a point inside the constraint region");
445 ROS_ERROR_NAMED(
"constraint_samplers",
"Unable to sample a point inside the constraint region. " 446 "Constraint region is empty when it should not be.");
452 if (sampling_pose_.position_constraint_->mobileReferenceFrame())
453 pos = ks.
getFrameTransform(sampling_pose_.position_constraint_->getReferenceFrame()) * pos;
460 pos = temp_state.
getGlobalLinkTransform(sampling_pose_.orientation_constraint_->getLinkModel()).translation();
463 if (sampling_pose_.orientation_constraint_)
467 2.0 * (random_number_generator_.uniform01() - 0.5) *
468 (sampling_pose_.orientation_constraint_->getXAxisTolerance() - std::numeric_limits<double>::epsilon());
470 2.0 * (random_number_generator_.uniform01() - 0.5) *
471 (sampling_pose_.orientation_constraint_->getYAxisTolerance() - std::numeric_limits<double>::epsilon());
473 2.0 * (random_number_generator_.uniform01() - 0.5) *
474 (sampling_pose_.orientation_constraint_->getZAxisTolerance() - std::numeric_limits<double>::epsilon());
475 Eigen::Isometry3d
diff(Eigen::AngleAxisd(angle_x, Eigen::Vector3d::UnitX()) *
476 Eigen::AngleAxisd(angle_y, Eigen::Vector3d::UnitY()) *
477 Eigen::AngleAxisd(angle_z, Eigen::Vector3d::UnitZ()));
478 Eigen::Isometry3d reqr(sampling_pose_.orientation_constraint_->getDesiredRotationMatrix() * diff.rotation());
479 quat = Eigen::Quaterniond(reqr.rotation());
483 if (sampling_pose_.orientation_constraint_->mobileReferenceFrame())
485 const Eigen::Isometry3d&
t = ks.
getFrameTransform(sampling_pose_.orientation_constraint_->getReferenceFrame());
486 Eigen::Isometry3d rt(t.rotation() * quat);
487 quat = Eigen::Quaterniond(rt.rotation());
494 random_number_generator_.quaternion(q);
495 quat = Eigen::Quaterniond(q[3], q[0], q[1], q[2]);
499 if (sampling_pose_.position_constraint_ && sampling_pose_.position_constraint_->hasLinkOffset())
501 pos = pos - quat * sampling_pose_.position_constraint_->getLinkOffset();
510 const geometry_msgs::Pose& ,
const std::vector<double>& ik_sol,
511 moveit_msgs::MoveItErrorCodes& error_code)
514 std::vector<double> solution(bij.size());
515 for (std::size_t i = 0; i < bij.size(); ++i)
516 solution[i] = ik_sol[bij[i]];
517 if (constraint(state, jmg, &solution[0]))
518 error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
525 unsigned int max_attempts)
527 return sampleHelper(state, reference_state, max_attempts,
false);
531 unsigned int max_attempts,
bool project)
535 ROS_WARN_NAMED(
"constraint_samplers",
"IKConstraintSampler not configured, won't sample");
540 if (group_state_validity_callback_)
541 adapted_ik_validity_callback =
542 boost::bind(&samplingIkCallbackFnAdapter, &state, jmg_, group_state_validity_callback_, _1, _2, _3);
544 for (
unsigned int a = 0; a < max_attempts; ++a)
548 Eigen::Quaterniond quat;
549 if (!samplePose(point, quat, reference_state, max_attempts))
552 ROS_INFO_NAMED(
"constraint_samplers",
"IK constraint sampler was unable to produce a pose to run IK for");
561 Eigen::Isometry3d ikq(Eigen::Translation3d(point) * quat);
563 point = ikq.translation();
564 quat = Eigen::Quaterniond(ikq.rotation());
567 if (need_eef_to_ik_tip_transform_)
570 Eigen::Isometry3d ikq(Eigen::Translation3d(point) * quat);
571 ikq = ikq * eef_to_ik_tip_transform_;
572 point = ikq.translation();
573 quat = Eigen::Quaterniond(ikq.rotation());
576 geometry_msgs::Pose ik_query;
577 ik_query.position.x = point.x();
578 ik_query.position.y = point.y();
579 ik_query.position.z = point.z();
580 ik_query.orientation.x = quat.x();
581 ik_query.orientation.y = quat.y();
582 ik_query.orientation.z = quat.z();
583 ik_query.orientation.w = quat.w();
585 if (callIK(ik_query, adapted_ik_validity_callback, ik_timeout_, state, project && a == 0))
593 return sampleHelper(state, state, max_attempts,
true);
599 return (!sampling_pose_.orientation_constraint_ ||
600 sampling_pose_.orientation_constraint_->decide(state, verbose_).satisfied) &&
601 (!sampling_pose_.position_constraint_ ||
602 sampling_pose_.position_constraint_->decide(state, verbose_).satisfied);
609 const std::vector<unsigned int>& ik_joint_bijection = jmg_->getKinematicsSolverJointBijection();
610 std::vector<double> seed(ik_joint_bijection.size(), 0.0);
611 std::vector<double> vals;
617 jmg_->getVariableRandomPositions(random_number_generator_, vals);
619 assert(vals.size() == ik_joint_bijection.size());
620 for (std::size_t i = 0; i < ik_joint_bijection.size(); ++i)
621 seed[i] = vals[ik_joint_bijection[i]];
623 std::vector<double> ik_sol;
624 moveit_msgs::MoveItErrorCodes error;
626 if (adapted_ik_validity_callback ?
627 kb_->searchPositionIK(ik_query, seed, timeout, ik_sol, adapted_ik_validity_callback, error) :
628 kb_->searchPositionIK(ik_query, seed, timeout, ik_sol, error))
630 assert(ik_sol.size() == ik_joint_bijection.size());
631 std::vector<double> solution(ik_joint_bijection.size());
632 for (std::size_t i = 0; i < ik_joint_bijection.size(); ++i)
633 solution[ik_joint_bijection[i]] = ik_sol[i];
641 error.val != moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE &&
643 ROS_ERROR_NAMED(
"constraint_samplers",
"IK solver failed with error %d", error.val);
bool validate(robot_state::RobotState &state) const
bool configure(const moveit_msgs::Constraints &constr) override
Configures a joint constraint given a Constraints message.
std::vector< unsigned int > uindex_
The index of the unbounded joints in the joint state vector.
A structure for potentially holding a position constraint and an orientation constraint for use durin...
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.
#define ROS_INFO_NAMED(name,...)
Class for constraints on the orientation of a link.
bool callIK(const geometry_msgs::Pose &ik_query, const kinematics::KinematicsBase::IKCallbackFn &adapted_ik_validity_callback, double timeout, robot_state::RobotState &state, bool use_as_seed)
Actually calls IK on the given pose, generating a random seed state.
Vec3fX< details::Vec3Data< double > > Vector3d
#define ROS_WARN_NAMED(name,...)
const std::vector< unsigned int > & getKinematicsSolverJointBijection() const
Return the mapping between the order of the joints in this group and the order of the joints in the k...
bool hasJointModel(const std::string &joint) const
Check if a joint is part of this group.
void potentiallyAdjustMinMaxBounds(double min, double max)
Function that adjusts the joints only if they are more restrictive. This means that the min limit is ...
bool sample(robot_state::RobotState &state, const robot_state::RobotState &reference_state, unsigned int max_attempts) override
Produces an IK sample.
std::vector< double > values_
Values associated with this group to avoid continuously reallocating.
Class for handling single DOF joint constraints.
random_numbers::RandomNumberGenerator random_number_generator_
Random number generator used to sample.
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
ROSCPP_DECL bool validate(const std::string &name, std::string &error)
void clear() override
Clears all data from the constraint.
IKSamplingPose()
Empty constructor.
double getSamplingVolume() const
Gets the volume associated with the position and orientation constraints.
const LinkTransformMap & getAssociatedFixedTransforms() const
Get the set of links that are attached to this one via fixed transforms.
bool loadIKSolver()
Performs checks and sets various internal values associated with the IK solver.
kinematic_constraints::OrientationConstraintPtr orientation_constraint_
Holds the orientation constraint for sampling.
virtual void clear()
Clears all data from the constraint.
static const int NO_IK_SOLUTION
Representation and evaluation of kinematic constraints.
geometry_msgs::TransformStamped t
bool dirtyLinkTransforms() const
bool project(robot_state::RobotState &state, unsigned int max_attempts) override
Project a sample given the constraints, updating the joint state group. This function allows the para...
The constraint samplers namespace contains a number of methods for generating samples based on a cons...
#define ROS_DEBUG_NAMED(name,...)
bool sampleHelper(robot_state::RobotState &state, const robot_state::RobotState &reference_state, unsigned int max_attempts, bool project)
void update(bool force=false)
Update all transforms.
std::vector< JointInfo > bounds_
The bounds for any joint with bounds that are more restrictive than the joint limits.
const std::string & getLinkName() const
Gets the link name associated with this sampler.
double uniformReal(double lower_bound, double upper_bound)
const std::string & getName() const
The name of this link.
boost::function< void(const geometry_msgs::Pose &ik_pose, const std::vector< double > &ik_solution, moveit_msgs::MoveItErrorCodes &error_code)> IKCallbackFn
Signature for a callback to validate an IK solution. Typically used for collision checking...
A joint from the robot. Models the transform that this joint applies in the kinematic chain...
const Eigen::Isometry3d & getFrameTransform(const std::string &frame_id)
Get the transformation matrix from the model frame to the frame identified by frame_id.
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...
Class for constraints on the XYZ position of a link.
bool configure(const moveit_msgs::Constraints &constr) override
Configures the IK constraint given a constraints message.
const robot_model::JointModelGroup *const jmg_
Holds the joint model group associated with this constraint.
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a variable. Throw an exception if the variable was not found.
int getVariableGroupIndex(const std::string &variable) const
Get the index of a variable within the group. Return -1 on error.
void clear() override
Clears all data from the constraint.
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
bool project(robot_state::RobotState &state, unsigned int max_attempts) override
Project a sample given the constraints, updating the joint state group. This function allows the para...
An internal structure used for maintaining constraints on a particular joint.
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...
void setToRandomPositions()
Set all joints to random values. Values will be within default bounds.
static const int TIMED_OUT
bool is_valid_
Holds the value for validity.
std::vector< const robot_model::JointModel * > unbounded_
The joints that are not bounded except by joint limits.
#define ROS_ERROR_NAMED(name,...)
Representation of a robot's state. This includes position, velocity, acceleration and effort...
A link from the robot. Contains the constant transform applied to the link and its geometry...
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
kinematic_constraints::PositionConstraintPtr position_constraint_
Holds the position constraint for sampling.
bool sample(robot_state::RobotState &state, const robot_state::RobotState &ks, unsigned int max_attempts) override
Samples given the constraints, populating state. This function allows the parameter max_attempts to b...
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
boost::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_...
planning_scene::PlanningSceneConstPtr scene_
Holds the planning scene.
bool samplePose(Eigen::Vector3d &pos, Eigen::Quaterniond &quat, const robot_state::RobotState &ks, unsigned int max_attempts)
Returns a pose that falls within the constraint regions.
const std::string & getName() const
Get the name of the joint.