00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <console_bridge/console.h>
00020 #include "descartes_moveit/moveit_state_adapter.h"
00021 #include "eigen_conversions/eigen_msg.h"
00022 #include "random_numbers/random_numbers.h"
00023 #include "descartes_core/pretty_print.hpp"
00024 #include "descartes_moveit/seed_search.h"
00025 #include <sstream>
00026
00027 const static int SAMPLE_ITERATIONS = 10;
00028
00029 namespace
00030 {
00031
00032 bool getJointVelocityLimits(const moveit::core::RobotState& state,
00033 const std::string& group_name,
00034 std::vector<double>& output)
00035 {
00036 std::vector<double> result;
00037
00038 auto models = state.getJointModelGroup(group_name)->getActiveJointModels();
00039 for (const moveit::core::JointModel* model : models)
00040 {
00041 const auto& bounds = model->getVariableBounds();
00042
00043
00044 if (model->getType() != moveit::core::JointModel::REVOLUTE &&
00045 model->getType() != moveit::core::JointModel::PRISMATIC)
00046 {
00047 ROS_ERROR_STREAM(__FUNCTION__ << " Unexpected joint type. Currently works only with single axis prismatic or revolute joints.");
00048 return false;
00049 }
00050 else
00051 {
00052 result.push_back(bounds[0].max_velocity_);
00053 }
00054 }
00055
00056 output = result;
00057 return true;
00058 }
00059
00060 }
00061
00062 namespace descartes_moveit
00063 {
00064
00065 MoveitStateAdapter::MoveitStateAdapter()
00066 {}
00067
00068 MoveitStateAdapter::MoveitStateAdapter(const moveit::core::RobotState & robot_state, const std::string & group_name,
00069 const std::string & tool_frame, const std::string & world_frame) :
00070 robot_state_(new moveit::core::RobotState(robot_state)),
00071 group_name_(group_name),
00072 tool_frame_(tool_frame),
00073 world_frame_(world_frame),
00074 world_to_root_(Eigen::Affine3d::Identity())
00075 {
00076
00077 ROS_INFO_STREAM("Generated random seeds");
00078 seed_states_ = seed::findRandomSeeds(*robot_state_, group_name_, SAMPLE_ITERATIONS);
00079
00080 const moveit::core::JointModelGroup* joint_model_group_ptr = robot_state_->getJointModelGroup(group_name);
00081 if (joint_model_group_ptr)
00082 {
00083
00084 if (!getJointVelocityLimits(*robot_state_, group_name, velocity_limits_))
00085 {
00086 logWarn("Could not determine velocity limits of RobotModel from MoveIt");
00087 }
00088
00089 joint_model_group_ptr->printGroupInfo();
00090
00091 const std::vector<std::string>& link_names = joint_model_group_ptr->getLinkModelNames();
00092 if (tool_frame_ != link_names.back())
00093 {
00094 logWarn("Tool frame '%s' does not match group tool frame '%s', functionality will be implemented in the future",
00095 tool_frame_.c_str(), link_names.back().c_str());
00096 }
00097
00098 if (world_frame_ != robot_state_->getRobotModel()->getModelFrame())
00099 {
00100 logWarn("World frame '%s' does not match model root frame '%s', all poses will be transformed to world frame '%s'",
00101 world_frame_.c_str(), link_names.front().c_str(),world_frame_.c_str());
00102
00103 Eigen::Affine3d root_to_world = robot_state_->getFrameTransform(world_frame_);
00104 world_to_root_ = descartes_core::Frame(root_to_world.inverse());
00105 }
00106
00107 }
00108 else
00109 {
00110 logError("Joint group: %s does not exist in robot model", group_name_.c_str());
00111 std::stringstream msg;
00112 msg << "Possible group names: " << robot_state_->getRobotModel()->getJointModelGroupNames();
00113 logError(msg.str().c_str());
00114 }
00115 return;
00116 }
00117
00118 bool MoveitStateAdapter::initialize(const std::string& robot_description, const std::string& group_name,
00119 const std::string& world_frame,const std::string& tcp_frame)
00120 {
00121
00122 robot_model_loader_.reset(new robot_model_loader::RobotModelLoader(robot_description));
00123 robot_model_ptr_ = robot_model_loader_->getModel();
00124 robot_state_.reset(new moveit::core::RobotState(robot_model_ptr_));
00125 planning_scene_.reset(new planning_scene::PlanningScene(robot_model_loader_->getModel()));
00126 group_name_ = group_name;
00127 tool_frame_ = tcp_frame;
00128 world_frame_ = world_frame;
00129
00130 if (seed_states_.empty())
00131 {
00132 seed_states_ = seed::findRandomSeeds(*robot_state_, group_name_, SAMPLE_ITERATIONS);
00133 ROS_INFO_STREAM("Generated "<<seed_states_.size()<< " random seeds");
00134 }
00135
00136
00137 if (!getJointVelocityLimits(*robot_state_, group_name, velocity_limits_))
00138 {
00139 logWarn("Could not determine velocity limits of RobotModel from MoveIt");
00140 }
00141
00142 const moveit::core::JointModelGroup* joint_model_group_ptr = robot_state_->getJointModelGroup(group_name);
00143 if (joint_model_group_ptr)
00144 {
00145 joint_model_group_ptr->printGroupInfo();
00146
00147 const std::vector<std::string>& link_names = joint_model_group_ptr->getLinkModelNames();
00148 if (tool_frame_ != link_names.back())
00149 {
00150 logWarn("Tool frame '%s' does not match group tool frame '%s', functionality will be implemented in the future",
00151 tool_frame_.c_str(), link_names.back().c_str());
00152 }
00153
00154 if (world_frame_ != robot_state_->getRobotModel()->getModelFrame())
00155 {
00156 logWarn("World frame '%s' does not match model root frame '%s', all poses will be transformed to world frame '%s'",
00157 world_frame_.c_str(), robot_state_->getRobotModel()->getModelFrame().c_str(),world_frame_.c_str());
00158
00159 Eigen::Affine3d root_to_world = robot_state_->getFrameTransform(world_frame_);
00160 world_to_root_ = descartes_core::Frame(root_to_world.inverse());
00161 }
00162
00163 }
00164 else
00165 {
00166 logError("Joint group: %s does not exist in robot model", group_name_.c_str());
00167 std::stringstream msg;
00168 msg << "Possible group names: " << robot_state_->getRobotModel()->getJointModelGroupNames();
00169 logError(msg.str().c_str());
00170 }
00171 return true;
00172 }
00173
00174 bool MoveitStateAdapter::getIK(const Eigen::Affine3d &pose, const std::vector<double> &seed_state,
00175 std::vector<double> &joint_pose) const
00176 {
00177 robot_state_->setJointGroupPositions(group_name_, seed_state);
00178 return getIK(pose, joint_pose);
00179 }
00180
00181 bool MoveitStateAdapter::getIK(const Eigen::Affine3d &pose, std::vector<double> &joint_pose) const
00182 {
00183 bool rtn = false;
00184
00185
00186 Eigen::Affine3d tool_pose = world_to_root_.frame* pose;
00187
00188
00189 if (robot_state_->setFromIK(robot_state_->getJointModelGroup(group_name_), tool_pose,
00190 tool_frame_))
00191 {
00192 robot_state_->copyJointGroupPositions(group_name_, joint_pose);
00193 if(!isValid(joint_pose))
00194 {
00195 ROS_DEBUG_STREAM("Robot joint pose is invalid");
00196 }
00197 else
00198 {
00199 rtn = true;
00200 }
00201 }
00202 else
00203 {
00204 rtn = false;
00205 }
00206
00207 return rtn;
00208 }
00209
00210 bool MoveitStateAdapter::getAllIK(const Eigen::Affine3d &pose, std::vector<std::vector<double> > &joint_poses) const
00211 {
00212
00213
00214
00215
00216 double epsilon = 4 * robot_state_->getRobotModel()->getJointModelGroup(group_name_)->getSolverInstance()->
00217 getSearchDiscretization();
00218 logDebug("Utilizing an min. difference of %f between IK solutions", epsilon);
00219 joint_poses.clear();
00220 for (size_t sample_iter = 0; sample_iter < seed_states_.size(); ++sample_iter)
00221 {
00222 robot_state_->setJointGroupPositions(group_name_, seed_states_[sample_iter]);
00223 std::vector<double> joint_pose;
00224 if (getIK(pose, joint_pose))
00225 {
00226 if( joint_poses.empty())
00227 {
00228 std::stringstream msg;
00229 msg << "Found *first* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00230 logDebug(msg.str().c_str());
00231 joint_poses.push_back(joint_pose);
00232 }
00233 else
00234 {
00235 std::stringstream msg;
00236 msg << "Found *potential* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00237 logDebug(msg.str().c_str());
00238
00239 std::vector<std::vector<double> >::iterator joint_pose_it;
00240 bool match_found = false;
00241 for(joint_pose_it = joint_poses.begin(); joint_pose_it != joint_poses.end(); ++joint_pose_it)
00242 {
00243 if( descartes_core::utils::equal(joint_pose, (*joint_pose_it), epsilon) )
00244 {
00245 logDebug("Found matching, potential solution is not new");
00246 match_found = true;
00247 break;
00248 }
00249 }
00250 if (!match_found)
00251 {
00252 std::stringstream msg;
00253 msg << "Found *new* solution on " << sample_iter << " iteration, joint: " << joint_pose;
00254 logDebug(msg.str().c_str());
00255 joint_poses.push_back(joint_pose);
00256 }
00257 }
00258 }
00259 }
00260 logDebug("Found %d joint solutions out of %d iterations", joint_poses.size(), seed_states_.size());
00261 if (joint_poses.empty())
00262 {
00263 logError("Found 0 joint solutions out of %d iterations", seed_states_.size());
00264 return false;
00265 }
00266 else
00267 {
00268 logInform("Found %d joint solutions out of %d iterations", joint_poses.size(), seed_states_.size());
00269 return true;
00270 }
00271 }
00272
00273 bool MoveitStateAdapter::isInCollision(const std::vector<double>& joint_pose) const
00274 {
00275 bool in_collision = false;
00276 if(check_collisions_)
00277 {
00278 robot_state_->setJointGroupPositions(group_name_, joint_pose);
00279 in_collision = planning_scene_->isStateColliding(*robot_state_,group_name_);
00280 }
00281 return in_collision;
00282 }
00283
00284 bool MoveitStateAdapter::getFK(const std::vector<double> &joint_pose, Eigen::Affine3d &pose) const
00285 {
00286 bool rtn = false;
00287 robot_state_->setJointGroupPositions(group_name_, joint_pose);
00288 if ( isValid(joint_pose) )
00289 {
00290 if (robot_state_->knowsFrameTransform(tool_frame_))
00291 {
00292
00293 pose = world_to_root_.frame*robot_state_->getFrameTransform(tool_frame_);
00294 rtn = true;
00295 }
00296 else
00297 {
00298 logError("Robot state does not recognize tool frame: %s", tool_frame_.c_str());
00299 rtn = false;
00300 }
00301 }
00302 else
00303 {
00304 logError("Invalid joint pose passed to get forward kinematics");
00305 rtn = false;
00306 }
00307 std::stringstream msg;
00308 msg << "Returning the pose " << std::endl << pose.matrix() << std::endl
00309 << "For joint pose: " << joint_pose;
00310 logDebug(msg.str().c_str());
00311 return rtn;
00312 }
00313
00314 bool MoveitStateAdapter::isValid(const std::vector<double> &joint_pose) const
00315 {
00316 bool rtn = false;
00317
00318 if (robot_state_->getJointModelGroup(group_name_)->getActiveJointModels().size() ==
00319 joint_pose.size())
00320 {
00321 robot_state_->setJointGroupPositions(group_name_, joint_pose);
00322
00323
00324 robot_state_->setVariableVelocities(std::vector<double>(joint_pose.size(), 0.));
00325 robot_state_->setVariableAccelerations(std::vector<double>(joint_pose.size(), 0.));
00326 if (robot_state_->satisfiesBounds())
00327 {
00328 rtn = true;
00329 }
00330 else
00331 {
00332 std::stringstream msg;
00333 msg << "Joint pose: " << joint_pose << ", outside joint boundaries";
00334 logDebug(msg.str().c_str());
00335 }
00336
00337 if(isInCollision(joint_pose))
00338 {
00339 ROS_DEBUG_STREAM("Robot is in collision at this joint pose");
00340 rtn = false;
00341 }
00342
00343 }
00344 else
00345 {
00346 logError("Size of joint pose: %d doesn't match robot state variable size: %d",
00347 joint_pose.size(),
00348 robot_state_->getJointModelGroup(group_name_)->getActiveJointModels().size());
00349 rtn = false;
00350 }
00351 return rtn;
00352 }
00353
00354 bool MoveitStateAdapter::isValid(const Eigen::Affine3d &pose) const
00355 {
00356
00357 std::vector<double> dummy;
00358 return getIK(pose, dummy);
00359 }
00360
00361 int MoveitStateAdapter::getDOF() const
00362 {
00363 const moveit::core::JointModelGroup* group;
00364 group = robot_state_->getJointModelGroup(group_name_);
00365 return group->getVariableCount();
00366 }
00367
00368 bool MoveitStateAdapter::isValidMove(const std::vector<double>& from_joint_pose,
00369 const std::vector<double>& to_joint_pose,
00370 double dt) const
00371 {
00372 std::vector<double> max_joint_deltas;
00373 max_joint_deltas.reserve(velocity_limits_.size());
00374
00375
00376 if (from_joint_pose.size() != to_joint_pose.size())
00377 {
00378 ROS_ERROR_STREAM("To and From joint poses are of different sizes.");
00379 return false;
00380 }
00381
00382
00383 for (std::vector<double>::const_iterator it = velocity_limits_.begin(); it != velocity_limits_.end(); ++it)
00384 {
00385 max_joint_deltas.push_back((*it) * dt);
00386 }
00387
00388 for (std::vector<double>::size_type i = 0; i < from_joint_pose.size(); ++i)
00389 {
00390 if ( std::abs(from_joint_pose[i] - to_joint_pose[i]) > max_joint_deltas[i] )
00391 {
00392 return false;
00393 }
00394 }
00395
00396 return true;
00397 }
00398
00399 }
00400