kinematic_constraint.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Ioan Sucan */
00036 
00037 #include <moveit/kinematic_constraints/kinematic_constraint.h>
00038 #include <geometric_shapes/body_operations.h>
00039 #include <geometric_shapes/shape_operations.h>
00040 #include <moveit/robot_state/conversions.h>
00041 #include <moveit/collision_detection_fcl/collision_robot_fcl.h>
00042 #include <moveit/collision_detection_fcl/collision_world_fcl.h>
00043 #include <boost/scoped_ptr.hpp>
00044 #include <boost/math/constants/constants.hpp>
00045 #include <eigen_conversions/eigen_msg.h>
00046 #include <boost/bind.hpp>
00047 #include <limits>
00048 
00049 namespace kinematic_constraints
00050 {
00051 static double normalizeAngle(double angle)
00052 {
00053   double v = fmod(angle, 2.0 * boost::math::constants::pi<double>());
00054   if (v < -boost::math::constants::pi<double>())
00055     v += 2.0 * boost::math::constants::pi<double>();
00056   else
00057     if (v > boost::math::constants::pi<double>())
00058       v -= 2.0 * boost::math::constants::pi<double>();
00059   return v;
00060 }
00061 }
00062 
00063 kinematic_constraints::KinematicConstraint::KinematicConstraint(const robot_model::RobotModelConstPtr &model) :
00064   type_(UNKNOWN_CONSTRAINT), robot_model_(model), constraint_weight_(std::numeric_limits<double>::epsilon())
00065 {
00066 }
00067 
00068 kinematic_constraints::KinematicConstraint::~KinematicConstraint()
00069 {
00070 }
00071 
00072 bool kinematic_constraints::JointConstraint::configure(const moveit_msgs::JointConstraint &jc)
00073 {
00074   //clearing before we configure to get rid of any old data
00075   clear();
00076 
00077   //testing tolerances first
00078   if (jc.tolerance_above < 0.0 || jc.tolerance_below < 0.0)
00079   {
00080     logWarn("JointConstraint tolerance values must be positive.");
00081     joint_model_ = NULL;
00082     return false;
00083   }
00084 
00085   joint_variable_name_ = jc.joint_name;
00086   local_variable_name_.clear();
00087   if (robot_model_->hasJointModel(joint_variable_name_))
00088     joint_model_ = robot_model_->getJointModel(joint_variable_name_);
00089   else
00090   {
00091     std::size_t pos = jc.joint_name.find_last_of("/");
00092     if (pos != std::string::npos)
00093     {
00094       joint_model_ = robot_model_->getJointModel(jc.joint_name.substr(0, pos));
00095       if (pos + 1 < jc.joint_name.length())
00096         local_variable_name_ = jc.joint_name.substr(pos + 1);
00097     }
00098     else
00099       joint_model_ = robot_model_->getJointModel(jc.joint_name);
00100   }
00101 
00102   if (joint_model_)
00103   {
00104     if (local_variable_name_.empty())
00105     {
00106       // check if the joint has 1 DOF (the only kind we can handle)
00107       if (joint_model_->getVariableCount() == 0)
00108       {
00109         logError("Joint '%s' has no parameters to constrain", jc.joint_name.c_str());
00110         joint_model_ = NULL;
00111       }
00112       else
00113         if (joint_model_->getVariableCount() > 1)
00114         {
00115           logError("Joint '%s' has more than one parameter to constrain. This type of constraint is not supported.", jc.joint_name.c_str());
00116           joint_model_ = NULL;
00117         }
00118     }
00119     else
00120     {
00121       int found = -1;
00122       const std::vector<std::string> &local_var_names = joint_model_->getLocalVariableNames();
00123       for (std::size_t i = 0 ; i < local_var_names.size() ; ++i)
00124         if (local_var_names[i] == local_variable_name_)
00125         {
00126           found = i;
00127           break;
00128         }
00129       if (found < 0)
00130       {
00131         logError("Local variable name '%s' is not known to joint '%s'", local_variable_name_.c_str(), joint_model_->getName().c_str());
00132         joint_model_ = NULL;
00133       }
00134     }
00135   }
00136 
00137 
00138   if (joint_model_)
00139   {
00140     joint_is_continuous_ = false;
00141     joint_tolerance_above_ = jc.tolerance_above;
00142     joint_tolerance_below_ = jc.tolerance_below;
00143 
00144     // check if we have to wrap angles when computing distances
00145     joint_is_continuous_ = false;
00146     if (joint_model_->getType() == robot_model::JointModel::REVOLUTE)
00147     {
00148       const robot_model::RevoluteJointModel *rjoint = static_cast<const robot_model::RevoluteJointModel*>(joint_model_);
00149       if (rjoint->isContinuous())
00150         joint_is_continuous_ = true;
00151     }
00152     else
00153       if (joint_model_->getType() == robot_model::JointModel::PLANAR)
00154       {
00155         if (local_variable_name_ == "theta")
00156           joint_is_continuous_ = true;
00157       }
00158 
00159     if (joint_is_continuous_)
00160     {
00161       joint_position_ = normalizeAngle(jc.position);
00162     }
00163     else
00164     {
00165       joint_position_ = jc.position;
00166 
00167       std::pair<double, double> bounds;
00168       joint_model_->getVariableBounds(joint_variable_name_, bounds);
00169 
00170       if (bounds.first > joint_position_ + joint_tolerance_above_)
00171       {
00172         joint_position_ = bounds.first;
00173         joint_tolerance_above_ = std::numeric_limits<double>::epsilon();
00174         logWarn("Joint %s is constrained to be below the minimum bounds. Assuming minimum bounds instead.", jc.joint_name.c_str());
00175       }
00176       else
00177         if (bounds.second < joint_position_ - joint_tolerance_below_)
00178         {
00179           joint_position_ = bounds.second;
00180           joint_tolerance_below_ = std::numeric_limits<double>::epsilon();
00181           logWarn("Joint %s is constrained to be above the maximum bounds. Assuming maximum bounds instead.", jc.joint_name.c_str());
00182         }
00183     }
00184 
00185     if (jc.weight <= std::numeric_limits<double>::epsilon())
00186     {
00187       logWarn("The weight on constraint for joint '%s' is very near zero.  Setting to 1.0.", jc.joint_name.c_str());
00188       constraint_weight_ = 1.0;
00189     }
00190     else
00191       constraint_weight_ = jc.weight;
00192   }
00193   return joint_model_ != NULL;
00194 }
00195 
00196 bool kinematic_constraints::JointConstraint::equal(const KinematicConstraint &other, double margin) const
00197 {
00198   if (other.getType() != type_)
00199     return false;
00200   const JointConstraint &o = static_cast<const JointConstraint&>(other);
00201   if (o.joint_model_ == joint_model_ && o.local_variable_name_ == local_variable_name_)
00202     return fabs(joint_position_ - o.joint_position_) <= margin &&
00203       fabs(joint_tolerance_above_ - o.joint_tolerance_above_) <= margin &&
00204       fabs(joint_tolerance_below_ - o.joint_tolerance_below_) <= margin;
00205   return false;
00206 }
00207 
00208 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::JointConstraint::decide(const robot_state::RobotState &state, bool verbose) const
00209 {
00210   if (!joint_model_)
00211     return ConstraintEvaluationResult(true, 0.0);
00212 
00213   const robot_state::JointState *joint = state.getJointState(joint_model_->getName());
00214 
00215   if (!joint)
00216   {
00217     logWarn("No joint in state with name '%s'", joint_model_->getName().c_str());
00218     return ConstraintEvaluationResult(true, 0.0);
00219   }
00220 
00221   double current_joint_position = joint->getVariableValues()[0];
00222   if (!local_variable_name_.empty())
00223   {
00224     const std::map<std::string, unsigned int> &index_map = joint->getVariableIndexMap();
00225     std::map<std::string, unsigned int>::const_iterator it = index_map.find(joint_variable_name_);
00226     if (it == index_map.end())
00227     {
00228       logWarn("Local name '%s' is not known to joint state with name '%s'", local_variable_name_.c_str(), joint_model_->getName().c_str());
00229       return ConstraintEvaluationResult(true, 0.0);
00230     }
00231     else
00232       current_joint_position = joint->getVariableValues()[it->second];
00233   }
00234 
00235   double dif = 0.0;
00236 
00237   // compute signed shortest distance for continuous joints
00238   if (joint_is_continuous_)
00239   {
00240     dif = normalizeAngle(current_joint_position) - joint_position_;
00241 
00242     if (dif > boost::math::constants::pi<double>())
00243       dif = 2.0*boost::math::constants::pi<double>() - dif;
00244     else
00245       if (dif < -boost::math::constants::pi<double>())
00246         dif += 2.0*boost::math::constants::pi<double>(); // we include a sign change to have dif > 0
00247   }
00248   else
00249     dif = current_joint_position - joint_position_;
00250 
00251   // check bounds
00252   bool result = dif <= (joint_tolerance_above_+2*std::numeric_limits<double>::epsilon()) && dif >= (-joint_tolerance_below_-2*std::numeric_limits<double>::epsilon());
00253   if (verbose)
00254     logInform("Constraint %s:: Joint name: '%s', actual value: %f, desired value: %f, tolerance_above: %f, tolerance_below: %f",
00255               result ? "satisfied" : "violated", joint_variable_name_.c_str(),
00256               current_joint_position, joint_position_, joint_tolerance_above_, joint_tolerance_below_);
00257   return ConstraintEvaluationResult(result, constraint_weight_ * fabs(dif));
00258 }
00259 
00260 bool kinematic_constraints::JointConstraint::enabled() const
00261 {
00262   return joint_model_;
00263 }
00264 
00265 void kinematic_constraints::JointConstraint::clear()
00266 {
00267   joint_model_ = NULL;
00268   joint_is_continuous_ = false;
00269   local_variable_name_ = "";
00270   joint_variable_name_ = "";
00271   joint_position_ = joint_tolerance_below_ = joint_tolerance_above_ = 0.0;
00272 }
00273 
00274 void kinematic_constraints::JointConstraint::print(std::ostream &out) const
00275 {
00276   if (joint_model_)
00277   {
00278     out << "Joint constraint for joint " << joint_variable_name_ << ": " << std::endl;
00279     out << "  value = ";
00280     out << joint_position_ << "; ";
00281     out << "  tolerance below = ";
00282     out << joint_tolerance_below_ << "; ";
00283     out << "  tolerance above = ";
00284     out << joint_tolerance_above_ << "; ";
00285     out << std::endl;
00286   }
00287   else
00288     out << "No constraint" << std::endl;
00289 }
00290 
00291 bool kinematic_constraints::PositionConstraint::configure(const moveit_msgs::PositionConstraint &pc, const robot_state::Transforms &tf)
00292 {
00293   //clearing before we configure to get rid of any old data
00294   clear();
00295 
00296   link_model_ = robot_model_->getLinkModel(pc.link_name);
00297   if (link_model_ == NULL)
00298   {
00299     logWarn("Position constraint link model %s not found in kinematic model.  Constraint invalid.", pc.link_name.c_str());
00300     return false;
00301   }
00302 
00303   if (pc.header.frame_id.empty())
00304   {
00305     logWarn("No frame specified for position constraint on link '%s'!", pc.link_name.c_str());
00306     return false;
00307   }
00308 
00309   offset_ = Eigen::Vector3d(pc.target_point_offset.x, pc.target_point_offset.y, pc.target_point_offset.z);
00310   has_offset_ = offset_.squaredNorm() > std::numeric_limits<double>::epsilon();
00311 
00312   if (tf.isFixedFrame(pc.header.frame_id))
00313   {
00314     constraint_frame_id_ = tf.getTargetFrame();
00315     mobile_frame_ = false;
00316   }
00317   else
00318   {
00319     constraint_frame_id_ = pc.header.frame_id;
00320     mobile_frame_ = true;
00321   }
00322 
00323   // load primitive shapes, first clearing any we already have
00324   for (std::size_t i = 0 ; i < pc.constraint_region.primitives.size() ; ++i)
00325   {
00326     boost::scoped_ptr<shapes::Shape> shape(shapes::constructShapeFromMsg(pc.constraint_region.primitives[i]));
00327     if (shape)
00328     {
00329       if (pc.constraint_region.primitive_poses.size() <= i)
00330       {
00331         logWarn("Constraint region message does not contain enough primitive poses");
00332         continue;
00333       }
00334       constraint_region_.push_back(bodies::BodyPtr(bodies::createBodyFromShape(shape.get())));
00335       Eigen::Affine3d t;
00336       tf::poseMsgToEigen(pc.constraint_region.primitive_poses[i], t);
00337       constraint_region_pose_.push_back(t);
00338       if (mobile_frame_)
00339         constraint_region_.back()->setPose(constraint_region_pose_.back());
00340       else
00341       {
00342         tf.transformPose(pc.header.frame_id, constraint_region_pose_.back(), constraint_region_pose_.back());
00343         constraint_region_.back()->setPose(constraint_region_pose_.back());
00344       }
00345     }
00346     else
00347       logWarn("Could not construct primitive shape %d", i);
00348   }
00349 
00350   // load meshes
00351   for (std::size_t i = 0 ; i < pc.constraint_region.meshes.size() ; ++i)
00352   {
00353     boost::scoped_ptr<shapes::Shape> shape(shapes::constructShapeFromMsg(pc.constraint_region.meshes[i]));
00354     if (shape)
00355     {
00356       if (pc.constraint_region.mesh_poses.size() <= i)
00357       {
00358         logWarn("Constraint region message does not contain enough primitive poses");
00359         continue;
00360       }
00361       constraint_region_.push_back(bodies::BodyPtr(bodies::createBodyFromShape(shape.get())));
00362       Eigen::Affine3d t;
00363       tf::poseMsgToEigen(pc.constraint_region.mesh_poses[i], t);
00364       constraint_region_pose_.push_back(t);
00365       if (mobile_frame_)
00366         constraint_region_.back()->setPose(constraint_region_pose_.back());
00367       else
00368       {
00369         tf.transformPose(pc.header.frame_id, constraint_region_pose_.back(), constraint_region_pose_.back());
00370         constraint_region_.back()->setPose(constraint_region_pose_.back());
00371       }
00372     }
00373     else
00374     {
00375       logWarn("Could not construct mesh shape %d",i);
00376     }
00377   }
00378 
00379     if (pc.weight <= std::numeric_limits<double>::epsilon())
00380     {
00381       logWarn("The weight on position constraint for link '%s' is near zero.  Setting to 1.0.", pc.link_name.c_str());
00382       constraint_weight_ = 1.0;
00383     }
00384     else
00385       constraint_weight_ = pc.weight;
00386 
00387   return !constraint_region_.empty();
00388 }
00389 
00390 bool kinematic_constraints::PositionConstraint::equal(const KinematicConstraint &other, double margin) const
00391 {
00392   if (other.getType() != type_)
00393     return false;
00394   const PositionConstraint &o = static_cast<const PositionConstraint&>(other);
00395 
00396   if (link_model_ == o.link_model_ && robot_state::Transforms::sameFrame(constraint_frame_id_, o.constraint_frame_id_))
00397   {
00398     if ((offset_ - o.offset_).norm() > margin)
00399       return false;
00400     std::vector<bool> other_region_matches_this(constraint_region_.size(), false);
00401     for (std::size_t i = 0 ; i < constraint_region_.size() ; ++i)
00402     {
00403       bool some_match = false;
00404       //need to check against all other regions
00405       for(std::size_t j = 0 ; j < o.constraint_region_.size() ; ++j)
00406       {
00407         Eigen::Affine3d diff = constraint_region_pose_[i].inverse() * o.constraint_region_pose_[j];
00408         if (diff.translation().norm() < margin
00409             && diff.rotation().isIdentity(margin)
00410             && constraint_region_[i]->getType() == o.constraint_region_[j]->getType()
00411             && fabs(constraint_region_[i]->computeVolume() - o.constraint_region_[j]->computeVolume()) < margin)
00412         {
00413           some_match = true;
00414           //can't break, as need to do matches the other way as well
00415           other_region_matches_this[j] = true;
00416         }
00417       }
00418       if (!some_match)
00419         return false;
00420     }
00421     for (std::size_t i = 0 ; i < o.constraint_region_.size() ; ++i)
00422       if (!other_region_matches_this[i])
00423         return false;
00424     return true;
00425   }
00426   return false;
00427 }
00428 
00429 namespace kinematic_constraints
00430 {
00431 // helper function to avoid code duplication
00432 static inline
00433 kinematic_constraints::ConstraintEvaluationResult finishPositionConstraintDecision(const Eigen::Vector3d &pt, const Eigen::Vector3d &desired, const std::string &name,
00434                                                                                    double weight, bool result, bool verbose)
00435 {
00436   double dx = desired.x() - pt.x();
00437   double dy = desired.y() - pt.y();
00438   double dz = desired.z() - pt.z();
00439   if (verbose)
00440   {
00441     logInform("Position constraint %s on link '%s'. Desired: %f, %f, %f, current: %f, %f, %f",
00442              result ? "satisfied" : "violated", name.c_str(), desired.x(), desired.y(), desired.z(), pt.x(), pt.y(), pt.z());
00443     logInform("Differences %g %g %g",dx,dy, dz);
00444   }
00445   return ConstraintEvaluationResult(result, weight * sqrt(dx * dx + dy * dy + dz * dz));
00446 }
00447 }
00448 
00449 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::PositionConstraint::decide(const robot_state::RobotState &state, bool verbose) const
00450 {
00451   if (!link_model_ || constraint_region_.empty())
00452     return ConstraintEvaluationResult(true, 0.0);
00453 
00454   const robot_state::LinkState *link_state = state.getLinkState(link_model_->getName());
00455 
00456   if (!link_state)
00457   {
00458     logWarn("No link in state with name '%s'", link_model_->getName().c_str());
00459     return ConstraintEvaluationResult(false, 0.0);
00460   }
00461 
00462   Eigen::Vector3d pt = link_state->getGlobalLinkTransform() * offset_;
00463   if (mobile_frame_)
00464   {
00465     for (std::size_t i = 0 ; i < constraint_region_.size() ; ++i)
00466     {
00467       Eigen::Affine3d tmp = state.getFrameTransform(constraint_frame_id_) * constraint_region_pose_[i];
00468       bool result = constraint_region_[i]->cloneAt(tmp)->containsPoint(pt, verbose);
00469       if (result || (i + 1 == constraint_region_pose_.size()))
00470         return finishPositionConstraintDecision(pt, tmp.translation(), link_model_->getName(), constraint_weight_, result, verbose);
00471       else
00472         finishPositionConstraintDecision(pt, tmp.translation(), link_model_->getName(), constraint_weight_, result, verbose);
00473     }
00474   }
00475   else
00476   {
00477     for (std::size_t i = 0 ; i < constraint_region_.size() ; ++i)
00478     {
00479       bool result = constraint_region_[i]->containsPoint(pt, true);
00480       if (result || (i + 1 == constraint_region_.size()))
00481         return finishPositionConstraintDecision(pt, constraint_region_[i]->getPose().translation(), link_model_->getName(), constraint_weight_, result, verbose);
00482       else
00483         finishPositionConstraintDecision(pt, constraint_region_[i]->getPose().translation(), link_model_->getName(), constraint_weight_, result, verbose);
00484     }
00485   }
00486   return ConstraintEvaluationResult(false, 0.0);
00487 }
00488 
00489 void kinematic_constraints::PositionConstraint::print(std::ostream &out) const
00490 {
00491   if (enabled())
00492     out << "Position constraint on link '" << link_model_->getName() << "'" << std::endl;
00493   else
00494     out << "No constraint" << std::endl;
00495 }
00496 
00497 void kinematic_constraints::PositionConstraint::clear()
00498 {
00499   offset_ = Eigen::Vector3d(0.0,0.0,0.0);
00500   has_offset_ = false;
00501   constraint_region_.clear();
00502   constraint_region_pose_.clear();
00503   mobile_frame_ = false;
00504   constraint_frame_id_ = "";
00505   link_model_ = NULL;
00506 }
00507 
00508 bool kinematic_constraints::PositionConstraint::enabled() const
00509 {
00510   return link_model_ && !constraint_region_.empty();
00511 }
00512 
00513 bool kinematic_constraints::OrientationConstraint::configure(const moveit_msgs::OrientationConstraint &oc, const robot_state::Transforms &tf)
00514 {
00515   //clearing out any old data
00516   clear();
00517 
00518   link_model_ = robot_model_->getLinkModel(oc.link_name);
00519   if(!link_model_)
00520   {
00521     logWarn("Could not find link model for link name %s", oc.link_name.c_str());
00522     return false;
00523   }
00524   Eigen::Quaterniond q;
00525   tf::quaternionMsgToEigen(oc.orientation, q);
00526   if (fabs(q.norm() - 1.0) > 1e-3)
00527   {
00528     logWarn("Orientation constraint for link '%s' is probably incorrect: %f, %f, %f, %f. Assuming identity instead.", oc.link_name.c_str(),
00529             oc.orientation.x, oc.orientation.y, oc.orientation.z, oc.orientation.w);
00530     q = Eigen::Quaterniond(1.0, 0.0, 0.0, 0.0);
00531   }
00532 
00533   if (oc.header.frame_id.empty())
00534     logWarn("No frame specified for position constraint on link '%s'!", oc.link_name.c_str());
00535 
00536   if (tf.isFixedFrame(oc.header.frame_id))
00537   {
00538     tf.transformQuaternion(oc.header.frame_id, q, q);
00539     desired_rotation_frame_id_ = tf.getTargetFrame();
00540     desired_rotation_matrix_ = Eigen::Matrix3d(q);
00541     desired_rotation_matrix_inv_ = desired_rotation_matrix_.inverse();
00542     mobile_frame_ = false;
00543   }
00544   else
00545   {
00546     desired_rotation_frame_id_ = oc.header.frame_id;
00547     desired_rotation_matrix_ = Eigen::Matrix3d(q);
00548     mobile_frame_ = true;
00549   }
00550   std::stringstream matrix_str;
00551   matrix_str << desired_rotation_matrix_;
00552   logDebug("The desired rotation matrix for link '%s' in frame %s is:\n%s", oc.link_name.c_str(), desired_rotation_frame_id_.c_str(), matrix_str.str().c_str());
00553 
00554   if (oc.weight <= std::numeric_limits<double>::epsilon())
00555   {
00556     logWarn("The weight on position constraint for link '%s' is near zero.  Setting to 1.0.", oc.link_name.c_str());
00557     constraint_weight_ = 1.0;
00558   }
00559   else
00560     constraint_weight_ = oc.weight;
00561   absolute_x_axis_tolerance_ = fabs(oc.absolute_x_axis_tolerance);
00562   if (absolute_x_axis_tolerance_ < std::numeric_limits<double>::epsilon())
00563     logWarn("Near-zero value for absolute_x_axis_tolerance");
00564   absolute_y_axis_tolerance_ = fabs(oc.absolute_y_axis_tolerance);
00565   if (absolute_y_axis_tolerance_ < std::numeric_limits<double>::epsilon())
00566     logWarn("Near-zero value for absolute_y_axis_tolerance");
00567   absolute_z_axis_tolerance_ = fabs(oc.absolute_z_axis_tolerance);
00568   if (absolute_z_axis_tolerance_ < std::numeric_limits<double>::epsilon())
00569     logWarn("Near-zero value for absolute_z_axis_tolerance");
00570 
00571   return link_model_ != NULL;
00572 }
00573 
00574 bool kinematic_constraints::OrientationConstraint::equal(const KinematicConstraint &other, double margin) const
00575 {
00576   if (other.getType() != type_)
00577     return false;
00578   const OrientationConstraint &o = static_cast<const OrientationConstraint&>(other);
00579 
00580   if (o.link_model_ == link_model_ && robot_state::Transforms::sameFrame(desired_rotation_frame_id_, o.desired_rotation_frame_id_))
00581   {
00582     Eigen::Matrix3d diff = desired_rotation_matrix_.inverse() * o.desired_rotation_matrix_;
00583     if (!diff.isIdentity(margin))
00584       return false;
00585     return fabs(absolute_x_axis_tolerance_ - o.absolute_x_axis_tolerance_) <= margin &&
00586       fabs(absolute_y_axis_tolerance_ - o.absolute_y_axis_tolerance_) <= margin &&
00587       fabs(absolute_z_axis_tolerance_ - o.absolute_z_axis_tolerance_) <= margin;
00588   }
00589   return false;
00590 }
00591 
00592 void kinematic_constraints::OrientationConstraint::clear()
00593 {
00594   link_model_ = NULL;
00595   desired_rotation_matrix_ = Eigen::Matrix3d::Identity();
00596   desired_rotation_matrix_inv_ = Eigen::Matrix3d::Identity();
00597   desired_rotation_frame_id_ = "";
00598   mobile_frame_ = false;
00599   absolute_z_axis_tolerance_ = absolute_y_axis_tolerance_ = absolute_x_axis_tolerance_ = 0.0;
00600 }
00601 
00602 bool kinematic_constraints::OrientationConstraint::enabled() const
00603 {
00604   return link_model_;
00605 }
00606 
00607 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::OrientationConstraint::decide(const robot_state::RobotState &state, bool verbose) const
00608 {
00609   if (!link_model_)
00610     return ConstraintEvaluationResult(true, 0.0);
00611 
00612   const robot_state::LinkState *link_state = state.getLinkState(link_model_->getName());
00613 
00614   if (!link_state)
00615   {
00616     logWarn("No link in state with name '%s'", link_model_->getName().c_str());
00617     return ConstraintEvaluationResult(false, 0.0);
00618   }
00619 
00620   Eigen::Vector3d xyz;
00621   if (mobile_frame_)
00622   {
00623     Eigen::Matrix3d tmp = state.getFrameTransform(desired_rotation_frame_id_).rotation() * desired_rotation_matrix_;
00624     Eigen::Affine3d diff(tmp.inverse() * link_state->getGlobalLinkTransform().rotation());
00625     xyz = diff.rotation().eulerAngles(0, 1, 2);
00626     // 0,1,2 corresponds to XYZ, the convention used in sampling constraints
00627   }
00628   else
00629   {
00630     Eigen::Affine3d diff(desired_rotation_matrix_inv_ * link_state->getGlobalLinkTransform().rotation());
00631     xyz = diff.rotation().eulerAngles(0, 1, 2); // 0,1,2 corresponds to XYZ, the convention used in sampling constraints
00632   }
00633 
00634   xyz(0) = std::min(fabs(xyz(0)), boost::math::constants::pi<double>() - fabs(xyz(0)));
00635   xyz(1) = std::min(fabs(xyz(1)), boost::math::constants::pi<double>() - fabs(xyz(1)));
00636   xyz(2) = std::min(fabs(xyz(2)), boost::math::constants::pi<double>() - fabs(xyz(2)));
00637   bool result = xyz(2) < absolute_z_axis_tolerance_+std::numeric_limits<double>::epsilon()
00638     && xyz(1) < absolute_y_axis_tolerance_+std::numeric_limits<double>::epsilon()
00639     && xyz(0) < absolute_x_axis_tolerance_+std::numeric_limits<double>::epsilon();
00640 
00641   if (verbose)
00642   {
00643     Eigen::Quaterniond q_act(link_state->getGlobalLinkTransform().rotation());
00644     Eigen::Quaterniond q_des(desired_rotation_matrix_);
00645     logInform("Orientation constraint %s for link '%s'. Quaternion desired: %f %f %f %f, quaternion actual: %f %f %f %f, error: x=%f, y=%f, z=%f, tolerance: x=%f, y=%f, z=%f",
00646              result ? "satisfied" : "violated", link_model_->getName().c_str(),
00647              q_des.x(), q_des.y(), q_des.z(), q_des.w(),
00648              q_act.x(), q_act.y(), q_act.z(), q_act.w(), xyz(0), xyz(1), xyz(2),
00649              absolute_x_axis_tolerance_, absolute_y_axis_tolerance_, absolute_z_axis_tolerance_);
00650   }
00651 
00652   return ConstraintEvaluationResult(result, constraint_weight_ * (xyz(0) + xyz(1) + xyz(2)));
00653 }
00654 
00655 void kinematic_constraints::OrientationConstraint::print(std::ostream &out) const
00656 {
00657   if (link_model_)
00658   {
00659     out << "Orientation constraint on link '" << link_model_->getName() << "'" << std::endl;
00660     Eigen::Quaterniond q_des(desired_rotation_matrix_);
00661     out << "Desired orientation:" << q_des.x() << "," <<  q_des.y() << ","  <<  q_des.z() << "," << q_des.w() << std::endl;
00662   }
00663   else
00664     out << "No constraint" << std::endl;
00665 }
00666 
00667 kinematic_constraints::VisibilityConstraint::VisibilityConstraint(const robot_model::RobotModelConstPtr &model) :
00668   KinematicConstraint(model), collision_robot_(new collision_detection::CollisionRobotFCL(model))
00669 {
00670   type_ = VISIBILITY_CONSTRAINT;
00671 }
00672 
00673 void kinematic_constraints::VisibilityConstraint::clear()
00674 {
00675   mobile_sensor_frame_ = false;
00676   mobile_target_frame_ = false;
00677   target_frame_id_ = "";
00678   sensor_frame_id_ = "";
00679   sensor_pose_ = Eigen::Affine3d::Identity();
00680   sensor_view_direction_ = 0;
00681   target_pose_ = Eigen::Affine3d::Identity();
00682   cone_sides_ = 0;
00683   points_.clear();
00684   target_radius_ = -1.0;
00685   max_view_angle_ = 0.0;
00686   max_range_angle_ = 0.0;
00687 }
00688 
00689 bool kinematic_constraints::VisibilityConstraint::configure(const moveit_msgs::VisibilityConstraint &vc, const robot_state::Transforms &tf)
00690 {
00691   clear();
00692   target_radius_ = fabs(vc.target_radius);
00693 
00694   if (vc.target_radius <= std::numeric_limits<double>::epsilon())
00695     logWarn("The radius of the target disc that must be visible should be strictly positive");
00696 
00697   if (vc.cone_sides < 3)
00698   {
00699     logWarn("The number of sides for the visibility region must be 3 or more. Assuming 3 sides instead of the specified %d", vc.cone_sides);
00700     cone_sides_ = 3;
00701   }
00702   else
00703     cone_sides_ = vc.cone_sides;
00704 
00705   // compute the points on the base circle of the cone that make up the cone sides
00706   points_.clear();
00707   double delta = 2.0 * boost::math::constants::pi<double>() / (double)cone_sides_;
00708   double a = 0.0;
00709   for (unsigned int i = 0 ; i < cone_sides_ ; ++i, a += delta)
00710   {
00711     double x = sin(a) * target_radius_;
00712     double y = cos(a) * target_radius_;
00713     points_.push_back(Eigen::Vector3d(x, y, 0.0));
00714   }
00715 
00716   tf::poseMsgToEigen(vc.target_pose.pose, target_pose_);
00717 
00718   if (tf.isFixedFrame(vc.target_pose.header.frame_id))
00719   {
00720     tf.transformPose(vc.target_pose.header.frame_id, target_pose_, target_pose_);
00721     target_frame_id_ = tf.getTargetFrame();
00722     mobile_target_frame_ = false;
00723     // transform won't change, so apply it now
00724     for (std::size_t i = 0 ; i < points_.size() ; ++i)
00725       points_[i] = target_pose_*points_[i];
00726   }
00727   else
00728   {
00729     target_frame_id_ = vc.target_pose.header.frame_id;
00730     mobile_target_frame_ = true;
00731   }
00732 
00733   tf::poseMsgToEigen(vc.sensor_pose.pose, sensor_pose_);
00734 
00735   if (tf.isFixedFrame(vc.sensor_pose.header.frame_id))
00736   {
00737     tf.transformPose(vc.sensor_pose.header.frame_id, sensor_pose_, sensor_pose_);
00738     sensor_frame_id_ = tf.getTargetFrame();
00739     mobile_sensor_frame_ = false;
00740   }
00741   else
00742   {
00743     sensor_frame_id_ = vc.sensor_pose.header.frame_id;
00744     mobile_sensor_frame_ = true;
00745   }
00746 
00747   if (vc.weight <= std::numeric_limits<double>::epsilon())
00748   {
00749     logWarn("The weight of visibility constraint is near zero.  Setting to 1.0.");
00750     constraint_weight_ = 1.0;
00751   }
00752   else
00753     constraint_weight_ = vc.weight;
00754 
00755   max_view_angle_ = vc.max_view_angle;
00756   max_range_angle_ = vc.max_range_angle;
00757   sensor_view_direction_ = vc.sensor_view_direction;
00758 
00759   return target_radius_ > std::numeric_limits<double>::epsilon();
00760 }
00761 
00762 bool kinematic_constraints::VisibilityConstraint::equal(const KinematicConstraint &other, double margin) const
00763 {
00764   if (other.getType() != type_)
00765     return false;
00766   const VisibilityConstraint &o = static_cast<const VisibilityConstraint&>(other);
00767 
00768   if (robot_state::Transforms::sameFrame(target_frame_id_, o.target_frame_id_) &&
00769       robot_state::Transforms::sameFrame(sensor_frame_id_, o.sensor_frame_id_) &&
00770       cone_sides_ == o.cone_sides_ && sensor_view_direction_ == o.sensor_view_direction_)
00771   {
00772     if (fabs(max_view_angle_ - o.max_view_angle_) > margin ||
00773         fabs(target_radius_ - o.target_radius_) > margin)
00774       return false;
00775     Eigen::Affine3d diff = sensor_pose_.inverse() * o.sensor_pose_;
00776     if (diff.translation().norm() > margin)
00777       return false;
00778     if (!diff.rotation().isIdentity(margin))
00779       return false;
00780     diff = target_pose_.inverse() * o.target_pose_;
00781     if (diff.translation().norm() > margin)
00782       return false;
00783     if (!diff.rotation().isIdentity(margin))
00784       return false;
00785     return true;
00786   }
00787   return false;
00788 }
00789 
00790 bool kinematic_constraints::VisibilityConstraint::enabled() const
00791 {
00792   return target_radius_ > std::numeric_limits<double>::epsilon();
00793 }
00794 
00795 shapes::Mesh* kinematic_constraints::VisibilityConstraint::getVisibilityCone(const robot_state::RobotState &state) const
00796 {
00797   // the current pose of the sensor
00798 
00799   const Eigen::Affine3d &sp = mobile_sensor_frame_ ? state.getFrameTransform(sensor_frame_id_) * sensor_pose_ : sensor_pose_;
00800   const Eigen::Affine3d &tp = mobile_target_frame_ ? state.getFrameTransform(target_frame_id_) * target_pose_ : target_pose_;
00801 
00802   // transform the points on the disc to the desired target frame
00803   const EigenSTL::vector_Vector3d *points = &points_;
00804   boost::scoped_ptr<EigenSTL::vector_Vector3d> tempPoints;
00805   if (mobile_target_frame_)
00806   {
00807     tempPoints.reset(new EigenSTL::vector_Vector3d(points_.size()));
00808     for (std::size_t i = 0 ; i < points_.size() ; ++i)
00809       tempPoints->at(i) = tp*points_[i];
00810     points = tempPoints.get();
00811   }
00812 
00813   // allocate memory for a mesh to represent the visibility cone
00814   shapes::Mesh *m = new shapes::Mesh();
00815   m->vertex_count = cone_sides_ + 2;
00816   m->vertices = new double[m->vertex_count * 3];
00817   m->triangle_count = cone_sides_ * 2;
00818   m->triangles = new unsigned int[m->triangle_count * 3];
00819   // we do NOT allocate normals because we do not compute them
00820 
00821   // the sensor origin
00822   m->vertices[0] = sp.translation().x();
00823   m->vertices[1] = sp.translation().y();
00824   m->vertices[2] = sp.translation().z();
00825 
00826   // the center of the base of the cone approximation
00827   m->vertices[3] = tp.translation().x();
00828   m->vertices[4] = tp.translation().y();
00829   m->vertices[5] = tp.translation().z();
00830 
00831   // the points that approximate the base disc
00832   for (std::size_t i = 0 ; i < points->size() ; ++i)
00833   {
00834     m->vertices[i*3 + 6] = points->at(i).x();
00835     m->vertices[i*3 + 7] = points->at(i).y();
00836     m->vertices[i*3 + 8] = points->at(i).z();
00837   }
00838 
00839   // add the triangles
00840   std::size_t p3 = points->size() * 3;
00841   for (std::size_t i = 1 ; i < points->size() ; ++i)
00842   {
00843     // triangle forming a side of the cone, using the sensor origin
00844     std::size_t i3 = (i - 1) * 3;
00845     m->triangles[i3] = i + 1;
00846     m->triangles[i3 + 1] = 0;
00847     m->triangles[i3 + 2] = i + 2;
00848     // triangle forming a part of the base of the cone, using the center of the base
00849     std::size_t i6 = p3 + i3;
00850     m->triangles[i6] = i + 1;
00851     m->triangles[i6 + 1] = 1;
00852     m->triangles[i6 + 2] = i + 2;
00853   }
00854 
00855   // last triangles
00856   m->triangles[p3 - 3] = points->size() + 1;
00857   m->triangles[p3 - 2] = 0;
00858   m->triangles[p3 - 1] = 2;
00859   p3 *= 2;
00860   m->triangles[p3 - 3] = points->size() + 1;
00861   m->triangles[p3 - 2] = 1;
00862   m->triangles[p3 - 1] = 2;
00863 
00864   return m;
00865 }
00866 
00867 void kinematic_constraints::VisibilityConstraint::getMarkers(const robot_state::RobotState &state, visualization_msgs::MarkerArray &markers) const
00868 {
00869   shapes::Mesh *m = getVisibilityCone(state);
00870   visualization_msgs::Marker mk;
00871   shapes::constructMarkerFromShape(m, mk);
00872   delete m;
00873   mk.header.frame_id = robot_model_->getModelFrame();
00874   mk.header.stamp = ros::Time::now();
00875   mk.ns = "constraints";
00876   mk.id = 1;
00877   mk.action = visualization_msgs::Marker::ADD;
00878   mk.pose.position.x = 0;
00879   mk.pose.position.y = 0;
00880   mk.pose.position.z = 0;
00881   mk.pose.orientation.x = 0;
00882   mk.pose.orientation.y = 0;
00883   mk.pose.orientation.z = 0;
00884   mk.pose.orientation.w = 1;
00885   mk.lifetime = ros::Duration(60);
00886   // this scale necessary to make results look reasonable
00887   mk.scale.x = .01;
00888   mk.color.a = 1.0;
00889   mk.color.r = 1.0;
00890   mk.color.g = 0.0;
00891   mk.color.b = 0.0;
00892 
00893   markers.markers.push_back(mk);
00894 
00895   const Eigen::Affine3d &sp = mobile_sensor_frame_ ? state.getFrameTransform(sensor_frame_id_) * sensor_pose_ : sensor_pose_;
00896   const Eigen::Affine3d &tp = mobile_target_frame_ ? state.getFrameTransform(target_frame_id_) * target_pose_ : target_pose_;
00897 
00898   visualization_msgs::Marker mka;
00899   mka.type = visualization_msgs::Marker::ARROW;
00900   mka.action = visualization_msgs::Marker::ADD;
00901   mka.color = mk.color;
00902   mka.pose = mk.pose;
00903 
00904   mka.header = mk.header;
00905   mka.ns = mk.ns;
00906   mka.id = 2;
00907   mka.lifetime = mk.lifetime;
00908   mka.scale.x = 0.05;
00909   mka.scale.y = .15;
00910   mka.scale.z = 0.0;
00911   mka.points.resize(2);
00912   Eigen::Vector3d d = tp.translation() + tp.rotation().col(2) * 0.5;
00913   mka.points[0].x = tp.translation().x();
00914   mka.points[0].y = tp.translation().y();
00915   mka.points[0].z = tp.translation().z();
00916   mka.points[1].x = d.x();
00917   mka.points[1].y = d.y();
00918   mka.points[1].z = d.z();
00919   markers.markers.push_back(mka);
00920 
00921   mka.id = 3;
00922   mka.color.b = 1.0;
00923   mka.color.r = 0.0;
00924 
00925   d = sp.translation() + sp.rotation().col(2-sensor_view_direction_) * 0.5;
00926   mka.points[0].x = sp.translation().x();
00927   mka.points[0].y = sp.translation().y();
00928   mka.points[0].z = sp.translation().z();
00929   mka.points[1].x = d.x();
00930   mka.points[1].y = d.y();
00931   mka.points[1].z = d.z();
00932 
00933   markers.markers.push_back(mka);
00934 }
00935 
00936 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::VisibilityConstraint::decide(const robot_state::RobotState &state, bool verbose) const
00937 {
00938   if (target_radius_ <= std::numeric_limits<double>::epsilon())
00939     return ConstraintEvaluationResult(true, 0.0);
00940 
00941   if (max_view_angle_ > 0.0 || max_range_angle_ > 0.0)
00942   {
00943     const Eigen::Affine3d &sp = mobile_sensor_frame_ ? state.getFrameTransform(sensor_frame_id_) * sensor_pose_ : sensor_pose_;
00944     const Eigen::Affine3d &tp = mobile_target_frame_ ? state.getFrameTransform(target_frame_id_) * target_pose_ : target_pose_;
00945 
00946     //necessary to do subtraction as SENSOR_Z is 0 and SENSOR_X is 2
00947     const Eigen::Vector3d &normal2 = sp.rotation().col(2-sensor_view_direction_);
00948 
00949     if (max_view_angle_ > 0.0)
00950     {
00951       const Eigen::Vector3d &normal1 = tp.rotation().col(2)*-1.0; // along Z axis and inverted
00952       double dp = normal2.dot(normal1);
00953       double ang = acos(dp);
00954       if (dp < 0.0)
00955       {
00956         if (verbose)
00957           logInform("Visibility constraint is violated because the sensor is looking at the wrong side");
00958         return ConstraintEvaluationResult(false, 0.0);
00959       }
00960       if (max_view_angle_ < ang)
00961       {
00962         if (verbose)
00963           logInform("Visibility constraint is violated because the view angle is %lf (above the maximum allowed of %lf)", ang, max_view_angle_);
00964         return ConstraintEvaluationResult(false, 0.0);
00965       }
00966     }
00967     if (max_range_angle_ > 0.0)
00968     {
00969       const Eigen::Vector3d &dir = (tp.translation() - sp.translation()).normalized();
00970       double dp = normal2.dot(dir);
00971       if (dp < 0.0)
00972       {
00973         if (verbose)
00974           logInform("Visibility constraint is violated because the sensor is looking at the wrong side");
00975         return ConstraintEvaluationResult(false, 0.0);
00976       }
00977 
00978       double ang = acos(dp);
00979       if (max_range_angle_ < ang)
00980       {
00981         if (verbose)
00982           logInform("Visibility constraint is violated because the range angle is %lf (above the maximum allowed of %lf)", ang, max_range_angle_);
00983         return ConstraintEvaluationResult(false, 0.0);
00984       }
00985     }
00986   }
00987 
00988   shapes::Mesh *m = getVisibilityCone(state);
00989   if (!m)
00990     return ConstraintEvaluationResult(false, 0.0);
00991 
00992   // add the visibility cone as an object
00993   collision_detection::CollisionWorldFCL collision_world;
00994   collision_world.getWorld()->addToObject("cone", shapes::ShapeConstPtr(m), Eigen::Affine3d::Identity());
00995 
00996   // check for collisions between the robot and the cone
00997   collision_detection::CollisionRequest req;
00998   collision_detection::CollisionResult res;
00999   collision_detection::AllowedCollisionMatrix acm;
01000   acm.setDefaultEntry("cone", boost::bind(&VisibilityConstraint::decideContact, this, _1));
01001   req.contacts = true;
01002   req.verbose = verbose;
01003   req.max_contacts = 1;
01004   collision_world.checkRobotCollision(req, res, *collision_robot_, state, acm);
01005 
01006   if (verbose)
01007   {
01008     std::stringstream ss;
01009     m->print(ss);
01010     logInform("Visibility constraint %ssatisfied. Visibility cone approximation:\n %s", res.collision ? "not " : "", ss.str().c_str());
01011   }
01012 
01013   return ConstraintEvaluationResult(!res.collision, res.collision ? res.contacts.begin()->second.front().depth : 0.0);
01014 }
01015 
01016 bool kinematic_constraints::VisibilityConstraint::decideContact(const collision_detection::Contact &contact) const
01017 {
01018     if (contact.body_type_1 == collision_detection::BodyTypes::ROBOT_ATTACHED ||
01019         contact.body_type_2 == collision_detection::BodyTypes::ROBOT_ATTACHED)
01020         return true;
01021     if (contact.body_type_1 == collision_detection::BodyTypes::ROBOT_LINK &&
01022         contact.body_type_2 == collision_detection::BodyTypes::WORLD_OBJECT &&
01023         (robot_state::Transforms::sameFrame(contact.body_name_1, sensor_frame_id_) ||
01024          robot_state::Transforms::sameFrame(contact.body_name_1, target_frame_id_)))
01025     {
01026       logDebug("Accepted collision with either sensor or target");
01027       return true;
01028     }
01029     if (contact.body_type_2 == collision_detection::BodyTypes::ROBOT_LINK &&
01030         contact.body_type_1 == collision_detection::BodyTypes::WORLD_OBJECT &&
01031         (robot_state::Transforms::sameFrame(contact.body_name_2, sensor_frame_id_) ||
01032          robot_state::Transforms::sameFrame(contact.body_name_2, target_frame_id_)))
01033     {
01034       logDebug("Accepted collision with either sensor or target");
01035       return true;
01036     }
01037     return false;
01038 }
01039 
01040 void kinematic_constraints::VisibilityConstraint::print(std::ostream &out) const
01041 {
01042   if (enabled())
01043   {
01044     out << "Visibility constraint for sensor in frame '" << sensor_frame_id_ << "' using target in frame '" << target_frame_id_ << "'" << std::endl;
01045     out << "Target radius: " << target_radius_ << ", using " << cone_sides_ << " sides." << std::endl;
01046   }
01047   else
01048     out << "No constraint" << std::endl;
01049 }
01050 
01051 void kinematic_constraints::KinematicConstraintSet::clear()
01052 {
01053   all_constraints_ = moveit_msgs::Constraints();
01054   kinematic_constraints_.clear();
01055   joint_constraints_.clear();
01056   position_constraints_.clear();
01057   orientation_constraints_.clear();
01058   visibility_constraints_.clear();
01059 }
01060 
01061 bool kinematic_constraints::KinematicConstraintSet::add(const std::vector<moveit_msgs::JointConstraint> &jc)
01062 {
01063   bool result = true;
01064   for (unsigned int i = 0 ; i < jc.size() ; ++i)
01065   {
01066     JointConstraint *ev = new JointConstraint(robot_model_);
01067     bool u = ev->configure(jc[i]);
01068     result = result && u;
01069     kinematic_constraints_.push_back(KinematicConstraintPtr(ev));
01070     joint_constraints_.push_back(jc[i]);
01071     all_constraints_.joint_constraints.push_back(jc[i]);
01072   }
01073   return result;
01074 }
01075 
01076 bool kinematic_constraints::KinematicConstraintSet::add(const std::vector<moveit_msgs::PositionConstraint> &pc, const robot_state::Transforms &tf)
01077 {
01078   bool result = true;
01079   for (unsigned int i = 0 ; i < pc.size() ; ++i)
01080   {
01081     PositionConstraint *ev = new PositionConstraint(robot_model_);
01082     bool u = ev->configure(pc[i], tf);
01083     result = result && u;
01084     kinematic_constraints_.push_back(KinematicConstraintPtr(ev));
01085     position_constraints_.push_back(pc[i]);
01086     all_constraints_.position_constraints.push_back(pc[i]);
01087   }
01088   return result;
01089 }
01090 
01091 bool kinematic_constraints::KinematicConstraintSet::add(const std::vector<moveit_msgs::OrientationConstraint> &oc, const robot_state::Transforms &tf)
01092 {
01093   bool result = true;
01094   for (unsigned int i = 0 ; i < oc.size() ; ++i)
01095   {
01096     OrientationConstraint *ev = new OrientationConstraint(robot_model_);
01097     bool u = ev->configure(oc[i], tf);
01098     result = result && u;
01099     kinematic_constraints_.push_back(KinematicConstraintPtr(ev));
01100     orientation_constraints_.push_back(oc[i]);
01101     all_constraints_.orientation_constraints.push_back(oc[i]);
01102   }
01103   return result;
01104 }
01105 
01106 bool kinematic_constraints::KinematicConstraintSet::add(const std::vector<moveit_msgs::VisibilityConstraint> &vc, const robot_state::Transforms &tf)
01107 {
01108   bool result = true;
01109   for (unsigned int i = 0 ; i < vc.size() ; ++i)
01110   {
01111     VisibilityConstraint *ev = new VisibilityConstraint(robot_model_);
01112     bool u = ev->configure(vc[i], tf);
01113     result = result && u;
01114     kinematic_constraints_.push_back(KinematicConstraintPtr(ev));
01115     visibility_constraints_.push_back(vc[i]);
01116     all_constraints_.visibility_constraints.push_back(vc[i]);
01117   }
01118   return result;
01119 }
01120 
01121 bool kinematic_constraints::KinematicConstraintSet::add(const moveit_msgs::Constraints &c, const robot_state::Transforms &tf)
01122 {
01123   bool j = add(c.joint_constraints);
01124   bool p = add(c.position_constraints, tf);
01125   bool o = add(c.orientation_constraints, tf);
01126   bool v = add(c.visibility_constraints, tf);
01127   return j && p && o && v;
01128 }
01129 
01130 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::KinematicConstraintSet::decide(const robot_state::RobotState &state, bool verbose) const
01131 {
01132   ConstraintEvaluationResult res(true, 0.0);
01133   for (unsigned int i = 0 ; i < kinematic_constraints_.size() ; ++i)
01134   {
01135     ConstraintEvaluationResult r = kinematic_constraints_[i]->decide(state, verbose);
01136     if (!r.satisfied)
01137       res.satisfied = false;
01138     res.distance += r.distance;
01139   }
01140   return res;
01141 }
01142 
01143 kinematic_constraints::ConstraintEvaluationResult kinematic_constraints::KinematicConstraintSet::decide(const robot_state::RobotState &state,
01144                                                                                                         std::vector<ConstraintEvaluationResult> &results,
01145                                                                                                         bool verbose) const
01146 {
01147   ConstraintEvaluationResult result(true, 0.0);
01148   results.resize(joint_constraints_.size());
01149   for (std::size_t i = 0 ; i < joint_constraints_.size() ; ++i)
01150   {
01151     results[i] = kinematic_constraints_[i]->decide(state, verbose);
01152     result.satisfied = result.satisfied && results[i].satisfied;
01153     result.distance += results[i].distance;
01154   }
01155 
01156   return result;
01157 }
01158 
01159 void kinematic_constraints::KinematicConstraintSet::print(std::ostream &out) const
01160 {
01161   out << kinematic_constraints_.size() << " kinematic constraints" << std::endl;
01162   for (unsigned int i = 0 ; i < kinematic_constraints_.size() ; ++i)
01163     kinematic_constraints_[i]->print(out);
01164 }
01165 
01166 bool kinematic_constraints::KinematicConstraintSet::equal(const KinematicConstraintSet &other, double margin) const
01167 {
01168   //each constraint in this matches some in the other
01169   for (unsigned int i = 0 ; i < kinematic_constraints_.size() ; ++i)
01170   {
01171     bool found = false;
01172     for (unsigned int j = 0 ; !found && j < other.kinematic_constraints_.size() ; ++j)
01173       found = kinematic_constraints_[i]->equal(*other.kinematic_constraints_[j], margin);
01174     if (!found)
01175       return false;
01176   }
01177   //each constraint in the other matches some constraint in this
01178   for (unsigned int i = 0 ; i < other.kinematic_constraints_.size() ; ++i)
01179   {
01180     bool found = false;
01181     for (unsigned int j = 0 ; !found && j < kinematic_constraints_.size() ; ++j)
01182       found = other.kinematic_constraints_[i]->equal(*kinematic_constraints_[j], margin);
01183     if (!found)
01184       return false;
01185   }
01186   return true;
01187 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Mon Oct 6 2014 02:24:47