SearchPlanner.cpp
Go to the documentation of this file.
00001 
00002 
00003 #include <geometry_msgs/Twist.h> 
00004 #include <nav_msgs/Path.h>
00005 #include <nav_msgs/GetPlan.h>
00006 
00007 #include <tf/LinearMath/Matrix3x3.h>
00008 #include <tf/LinearMath/Transform.h>
00009 #include <tf/transform_datatypes.h>
00010 
00011 
00012 #include "SearchPlanner.h"
00013 
00014 #include <fstream>
00015 
00016 #define SCENE_ANALYZATION_COST (60)
00017 
00018 geometry_msgs::PoseWithCovarianceStamped curr_position; 
00019 //bwi_scavenger::VisionTaskGoal *goal; 
00020 
00021 //actionlib::SimpleActionClient <bwi_scavenger::VisionTaskAction> * ac; 
00022 
00023 // callback function that saves robot's current position
00024 void callbackCurrPos(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg) {
00025     curr_position = *msg;
00026 }
00027 
00028 
00029 SearchPlannerSimple::SearchPlannerSimple(ros::NodeHandle *node_handle) {
00030 
00031     nh = node_handle;
00032 
00033     doors.push_back("d3_414b1");
00034     doors.push_back("d3_414b2");
00035     doors.push_back("d3_414a1");
00036     doors.push_back("d3_414a2");
00037 
00038     client = new KrClient("/action_executor/execute_plan", true);
00039     client->waitForServer(); 
00040     goal_door = 0; 
00041     srand(time(NULL)); 
00042    busy = false; 
00043 }
00044 
00045 bool SearchPlannerSimple::cancelCurrentGoal() {
00046 
00047     ros::Publisher pub1 = nh->advertise<actionlib_msgs::GoalID> 
00048         ("/move_base/cancel", 1000); 
00049     ros::Publisher pub2 = nh->advertise<actionlib_msgs::GoalID> 
00050         ("/move_base_interruptable/cancel", 1000); 
00051     actionlib_msgs::GoalID msg; 
00052 
00053     ros::spinOnce(); 
00054     pub1.publish(msg); 
00055 
00056     ros::spinOnce(); 
00057     pub2.publish(msg); 
00058 
00059     ros::spinOnce(); 
00060 
00061     client->cancelAllGoals(); 
00062 
00063 }
00064 
00065 bool SearchPlannerSimple::moveToNextDoor() {
00066     
00067     goal_door = (goal_door + rand()) % doors.size(); 
00068 
00069     ROS_INFO_STREAM("going to " << doors.at(goal_door));
00070     bwi_kr_execution::ExecutePlanGoal goal; 
00071     bwi_kr_execution::AspRule rule;
00072     bwi_kr_execution::AspFluent fluent;
00073     fluent.name = "not beside";
00074     fluent.variables.push_back(doors.at(goal_door));
00075     rule.body.push_back(fluent);
00076     goal.aspGoal.push_back(rule);
00077 
00078     ROS_INFO("sending goal"); 
00079     client->sendGoalAndWait(goal); 
00080     busy = true; 
00081 
00082     if (client->getState() == actionlib::SimpleClientGoalState::ABORTED) {
00083         ROS_INFO("Aborted");
00084     } else if (client->getState() == actionlib::SimpleClientGoalState::PREEMPTED) {
00085         ROS_INFO("Preempted");
00086     }
00087 
00088     else if (client->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) {
00089         ROS_INFO("Succeeded!");
00090     } else
00091         ROS_INFO("Terminated");
00092 
00093     busy = false; 
00094     return 0; 
00095 }
00096 
00097 
00098 SearchPlanner::SearchPlanner(ros::NodeHandle *node_handle, std::string path_to_yaml, float goal_tolerance) : 
00099         tolerance(goal_tolerance) {
00100 
00101     nh = node_handle; 
00102     client = new KrClient("/action_executor/execute_plan", true);
00103     client->waitForServer(); 
00104 
00105     YAML::Node yaml_positions; 
00106     std::ifstream fin(path_to_yaml.c_str()); 
00107 
00108 #ifdef HAVE_NEW_YAMLCPP
00109     yaml_positions = YAML::Load(fin);
00110 #else
00111     YAML::Parser parser(fin);
00112     parser.GetNextDocument(yaml_positions); 
00113 #endif
00114 
00115     // YAML::Node yaml_positions = YAML::LoadFile(path_to_yaml); 
00116 
00117     belief = std::vector<float> (yaml_positions.size(), 1.0/yaml_positions.size()); 
00118 
00119     client_make_plan = nh->serviceClient <nav_msgs::GetPlan> ("move_base/GlobalPlanner/make_plan"); 
00120 
00121     pub_simple_goal = nh->advertise<geometry_msgs::PoseStamped>("/move_base_interruptable_simple/goal", 100);
00122 
00123     sub_amcl_pose = nh->subscribe("amcl_pose", 100, callbackCurrPos); 
00124     ros::Duration(1.0).sleep(); 
00125 
00126     for (int i=0; i<yaml_positions.size(); i++) {
00127 #ifdef HAVE_NEW_YAMLCPP
00128         geometry_msgs::PoseStamped tmp_pose; 
00129         tmp_pose.header.frame_id = "level_mux/map";
00130         tmp_pose.pose.position.x = yaml_positions[i][0].as<double>(); 
00131         tmp_pose.pose.position.y = yaml_positions[i][1].as<double>(); 
00132         tmp_pose.pose.orientation.z = yaml_positions[i][2].as<double>(); 
00133         tmp_pose.pose.orientation.w = yaml_positions[i][3].as<double>(); 
00134         positions.push_back(tmp_pose); 
00135 #else
00136 #warning "yaml-cpp version < 0.5.0 does not work"
00137         // For Ubuntu Saucy to work, this would require a yaml-cpp
00138         // 0.3.0 compatible implementation.  Since we don't use Saucy,
00139         // we just let it fail.
00140 #endif
00141 
00142     }        
00143 
00144     busy = false; 
00145     setTargetDetection(false); 
00146     ros::spinOnce(); 
00147 }
00148 
00149 geometry_msgs::PoseStamped SearchPlanner::selectNextScene(const std::vector<float> &belief, int &next_goal_index) {
00150 
00151     geometry_msgs::PoseStamped nextScene; 
00152 
00153     nav_msgs::GetPlan srv; 
00154 
00155     std::vector<float> distances(belief.size(), 0.0); 
00156     std::vector<float> fitness(belief.size(), 0.0); 
00157     
00158     for (unsigned i=0; i<positions.size(); i++) {
00159 
00160         srv.request.tolerance = tolerance; 
00161         srv.request.start.header.frame_id = "level_mux/map"; 
00162         srv.request.start.pose.position.x = curr_position.pose.pose.position.x; 
00163         srv.request.start.pose.position.y = curr_position.pose.pose.position.y; 
00164 
00165         srv.request.goal.header.frame_id = "level_mux/map"; 
00166         srv.request.goal.pose.position.x = positions[i].pose.position.x; 
00167         srv.request.goal.pose.position.y = positions[i].pose.position.y; 
00168     
00169         client_make_plan.waitForExistence();
00170         if (false == client_make_plan.call(srv))
00171             ROS_ERROR("Failed in calling service for making a path"); 
00172     
00173         distances[i] = srv.response.plan.poses.size();
00174     }
00175     
00176     next_goal_index = -1; 
00177     float max_value = -1.0; 
00178 
00179     float resolution;
00180     ros::param::param <float> ("/move_base/local_costmap/resolution", resolution, 0.05); 
00181     
00182     for (unsigned i=0; i<positions.size(); i++) {
00183         
00184         fitness[i] = belief[i] / (distances[i]*resolution + SCENE_ANALYZATION_COST); 
00185         next_goal_index = (fitness[i] >= max_value) ? i : next_goal_index; 
00186         max_value = (fitness[i] >= max_value) ? fitness[i] : max_value;
00187     }
00188     
00189     nextScene = positions[next_goal_index]; 
00190     nextScene.header.frame_id = "level_mux/map";
00191     return nextScene; 
00192 }
00193 
00194 void SearchPlanner::moveToNextScene(const geometry_msgs::PoseStamped &msg_goal) {
00195 
00196     bool hasArrived = false; 
00197     ROS_INFO("Moving to next scene"); 
00198 
00199     busy = true; 
00200     ros::Rate r(2);
00201     while (ros::ok() and r.sleep() and !hasArrived and false == getTargetDetection()) {
00202 
00203         ros::spinOnce(); 
00204         float x = msg_goal.pose.position.x - curr_position.pose.pose.position.x;
00205         float y = msg_goal.pose.position.y - curr_position.pose.pose.position.y;
00206         float dis = pow(x*x + y*y, 0.5); 
00207 
00208         // ROS_INFO("distance to next goal: %f", dis); 
00209         // ROS_INFO("tolerance: %f", tolerance); 
00210         hasArrived = dis < tolerance;
00211 
00212         // sometimes motion plannerg gets aborted for unknown reasons, so here 
00213         // we periodically re-send the goal
00214         pub_simple_goal.publish(msg_goal); 
00215     }
00216     ROS_INFO("Arrived"); 
00217     busy = false; 
00218 }
00219 
00220 void SearchPlanner::analyzeScene(float angle, float angular_vel) {
00221 
00222     ros::Publisher pub = nh->advertise <geometry_msgs::Twist> ("/cmd_vel", 100); 
00223     geometry_msgs::Twist vel; 
00224     vel.linear.x = 0;
00225     vel.linear.y = 0;
00226 
00227     busy = true; 
00228     for (int i=0; i<170; i++) {
00229         if (i<10 or i>160) {
00230             vel.angular.z = 0;
00231         } else if (i<60) {
00232             //ROS_INFO("Look to the left..."); 
00233             vel.angular.z = angular_vel;
00234         } else if (i<160) {
00235             //ROS_INFO("Look to the right...");
00236             vel.angular.z = (-1.0) * angular_vel;
00237         } 
00238         ros::spinOnce();
00239         pub.publish(vel); 
00240         ros::Duration(0.1).sleep();
00241 
00242         if (getTargetDetection())
00243             break; 
00244     }
00245     busy = false; 
00246 }
00247 
00248 void SearchPlanner::updateBelief(int next_goal_index) {
00249     
00250     float true_positive_rate, true_negative_rate;
00251     true_positive_rate = true_negative_rate = 0.95; 
00252 
00253     std::vector <float> tmp_belief (belief); 
00254 
00255     // if (detected)
00256     //     tmp_belief[next_goal_index] = tmp_belief[next_goal_index] * true_positive_rate / 
00257     //         ((tmp_belief[next_goal_index] * true_positive_rate) + 
00258     //          ((1.0 - tmp_belief[next_goal_index]) * (1.0 - true_negative_rate))); 
00259     // else
00260     //     tmp_belief[next_goal_index] = tmp_belief[next_goal_index] * (1.0 - true_positive_rate) / 
00261     //         ((tmp_belief[next_goal_index] * (1.0 - true_positive_rate)) + 
00262     //          ((1.0 - tmp_belief[next_goal_index]) * true_negative_rate)); 
00263 
00264     tmp_belief[next_goal_index] = tmp_belief[next_goal_index] * 
00265                                   (1.0 - true_positive_rate) / 
00266                                   ( (tmp_belief[next_goal_index] * (1.0 - true_positive_rate)) + 
00267                                     ((1.0 - tmp_belief[next_goal_index]) * true_negative_rate)
00268                                   ); 
00269     float normalizer = 0.0; 
00270 
00271     for (int i = 0; i < tmp_belief.size(); i++)
00272         normalizer += tmp_belief[i]; 
00273 
00274     for (int i = 0; i < tmp_belief.size(); i++)
00275         belief[i]  = tmp_belief[i] / normalizer; 
00276 }
00277 


bwi_scavenger
Author(s): Shiqi Zhang
autogenerated on Thu Jun 6 2019 17:57:53