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
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
00044
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 }
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
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
00089 group_name_ = group_name;
00090 tool_frame_ = tcp_frame;
00091 world_frame_ = world_frame;
00092
00093
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
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
00174
00175
00176
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
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
00286 if (!joint_group_->satisfiesPositionBounds(joint_pose.data()))
00287 {
00288 return false;
00289 }
00290
00291 return !isInCollision(joint_pose);
00292 }
00293
00294 bool MoveitStateAdapter::isValid(const Eigen::Affine3d& pose) const
00295 {
00296
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
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 }