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
00038 #include <ros/ros.h>
00039
00040 #include <planning_environment/util/collision_operations_generator.h>
00041 #include <yaml-cpp/yaml.h>
00042
00043 using namespace planning_environment;
00044
00045 inline double gen_rand(double min, double max)
00046 {
00047 int rand_num = rand()%100+1;
00048 double result = min + (double)((max-min)*rand_num)/101.0;
00049 return result;
00050 }
00051
00052 CollisionOperationsGenerator::CollisionOperationsGenerator(planning_environment::CollisionModels* cm)
00053 {
00054 setSafety(CollisionOperationsGenerator::Normal);
00055 cm_ = cm;
00056
00057 enableAllCollisions();
00058
00059 }
00060
00061 void CollisionOperationsGenerator::generateAdjacentInCollisionPairs(std::vector<CollisionOperationsGenerator::StringPair>& adjacent_in_collision_pairs)
00062 {
00063 adjacent_in_collision_pairs.clear();
00064 const planning_models::KinematicModel* model = cm_->getKinematicModel();
00065 const planning_models::KinematicModel::LinkModel* link = model->getRoot()->getChildLinkModel();
00066 accumulateAdjacentLinksRecursive(link, adjacent_in_collision_pairs);
00067 }
00068
00069 void CollisionOperationsGenerator::accumulateAdjacentLinksRecursive(const planning_models::KinematicModel::LinkModel* parent,
00070 std::vector<CollisionOperationsGenerator::StringPair>& adjacencies){
00071 std::vector<planning_models::KinematicModel::JointModel*> joints = parent->getChildJointModels();
00072
00073 for(size_t i = 0; i < joints.size(); i++)
00074 {
00075 const planning_models::KinematicModel::JointModel* joint = joints[i];
00076 StringPair pair;
00077 pair.first = parent->getName();
00078 pair.second = joint->getChildLinkModel()->getName();
00079 adjacencies.push_back(pair);
00080 accumulateAdjacentLinksRecursive(joint->getChildLinkModel(), adjacencies);
00081 }
00082 }
00083
00084
00085 void CollisionOperationsGenerator::generateAlwaysInCollisionPairs(std::vector<CollisionOperationsGenerator::StringPair>& always_in_collision,
00086 std::vector<CollisionOperationsGenerator::CollidingJointValues>& in_collision_joint_values)
00087 {
00088 sampleAndCountCollisions(establish_always_num_);
00089 std::vector<double> percentages;
00090 std::map<std::string, std::map<std::string, double> > percentage_num;
00091 buildOutputStructures(establish_always_num_, 1.0, 1.0,
00092 always_in_collision, percentages, in_collision_joint_values, percentage_num);
00093
00094 }
00095
00096
00097 void CollisionOperationsGenerator::generateDefaultInCollisionPairs(std::vector<CollisionOperationsGenerator::StringPair>& default_in_collision,
00098 std::vector<CollisionOperationsGenerator::CollidingJointValues>& in_collision_joint_values)
00099 {
00100 default_in_collision.clear();
00101 in_collision_joint_values.clear();
00102
00103 planning_models::KinematicState state(cm_->getKinematicModel());
00104
00105 state.setKinematicStateToDefault();
00106 CollidingJointValues cjv;
00107 state.getKinematicStateValues(cjv);
00108 std::vector<arm_navigation_msgs::ContactInformation> contacts;
00109 cm_->getAllCollisionsForState(state,
00110 contacts);
00111
00112 for(unsigned int i = 0; i < contacts.size(); i++) {
00113 arm_navigation_msgs::ContactInformation& contact = contacts[i];
00114 default_in_collision.push_back(StringPair(contact.contact_body_1, contact.contact_body_2));
00115 in_collision_joint_values.push_back(cjv);
00116 }
00117 }
00118
00119 void CollisionOperationsGenerator::generateOftenInCollisionPairs(std::vector<CollisionOperationsGenerator::StringPair>& often_in_collision,
00120 std::vector<double>& percentages,
00121 std::vector<CollisionOperationsGenerator::CollidingJointValues>& in_collision_joint_values)
00122 {
00123 sampleAndCountCollisions(establish_often_num_);
00124 std::map<std::string, std::map<std::string, double> > percentage_num;
00125 buildOutputStructures(establish_often_num_, establish_often_percentage_, 1.0,
00126 often_in_collision, percentages, in_collision_joint_values, percentage_num);
00127
00128 }
00129
00130 void CollisionOperationsGenerator::generateOccasionallyAndNeverInCollisionPairs(std::vector<CollisionOperationsGenerator::StringPair>& occasionally_in_collision_pairs,
00131 std::vector<CollisionOperationsGenerator::StringPair>& never_in_collision_pairs,
00132 std::vector<double>& collision_percentages,
00133 std::vector<CollisionOperationsGenerator::CollidingJointValues>& in_collision_joint_values)
00134 {
00135 occasionally_in_collision_pairs.clear();
00136 collision_percentages.clear();
00137 never_in_collision_pairs.clear();
00138 in_collision_joint_values.clear();
00139
00140 std::vector<CollisionOperationsGenerator::StringPair> first_in_collision_pairs;
00141 std::vector<CollisionOperationsGenerator::StringPair> second_in_collision_pairs;
00142
00143 std::vector<CollisionOperationsGenerator::CollidingJointValues> first_in_collision_joint_values;
00144 std::vector<CollisionOperationsGenerator::CollidingJointValues> second_in_collision_joint_values;
00145
00146 std::map<std::string, std::map<std::string, double> > first_percentage_num;
00147 std::map<std::string, std::map<std::string, double> > second_percentage_num;
00148
00149 sampleAndCountCollisions(establish_occasional_num_);
00150 buildOutputStructures(establish_occasional_num_, 1.0/(establish_occasional_num_*1.0), 1.0,
00151 first_in_collision_pairs, collision_percentages, first_in_collision_joint_values, first_percentage_num);
00152
00153 ROS_INFO_STREAM("First in collision size " << first_in_collision_pairs.size());
00154
00155 sampleAndCountCollisions(establish_occasional_num_);
00156 buildOutputStructures(establish_occasional_num_, 1.0/(establish_occasional_num_*1.0), 1.0,
00157 second_in_collision_pairs, collision_percentages, second_in_collision_joint_values, second_percentage_num);
00158
00159 ROS_INFO_STREAM("Second in collision size " << second_in_collision_pairs.size());
00160
00161 collision_percentages.clear();
00162 unsigned int diff_pairs = 0;
00163 std::map<std::string, std::map<std::string, bool> > already_occasionally;
00164 std::map<std::string, std::map<std::string, bool> > already_never;
00165 for(std::map<std::string, std::map<std::string, double> >::iterator it = first_percentage_num.begin();
00166 it != first_percentage_num.end();
00167 it++) {
00168 for(std::map<std::string, double>::iterator it2 = it->second.begin();
00169 it2 != it->second.end();
00170 it2++) {
00171 bool first_never = (it2->second == 0);
00172 bool second_never = (second_percentage_num[it->first][it2->first] == 0);
00173
00174 if(first_never && second_never) {
00175 if(already_never[it->first][it2->first] ||
00176 already_never[it2->first][it->first]) {
00177 continue;
00178 }
00179 already_never[it->first][it2->first] = true;
00180 already_never[it2->first][it->first] = true;
00181 never_in_collision_pairs.push_back(StringPair(it->first, it2->first));
00182 } else if(second_never) {
00183 diff_pairs++;
00184 occasionally_in_collision_pairs.push_back(StringPair(it->first, it2->first));
00185 collision_percentages.push_back(first_percentage_num[it->first][it2->first]);
00186 for(unsigned int i = 0; i < first_in_collision_pairs.size(); i++) {
00187 if((first_in_collision_pairs[i].first == it->first && first_in_collision_pairs[i].second == it2->first) ||
00188 (first_in_collision_pairs[i].first == it2->first && first_in_collision_pairs[i].second == it->first)) {
00189 in_collision_joint_values.push_back(first_in_collision_joint_values[i]);
00190 }
00191 }
00192 } else if(first_never){
00193 diff_pairs++;
00194 occasionally_in_collision_pairs.push_back(StringPair(it->first, it2->first));
00195 collision_percentages.push_back(second_percentage_num[it->first][it2->first]);
00196 for(unsigned int i = 0; i < second_in_collision_pairs.size(); i++) {
00197 if((second_in_collision_pairs[i].first == it->first && second_in_collision_pairs[i].second == it2->first) ||
00198 (second_in_collision_pairs[i].first == it2->first && second_in_collision_pairs[i].second == it->first)) {
00199 in_collision_joint_values.push_back(second_in_collision_joint_values[i]);
00200 }
00201 }
00202 } else {
00203 if(already_occasionally[it->first][it2->first] ||
00204 already_occasionally[it2->first][it->first]) {
00205 continue;
00206 }
00207 already_occasionally[it->first][it2->first] = true;
00208 already_occasionally[it2->first][it->first] = true;
00209 occasionally_in_collision_pairs.push_back(StringPair(it->first, it2->first));
00210 collision_percentages.push_back(second_percentage_num[it->first][it2->first]);
00211 for(unsigned int i = 0; i < second_in_collision_pairs.size(); i++) {
00212 if((second_in_collision_pairs[i].first == it->first && second_in_collision_pairs[i].second == it2->first) ||
00213 (second_in_collision_pairs[i].first == it2->first && second_in_collision_pairs[i].second == it->first)) {
00214 in_collision_joint_values.push_back(second_in_collision_joint_values[i]);
00215 }
00216 }
00217 }
00218 }
00219 }
00220 ROS_INFO_STREAM("Occasionally pairs num " << occasionally_in_collision_pairs.size());
00221 ROS_INFO_STREAM("Never pairs num " << never_in_collision_pairs.size());
00222 ROS_INFO_STREAM("Diff pairs num " << diff_pairs);
00223 }
00224
00225 void CollisionOperationsGenerator::enableAllCollisions() {
00226 collision_space::EnvironmentModel::AllowedCollisionMatrix altered_acm = cm_->getCurrentAllowedCollisionMatrix();
00227 altered_acm.changeEntry(false);
00228 cm_->setAlteredAllowedCollisionMatrix(altered_acm);
00229 }
00230
00231
00232 void CollisionOperationsGenerator::enablePairCollisionChecking(const CollisionOperationsGenerator::StringPair& pair){
00233 collision_space::EnvironmentModel::AllowedCollisionMatrix altered_acm = cm_->getCurrentAllowedCollisionMatrix();
00234 altered_acm.changeEntry(pair.first, pair.second, false);
00235 cm_->setAlteredAllowedCollisionMatrix(altered_acm);
00236
00237 }
00238 void CollisionOperationsGenerator::disablePairCollisionChecking(const CollisionOperationsGenerator::StringPair& pair) {
00239 collision_space::EnvironmentModel::AllowedCollisionMatrix altered_acm = cm_->getCurrentAllowedCollisionMatrix();
00240 altered_acm.changeEntry(pair.first, pair.second, true);
00241 cm_->setAlteredAllowedCollisionMatrix(altered_acm);
00242 }
00243
00244 void CollisionOperationsGenerator::disablePairCollisionChecking(const std::vector<CollisionOperationsGenerator::StringPair>& pair_vec) {
00245 collision_space::EnvironmentModel::AllowedCollisionMatrix altered_acm = cm_->getCurrentAllowedCollisionMatrix();
00246 for(unsigned int i = 0; i < pair_vec.size(); i++) {
00247 altered_acm.changeEntry(pair_vec[i].first, pair_vec[i].second, true);
00248 }
00249 cm_->setAlteredAllowedCollisionMatrix(altered_acm);
00250 }
00251
00252 void CollisionOperationsGenerator::generateSamplingStructures(const std::map<std::string, bool>& add_map) {
00253 joint_bounds_map_.clear();
00254
00255 const std::vector<planning_models::KinematicModel::JointModel*>& jmv = cm_->getKinematicModel()->getJointModels();
00256
00257 for(unsigned int i = 1; i < jmv.size(); i++) {
00258 const std::map<std::string, std::pair<double, double> >& joint_bounds = jmv[i]->getAllVariableBounds();
00259 for(std::map<std::string, std::pair<double, double> >::const_iterator it = joint_bounds.begin();
00260 it != joint_bounds.end();
00261 it++) {
00262 if(joint_bounds_map_.find(it->first) != joint_bounds_map_.end()) {
00263 ROS_WARN_STREAM("Have repeat DOF names for " << it->first);
00264 continue;
00265 }
00266 if(add_map.find(it->first) != add_map.end()) {
00267 if(!add_map.find(it->first)->second) {
00268 continue;
00269 }
00270 }
00271 if(it->second.first > it->second.second) {
00272 ROS_WARN_STREAM("Lower bound for DOF " << it->first << " is greater than upper bound " << it->second.first << " " << it->second.second);
00273 } else if(it->second.first == -DBL_MAX) {
00274 ROS_WARN_STREAM("Some non-root DOF " << it->first << " has negative inf lower bound");
00275 }
00276 if(it->second.second == DBL_MAX) {
00277 ROS_WARN_STREAM("Some non-root DOF " << it->first << " has inf upper bound");
00278 }
00279 joint_bounds_map_[it->first] = it->second;
00280 }
00281 }
00282 }
00283
00284 void CollisionOperationsGenerator::sampleAndCountCollisions(unsigned int num) {
00285 resetCountingMap();
00286
00287 planning_models::KinematicState state(cm_->getKinematicModel());
00288
00289 for(unsigned int i = 0; i < num; i++) {
00290 generateRandomState(state);
00291
00292 std::vector<arm_navigation_msgs::ContactInformation> contacts;
00293 cm_->getAllCollisionsForState(state,
00294 contacts);
00295
00296 if(i != 0 && i % 10000 == 0) {
00297 ROS_INFO_STREAM("On iteration " << i);
00298 }
00299
00300 for(unsigned int i = 0; i < contacts.size(); i++) {
00301 arm_navigation_msgs::ContactInformation& contact = contacts[i];
00302 if(collision_count_map_.find(contact.contact_body_1) == collision_count_map_.end()) {
00303 ROS_WARN_STREAM("Problem - have no count for collision body " << contact.contact_body_1);
00304 }
00305 if(collision_count_map_.find(contact.contact_body_2) == collision_count_map_.end()) {
00306 ROS_WARN_STREAM("Problem - have no count for collision body " << contact.contact_body_2);
00307 }
00308 collision_count_map_[contact.contact_body_1][contact.contact_body_2]++;
00309 collision_count_map_[contact.contact_body_2][contact.contact_body_1]++;
00310 CollidingJointValues cjv;
00311 state.getKinematicStateValues(cjv);
00312 collision_joint_values_[contact.contact_body_1][contact.contact_body_2] = cjv;
00313 collision_joint_values_[contact.contact_body_2][contact.contact_body_1] = cjv;
00314 }
00315 }
00316 }
00317
00318 void CollisionOperationsGenerator::buildOutputStructures(unsigned int num, double low_threshold, double high_threshold,
00319 std::vector<CollisionOperationsGenerator::StringPair>& meets_threshold_collision,
00320 std::vector<double>& percentages,
00321 std::vector<CollisionOperationsGenerator::CollidingJointValues>& joint_values,
00322 std::map<std::string, std::map<std::string, double> >& percentage_num){
00323 meets_threshold_collision.clear();
00324 percentages.clear();
00325 joint_values.clear();
00326 percentage_num.clear();
00327
00328 bool do_output = false;
00329 for(std::map<std::string, std::map<std::string, unsigned int> >::iterator it = collision_count_map_.begin();
00330 it != collision_count_map_.end();
00331 it++) {
00332 for(std::map<std::string, unsigned int>::iterator it2 = it->second.begin();
00333 it2 != it->second.end();
00334 it2++) {
00335 if(it->first == it2->first) {
00336 continue;
00337 }
00338
00339 if(percentage_num.find(it->first) != percentage_num.end()) {
00340 if(percentage_num.find(it->first)->second.find(it2->first) !=
00341 percentage_num.find(it->first)->second.end()) {
00342 continue;
00343 }
00344 }
00345 if(percentage_num.find(it2->first) != percentage_num.end()) {
00346 if(percentage_num.find(it2->first)->second.find(it->first) !=
00347 percentage_num.find(it2->first)->second.end()) {
00348 continue;
00349 }
00350 }
00351 double per = (it2->second*1.0)/(num*1.0);
00352 percentage_num[it->first][it2->first] = per;
00353 percentage_num[it2->first][it->first] = per;
00354 if(per >= low_threshold && per <= high_threshold) {
00355 meets_threshold_collision.push_back(StringPair(it->first, it2->first));
00356 percentages.push_back(per);
00357 joint_values.push_back(collision_joint_values_[it->first][it2->first]);
00358 }
00359 if(do_output) {
00360 ROS_INFO_STREAM("Per between " << it->first << " and " << it2->first << " is " << per << " low " << low_threshold << " high " << high_threshold);
00361 }
00362 }
00363 do_output = false;
00364 }
00365 }
00366
00367 void CollisionOperationsGenerator::performanceTestSavedResults(std::map<CollisionOperationsGenerator::DisableType, std::vector<CollisionOperationsGenerator::StringPair> >& disable_types) {
00368 enableAllCollisions();
00369 ros::WallTime n1 = ros::WallTime::now();
00370 sampleAndCountCollisions(performance_testing_num_);
00371 ROS_INFO_STREAM("With no collisions disabled full collision check take an average of "
00372 << (ros::WallTime::now()-n1).toSec()/(performance_testing_num_/1.0) << " seconds.");
00373 for(std::map<DisableType, std::vector<StringPair> >::iterator it = disable_types.begin();
00374 it != disable_types.end(); it++) {
00375 disablePairCollisionChecking(it->second);
00376 std::string com = "Disabling ";
00377 if(it->first == ALWAYS) {
00378 com = "Always";
00379 } else if(it->first == DEFAULT) {
00380 com = "Default";
00381 } else if(it->first == OFTEN) {
00382 com = "Often";
00383 } else if(it->first == OCCASIONALLY) {
00384 com = "Occasionally";
00385 } else if(it->first == ADJACENT){
00386 com = "Adjacent";
00387 } else {
00388 com = "Never";
00389 }
00390 com += " in collision pairs average full check time is ";
00391 n1 = ros::WallTime::now();
00392 sampleAndCountCollisions(performance_testing_num_);
00393 ROS_INFO_STREAM(com << (ros::WallTime::now()-n1).toSec()/(performance_testing_num_/1.0) << " seconds.");
00394 }
00395 }
00396
00397
00398 void CollisionOperationsGenerator::outputYamlStringOfSavedResults(YAML::Emitter& outy, const std::map<CollisionOperationsGenerator::DisableType, std::vector<CollisionOperationsGenerator::StringPair> >& disable_types) {
00399 std::map<std::pair<std::string, std::string>, bool> already_output;
00400 outy << YAML::Key << "default_collision_operations";
00401 outy << YAML::Value << YAML::BeginSeq;
00402 for(std::map<DisableType, std::vector<StringPair> >::const_iterator it = disable_types.begin();
00403 it != disable_types.end(); it++) {
00404 std::string com;
00405 if(it->first == ALWAYS) {
00406 com = "Always";
00407 } else if(it->first == DEFAULT) {
00408 com = "Default";
00409 } else if(it->first == OFTEN) {
00410 com = "Often";
00411 } else if(it->first == OCCASIONALLY) {
00412 com = "Occasionally";
00413 } else if(it->first == ADJACENT){
00414 com = "Adjacent";
00415 } else {
00416 com = "Never";
00417 }
00418 com += " in collision";
00419 for(unsigned int i = 0; i < it->second.size(); i++) {
00420 std::pair<std::string, std::string> p1(it->second[i].first, it->second[i].second);
00421 std::pair<std::string, std::string> p2(it->second[i].second, it->second[i].first);
00422 if(already_output.find(p1) != already_output.end() ||
00423 already_output.find(p2) != already_output.end()) {
00424 continue;
00425 }
00426 already_output[p1] = true;
00427 already_output[p2] = true;
00428 outy << YAML::BeginMap;
00429 outy << YAML::Key << "object1" << YAML::Value << it->second[i].first;
00430 outy << YAML::Key << "object2" << YAML::Value << it->second[i].second;
00431 outy << YAML::Key << "operation" << YAML::Value << "disable";
00432 outy << YAML::Comment(com);
00433 outy << YAML::EndMap;
00434 }
00435 }
00436 }
00437
00438 void CollisionOperationsGenerator::resetCountingMap() {
00439 const std::vector<planning_models::KinematicModel::LinkModel*>& lmv = cm_->getKinematicModel()->getLinkModelsWithCollisionGeometry();
00440
00441 collision_count_map_.clear();
00442
00443 std::map<std::string, unsigned int> all_link_zero;
00444 for(unsigned int i = 0; i < lmv.size(); i++) {
00445 all_link_zero[lmv[i]->getName()] = 0;
00446 }
00447 for(unsigned int i = 0; i < lmv.size(); i++) {
00448 collision_count_map_[lmv[i]->getName()] = all_link_zero;
00449 }
00450 collision_joint_values_.clear();
00451 }
00452
00453 void CollisionOperationsGenerator::generateRandomState(planning_models::KinematicState& state) {
00454 std::map<std::string, double> values;
00455 for(std::map<std::string, std::pair<double, double> >::iterator it = joint_bounds_map_.begin();
00456 it != joint_bounds_map_.end();
00457 it++) {
00458 values[it->first] = gen_rand(it->second.first, it->second.second);
00459
00460
00461 }
00462 state.setKinematicState(values);
00463 }