00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <moveit/ompl_interface/detail/state_validity_checker.h>
00038 #include <moveit/ompl_interface/model_based_planning_context.h>
00039 #include <moveit/profiler/profiler.h>
00040 #include <ros/ros.h>
00041
00042 ompl_interface::StateValidityChecker::StateValidityChecker(const ModelBasedPlanningContext *pc) :
00043 ompl::base::StateValidityChecker(pc->getOMPLSimpleSetup().getSpaceInformation()), planning_context_(pc),
00044 group_name_(pc->getGroupName()), tss_(pc->getCompleteInitialRobotState()), verbose_(false)
00045 {
00046 specs_.clearanceComputationType = ompl::base::StateValidityCheckerSpecs::APPROXIMATE;
00047 specs_.hasValidDirectionComputation = false;
00048
00049 collision_request_with_distance_.distance = true;
00050 collision_request_with_cost_.cost = true;
00051
00052 collision_request_simple_.group_name = planning_context_->getGroupName();
00053 collision_request_with_distance_.group_name = planning_context_->getGroupName();
00054 collision_request_with_cost_.group_name = planning_context_->getGroupName();
00055
00056 collision_request_simple_verbose_ = collision_request_simple_;
00057 collision_request_simple_verbose_.verbose = true;
00058
00059 collision_request_with_distance_verbose_ = collision_request_with_distance_;
00060 collision_request_with_distance_verbose_.verbose = true;
00061 }
00062
00063 void ompl_interface::StateValidityChecker::setVerbose(bool flag)
00064 {
00065 verbose_ = flag;
00066 }
00067
00068 bool ompl_interface::StateValidityChecker::isValid(const ompl::base::State *state, bool verbose) const
00069 {
00070
00071 return planning_context_->useStateValidityCache() ? isValidWithCache(state, verbose) : isValidWithoutCache(state, verbose);
00072 }
00073
00074 bool ompl_interface::StateValidityChecker::isValid(const ompl::base::State *state, double &dist, bool verbose) const
00075 {
00076
00077 return planning_context_->useStateValidityCache() ? isValidWithCache(state, dist, verbose) : isValidWithoutCache(state, dist, verbose);
00078 }
00079
00080 double ompl_interface::StateValidityChecker::cost(const ompl::base::State *state) const
00081 {
00082 bool useCollisionDistanceCost = false;
00083 double cost = 0.0;
00084
00085 if( useCollisionDistanceCost )
00086 {
00087 robot_state::RobotState *kstate = tss_.getStateStorage();
00088 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00089
00090 collision_detection::CollisionResult res;
00091 planning_context_->getPlanningScene()->checkCollision(collision_request_with_cost_, res, *kstate);
00092
00093 for (std::set<collision_detection::CostSource>::const_iterator it = res.cost_sources.begin() ; it != res.cost_sources.end() ; ++it)
00094 cost += it->cost * it->getVolume();
00095 }
00096 else
00097 {
00098 static std::vector<double> prev_joint_values;
00099 static bool first_time = true;
00100 static boost::thread::id thread_id = boost::this_thread::get_id();
00101
00102
00103 if( thread_id != boost::this_thread::get_id() )
00104 ROS_ERROR_STREAM("Multiple threads are not implemented here...");
00105
00106
00107 robot_state::RobotState *kstate = tss_.getStateStorage();
00108 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00109
00110 std::vector<double> new_joint_values;
00111
00112
00113 kstate->getStateValues(new_joint_values);
00114
00115
00116 for (std::size_t i = 0; i < new_joint_values.size(); ++i)
00117 {
00118 double value = 0;
00119
00120 if (first_time)
00121 {
00122 first_time = false;
00123 prev_joint_values.resize(new_joint_values.size());
00124 }
00125 else
00126 {
00127
00128 value = fabs(prev_joint_values[i] - new_joint_values[i]);
00129 }
00130
00131 cost += value;
00132
00133
00134 prev_joint_values[i] = new_joint_values[i];
00135 }
00136 }
00137
00138 return cost;
00139 }
00140
00141 double ompl_interface::StateValidityChecker::clearance(const ompl::base::State *state) const
00142 {
00143 robot_state::RobotState *kstate = tss_.getStateStorage();
00144 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00145
00146 collision_detection::CollisionResult res;
00147 planning_context_->getPlanningScene()->checkCollision(collision_request_with_distance_, res, *kstate);
00148 return res.collision ? 0.0 : (res.distance < 0.0 ? std::numeric_limits<double>::infinity() : res.distance);
00149 }
00150
00151 bool ompl_interface::StateValidityChecker::isValidWithoutCache(const ompl::base::State *state, bool verbose) const
00152 {
00153 if (!si_->satisfiesBounds(state))
00154 {
00155 if (verbose)
00156 logInform("State outside bounds");
00157 return false;
00158 }
00159
00160 robot_state::RobotState *kstate = tss_.getStateStorage();
00161 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00162
00163
00164 const kinematic_constraints::KinematicConstraintSetPtr &kset = planning_context_->getPathConstraints();
00165 if (kset && !kset->decide(*kstate, verbose).satisfied)
00166 return false;
00167
00168
00169 if (!planning_context_->getPlanningScene()->isStateFeasible(*kstate, verbose))
00170 return false;
00171
00172
00173 collision_detection::CollisionResult res;
00174 planning_context_->getPlanningScene()->checkCollision(verbose ? collision_request_simple_verbose_ : collision_request_simple_, res, *kstate);
00175 return res.collision == false;
00176 }
00177
00178 bool ompl_interface::StateValidityChecker::isValidWithoutCache(const ompl::base::State *state, double &dist, bool verbose) const
00179 {
00180 if (!si_->satisfiesBounds(state))
00181 {
00182 if (verbose)
00183 logInform("State outside bounds");
00184 return false;
00185 }
00186
00187 robot_state::RobotState *kstate = tss_.getStateStorage();
00188 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00189
00190
00191 const kinematic_constraints::KinematicConstraintSetPtr &kset = planning_context_->getPathConstraints();
00192 if (kset)
00193 {
00194 kinematic_constraints::ConstraintEvaluationResult cer = kset->decide(*kstate, verbose);
00195 if (!cer.satisfied)
00196 {
00197 dist = cer.distance;
00198 return false;
00199 }
00200 }
00201
00202
00203 if (!planning_context_->getPlanningScene()->isStateFeasible(*kstate, verbose))
00204 {
00205 dist = 0.0;
00206 return false;
00207 }
00208
00209
00210 collision_detection::CollisionResult res;
00211 planning_context_->getPlanningScene()->checkCollision(verbose ? collision_request_with_distance_verbose_ : collision_request_with_distance_, res, *kstate);
00212 dist = res.distance;
00213 return res.collision == false;
00214 }
00215
00216 bool ompl_interface::StateValidityChecker::isValidWithCache(const ompl::base::State *state, bool verbose) const
00217 {
00218 if (state->as<ModelBasedStateSpace::StateType>()->isValidityKnown())
00219 return state->as<ModelBasedStateSpace::StateType>()->isMarkedValid();
00220
00221 if (!si_->satisfiesBounds(state))
00222 {
00223 if (verbose)
00224 logInform("State outside bounds");
00225 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid();
00226 return false;
00227 }
00228
00229 robot_state::RobotState *kstate = tss_.getStateStorage();
00230 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00231
00232
00233 const kinematic_constraints::KinematicConstraintSetPtr &kset = planning_context_->getPathConstraints();
00234 if (kset && !kset->decide(*kstate, verbose).satisfied)
00235 {
00236 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid();
00237 return false;
00238 }
00239
00240
00241 if (!planning_context_->getPlanningScene()->isStateFeasible(*kstate, verbose))
00242 {
00243 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid();
00244 return false;
00245 }
00246
00247
00248 collision_detection::CollisionResult res;
00249 planning_context_->getPlanningScene()->checkCollision(verbose ? collision_request_simple_verbose_ : collision_request_simple_, res, *kstate);
00250 if (res.collision == false)
00251 {
00252 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markValid();
00253 return true;
00254 }
00255 else
00256 {
00257 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid();
00258 return false;
00259 }
00260 }
00261
00262 bool ompl_interface::StateValidityChecker::isValidWithCache(const ompl::base::State *state, double &dist, bool verbose) const
00263 {
00264 if (state->as<ModelBasedStateSpace::StateType>()->isValidityKnown() && state->as<ModelBasedStateSpace::StateType>()->isGoalDistanceKnown())
00265 {
00266 dist = state->as<ModelBasedStateSpace::StateType>()->distance;
00267 return state->as<ModelBasedStateSpace::StateType>()->isMarkedValid();
00268 }
00269
00270 if (!si_->satisfiesBounds(state))
00271 {
00272 if (verbose)
00273 logInform("State outside bounds");
00274 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid(0.0);
00275 return false;
00276 }
00277
00278 robot_state::RobotState *kstate = tss_.getStateStorage();
00279 planning_context_->getOMPLStateSpace()->copyToRobotState(*kstate, state);
00280
00281
00282 const kinematic_constraints::KinematicConstraintSetPtr &kset = planning_context_->getPathConstraints();
00283 if (kset)
00284 {
00285 kinematic_constraints::ConstraintEvaluationResult cer = kset->decide(*kstate, verbose);
00286 if (!cer.satisfied)
00287 {
00288 dist = cer.distance;
00289 const_cast<ob::State*>(state)->as<ModelBasedStateSpace::StateType>()->markInvalid(dist);
00290 return false;
00291 }
00292 }
00293
00294
00295 if (!planning_context_->getPlanningScene()->isStateFeasible(*kstate, verbose))
00296 {
00297 dist = 0.0;
00298 return false;
00299 }
00300
00301
00302 collision_detection::CollisionResult res;
00303 planning_context_->getPlanningScene()->checkCollision(verbose ? collision_request_with_distance_verbose_ : collision_request_with_distance_, res, *kstate);
00304 dist = res.distance;
00305 return res.collision == false;
00306 }