moveit_state_adapter.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Apache License)
00003  *
00004  * Copyright (c) 2014, Dan Solomon
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  * http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include <console_bridge/console.h>
00020 
00021 #include "descartes_moveit/moveit_state_adapter.h"
00022 #include "descartes_core/pretty_print.hpp"
00023 #include "descartes_moveit/seed_search.h"
00024 
00025 #include <eigen_conversions/eigen_msg.h>
00026 #include <random_numbers/random_numbers.h>
00027 #include <ros/assert.h>
00028 #include <sstream>
00029 
00030 const static int SAMPLE_ITERATIONS = 10;
00031 
00032 namespace
00033 {
00034 bool getJointVelocityLimits(const moveit::core::RobotState& state, const std::string& group_name,
00035                             std::vector<double>& output)
00036 {
00037   std::vector<double> result;
00038 
00039   auto models = state.getJointModelGroup(group_name)->getActiveJointModels();
00040   for (const moveit::core::JointModel* model : models)
00041   {
00042     const auto& bounds = model->getVariableBounds();
00043     // Check to see if there is a single bounds constraint (more might indicate
00044     // not revolute joint)
00045     if (model->getType() != moveit::core::JointModel::REVOLUTE &&
00046         model->getType() != moveit::core::JointModel::PRISMATIC)
00047     {
00048       ROS_ERROR_STREAM(__FUNCTION__ << " Unexpected joint type. Currently works only"
00049                                        " with single axis prismatic or revolute joints.");
00050       return false;
00051     }
00052     else
00053     {
00054       result.push_back(bounds[0].max_velocity_);
00055     }
00056   }
00057 
00058   output = result;
00059   return true;
00060 }
00061 
00062 }  // end anon namespace
00063 
00064 namespace descartes_moveit
00065 {
00066 MoveitStateAdapter::MoveitStateAdapter() : world_to_root_(Eigen::Affine3d::Identity())
00067 {
00068 }
00069 
00070 bool MoveitStateAdapter::initialize(const std::string& robot_description, const std::string& group_name,
00071                                     const std::string& world_frame, const std::string& tcp_frame)
00072 {
00073   // Initialize MoveIt state objects
00074   robot_model_loader_.reset(new robot_model_loader::RobotModelLoader(robot_description));
00075 
00076   return initialize(robot_model_loader_->getModel(), group_name, world_frame, tcp_frame);
00077 }
00078 
00079 bool MoveitStateAdapter::initialize(robot_model::RobotModelConstPtr robot_model, const std::string &group_name,
00080                                     const std::string &world_frame, const std::string &tcp_frame)
00081 {
00082   robot_model_ptr_ = robot_model;
00083   robot_state_.reset(new moveit::core::RobotState(robot_model_ptr_));
00084   robot_state_->setToDefaultValues();
00085   planning_scene_.reset(new planning_scene::PlanningScene(robot_model));
00086   joint_group_ = robot_model_ptr_->getJointModelGroup(group_name);
00087 
00088   // Assign robot frames
00089   group_name_ = group_name;
00090   tool_frame_ = tcp_frame;
00091   world_frame_ = world_frame;
00092 
00093   // Validate our model inputs w/ URDF
00094   if (!joint_group_)
00095   {
00096     logError("%s: Joint group '%s' does not exist in robot model", __FUNCTION__, group_name_.c_str());
00097     std::stringstream msg;
00098     msg << "Possible group names: " << robot_state_->getRobotModel()->getJointModelGroupNames();
00099     logError(msg.str().c_str());
00100     return false;
00101   }
00102 
00103   const auto& link_names = joint_group_->getLinkModelNames();
00104   if (tool_frame_ != link_names.back())
00105   {
00106     logError("%s: Tool frame '%s' does not match group tool frame '%s', functionality"
00107              "will be implemented in the future",
00108              __FUNCTION__, tool_frame_.c_str(), link_names.back().c_str());
00109     return false;
00110   }
00111 
00112   if (!getJointVelocityLimits(*robot_state_, group_name, velocity_limits_))
00113   {
00114     logWarn("%s: Could not determine velocity limits of RobotModel from MoveIt", __FUNCTION__);
00115   }
00116 
00117   if (seed_states_.empty())
00118   {
00119     seed_states_ = seed::findRandomSeeds(*robot_state_, group_name_, SAMPLE_ITERATIONS);
00120     logDebug("Generated %lu random seeds", static_cast<unsigned long>(seed_states_.size()));
00121   }
00122 
00123   auto model_frame = robot_state_->getRobotModel()->getModelFrame();
00124   if (world_frame_ != model_frame)
00125   {
00126     logInform("%s: World frame '%s' does not match model root frame '%s', all poses will be"
00127               " transformed to world frame '%s'",
00128               __FUNCTION__, world_frame_.c_str(), model_frame.c_str(), world_frame_.c_str());
00129 
00130     Eigen::Affine3d root_to_world = robot_state_->getFrameTransform(world_frame_);
00131     world_to_root_ = descartes_core::Frame(root_to_world.inverse());
00132   }
00133 
00134   return true;
00135 }
00136 
00137 bool MoveitStateAdapter::getIK(const Eigen::Affine3d& pose, const std::vector<double>& seed_state,
00138                                std::vector<double>& joint_pose) const
00139 {
00140   robot_state_->setJointGroupPositions(group_name_, seed_state);
00141   return getIK(pose, joint_pose);
00142 }
00143 
00144 bool MoveitStateAdapter::getIK(const Eigen::Affine3d& pose, std::vector<double>& joint_pose) const
00145 {
00146   bool rtn = false;
00147 
00148   // transform to group base
00149   Eigen::Affine3d tool_pose = world_to_root_.frame * pose;
00150 
00151   if (robot_state_->setFromIK(joint_group_, tool_pose, tool_frame_))
00152   {
00153     robot_state_->copyJointGroupPositions(group_name_, joint_pose);
00154     if (!isValid(joint_pose))
00155     {
00156       ROS_DEBUG_STREAM("Robot joint pose is invalid");
00157     }
00158     else
00159     {
00160       rtn = true;
00161     }
00162   }
00163   else
00164   {
00165     rtn = false;
00166   }
00167 
00168   return rtn;
00169 }
00170 
00171 bool MoveitStateAdapter::getAllIK(const Eigen::Affine3d& pose, std::vector<std::vector<double> >& joint_poses) const
00172 {
00173   // The minimum difference between solutions should be greater than the search discretization
00174   // used by the IK solver.  This value is multiplied by 4 to remove any chance that a solution
00175   // in the middle of a discretization step could be double counted.  In reality, we'd like solutions
00176   // to be further apart than this.
00177   double epsilon = 4 * joint_group_->getSolverInstance()->getSearchDiscretization();
00178   logDebug("Utilizing an min. difference of %f between IK solutions", epsilon);
00179   joint_poses.clear();
00180   for (size_t sample_iter = 0; sample_iter < seed_states_.size(); ++sample_iter)
00181   {
00182     robot_state_->setJointGroupPositions(group_name_, seed_states_[sample_iter]);
00183     std::vector<double> joint_pose;
00184     if (getIK(pose, joint_pose))
00185     {
00186       if (joint_poses.empty())
00187       {
00188         std::stringstream msg;
00189         msg << "Found *first* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00190         logDebug(msg.str().c_str());
00191         joint_poses.push_back(joint_pose);
00192       }
00193       else
00194       {
00195         std::stringstream msg;
00196         msg << "Found *potential* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00197         logDebug(msg.str().c_str());
00198 
00199         std::vector<std::vector<double> >::iterator joint_pose_it;
00200         bool match_found = false;
00201         for (joint_pose_it = joint_poses.begin(); joint_pose_it != joint_poses.end(); ++joint_pose_it)
00202         {
00203           if (descartes_core::utils::equal(joint_pose, (*joint_pose_it), epsilon))
00204           {
00205             logDebug("Found matching, potential solution is not new");
00206             match_found = true;
00207             break;
00208           }
00209         }
00210         if (!match_found)
00211         {
00212           std::stringstream msg;
00213           msg << "Found *new* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00214           logDebug(msg.str().c_str());
00215           joint_poses.push_back(joint_pose);
00216         }
00217       }
00218     }
00219   }
00220 
00221   logDebug("Found %lu joint solutions out of %lu iterations", static_cast<unsigned long>(joint_poses.size()),
00222            static_cast<unsigned long>(seed_states_.size()));
00223 
00224   if (joint_poses.empty())
00225   {
00226     logError("Found 0 joint solutions out of %lu iterations", static_cast<unsigned long>(seed_states_.size()));
00227     return false;
00228   }
00229   else
00230   {
00231     logInform("Found %lu joint solutions out of %lu iterations", static_cast<unsigned long>(joint_poses.size()),
00232               static_cast<unsigned long>(seed_states_.size()));
00233     return true;
00234   }
00235 }
00236 
00237 bool MoveitStateAdapter::isInCollision(const std::vector<double>& joint_pose) const
00238 {
00239   bool in_collision = false;
00240   if (check_collisions_)
00241   {
00242     robot_state_->setJointGroupPositions(group_name_, joint_pose);
00243     in_collision = planning_scene_->isStateColliding(*robot_state_, group_name_);
00244   }
00245   return in_collision;
00246 }
00247 
00248 bool MoveitStateAdapter::getFK(const std::vector<double>& joint_pose, Eigen::Affine3d& pose) const
00249 {
00250   bool rtn = false;
00251   robot_state_->setJointGroupPositions(group_name_, joint_pose);
00252   if (isValid(joint_pose))
00253   {
00254     if (robot_state_->knowsFrameTransform(tool_frame_))
00255     {
00256       pose = world_to_root_.frame * robot_state_->getFrameTransform(tool_frame_);
00257       rtn = true;
00258     }
00259     else
00260     {
00261       logError("Robot state does not recognize tool frame: %s", tool_frame_.c_str());
00262       rtn = false;
00263     }
00264   }
00265   else
00266   {
00267     logError("Invalid joint pose passed to get forward kinematics");
00268     rtn = false;
00269   }
00270 
00271   return rtn;
00272 }
00273 
00274 bool MoveitStateAdapter::isValid(const std::vector<double>& joint_pose) const
00275 {
00276   // Logical check on input sizes
00277   if (joint_group_->getActiveJointModels().size() != joint_pose.size())
00278   {
00279     logError("Size of joint pose: %lu doesn't match robot state variable size: %lu",
00280              static_cast<unsigned long>(joint_pose.size()),
00281              static_cast<unsigned long>(joint_group_->getActiveJointModels().size()));
00282     return false;
00283   }
00284 
00285   // Satisfies joint positional bounds?
00286   if (!joint_group_->satisfiesPositionBounds(joint_pose.data()))
00287   {
00288     return false;
00289   }
00290   // Is in collision (if collision is active)
00291   return !isInCollision(joint_pose);
00292 }
00293 
00294 bool MoveitStateAdapter::isValid(const Eigen::Affine3d& pose) const
00295 {
00296   // TODO: Could check robot extents first as a quick check
00297   std::vector<double> dummy;
00298   return getIK(pose, dummy);
00299 }
00300 
00301 int MoveitStateAdapter::getDOF() const
00302 {
00303   return joint_group_->getVariableCount();
00304 }
00305 
00306 bool MoveitStateAdapter::isValidMove(const std::vector<double>& from_joint_pose,
00307                                      const std::vector<double>& to_joint_pose, double dt) const
00308 {
00309   // Check for equal sized arrays
00310   if (from_joint_pose.size() != to_joint_pose.size())
00311   {
00312     logError("To and From joint poses are of different sizes.");
00313     return false;
00314   }
00315 
00316   for (std::size_t i = 0; i < from_joint_pose.size(); ++i)
00317   {
00318     double dtheta = std::abs(from_joint_pose[i] - to_joint_pose[i]);
00319     double max_dtheta = dt * velocity_limits_[i];
00320     if (dtheta > max_dtheta)
00321       return false;
00322   }
00323 
00324   return true;
00325 }
00326 
00327 void MoveitStateAdapter::setState(const moveit::core::RobotState& state)
00328 {
00329   ROS_ASSERT_MSG(static_cast<bool>(robot_state_), "'robot_state_' member pointer is null. Have you called "
00330                                                   "initialize()?");
00331   *robot_state_ = state;
00332   planning_scene_->setCurrentState(state);
00333 }
00334 
00335 }  // descartes_moveit


descartes_moveit
Author(s): Shaun Edwards
autogenerated on Thu Jun 6 2019 21:36:08