segbot_logical_translator.cpp
Go to the documentation of this file.
00001 
00037 #include <tf/transform_datatypes.h>
00038 
00039 #include <boost/algorithm/string/classification.hpp>
00040 #include <boost/algorithm/string/join.hpp>
00041 #include <boost/algorithm/string/split.hpp>
00042 #include <boost/foreach.hpp>
00043 #include <bwi_mapper/map_utils.h>
00044 #include <bwi_mapper/point_utils.h>
00045 
00046 #include <segbot_logical_translator/segbot_logical_translator.h>
00047 
00048 namespace segbot_logical_translator {
00049 
00050   SegbotLogicalTranslator::SegbotLogicalTranslator() {
00051 
00052     ROS_INFO_STREAM("SegbotLogicalTranslator: Initializing...");
00053     nh_.reset(new ros::NodeHandle);
00054     
00055     std::string map_file, door_file, location_file;
00056     std::vector<std::string> required_parameters;
00057     if (!ros::param::get("~map_file", map_file)) {
00058       required_parameters.push_back("~map_file");
00059     }
00060     if (!ros::param::get("~door_file", door_file)) {
00061       required_parameters.push_back("~door_file");
00062     }
00063     if (!ros::param::get("~location_file", location_file)) {
00064       required_parameters.push_back("~location_file");
00065     }
00066     if (required_parameters.size() != 0) {
00067       std::string message = "SegbotLogicalTranslator: Required parameters [" + 
00068         boost::algorithm::join(required_parameters, ", ") + "] missing!";
00069       ROS_FATAL_STREAM(message);
00070       throw std::runtime_error(message);
00071     }
00072 
00073     std::string object_file;
00074     if (ros::param::get("~object_file", object_file)) {
00075       ROS_INFO_STREAM("Reading in object file from: " << object_file);
00076       bwi_planning_common::readObjectApproachFile( object_file,
00077           object_approach_map_);
00078     }
00079     bwi_planning_common::readDoorFile(door_file, doors_);
00080     bwi_planning_common::readLocationFile(location_file, 
00081         locations_, location_map_);
00082     mapper_.reset(new bwi_mapper::MapLoader(map_file));
00083     nav_msgs::OccupancyGrid grid;
00084     mapper_->getMap(grid);
00085     info_ = grid.info;
00086 
00087     ROS_INFO_STREAM("SegbotLogicalTranslator: Waiting for make_plan service..");
00088     make_plan_client_ = 
00089       nh_->serviceClient<nav_msgs::GetPlan>("move_base/make_plan"); 
00090     make_plan_client_.waitForExistence();
00091     ROS_INFO_STREAM("SegbotLogicalTranslator: make_plan service found!");
00092 
00093     ros::param::param<std::string>(
00094         "~global_frame_id", global_frame_id_, "/map");
00095   }
00096 
00097   bool SegbotLogicalTranslator::isDoorOpen(size_t idx) {
00098 
00099     if (idx > doors_.size()) {
00100       return false;
00101     }
00102 
00103     bwi_mapper::Point2f start_pt, goal_pt;
00104     float start_yaw, goal_yaw;
00105 
00106     start_pt = doors_[idx].approach_points[0];
00107     goal_pt = doors_[idx].approach_points[1];
00108     start_yaw = doors_[idx].approach_yaw[0];
00109     goal_yaw = doors_[idx].approach_yaw[1];
00110 
00111     nav_msgs::GetPlan srv;
00112     geometry_msgs::PoseStamped &start = srv.request.start;
00113     geometry_msgs::PoseStamped &goal = srv.request.goal;
00114     start.header.frame_id = goal.header.frame_id = global_frame_id_;
00115     start.header.stamp = goal.header.stamp = ros::Time::now();
00116 
00117     start.pose.position.x = start_pt.x;
00118     start.pose.position.y = start_pt.y;
00119     start.pose.position.z = 0;
00120     start.pose.orientation = tf::createQuaternionMsgFromYaw(start_yaw); 
00121 
00122     goal.pose.position.x = goal_pt.x;
00123     goal.pose.position.y = goal_pt.y;
00124     goal.pose.position.z = 0;
00125     goal.pose.orientation = tf::createQuaternionMsgFromYaw(goal_yaw);
00126     srv.request.tolerance = 0.5 + 1e-6;
00127 
00128     float min_distance = cv::norm(start_pt - goal_pt);
00129 
00130     if (make_plan_client_.call(srv)) {
00131       if (srv.response.plan.poses.size() != 0) {
00132         // Valid plan received. Check if plan distance seems reasonable
00133         float distance = 0;
00134         geometry_msgs::Point old_pt = 
00135           srv.response.plan.poses[0].pose.position;
00136         for (size_t i = 1; i < srv.response.plan.poses.size(); ++i) {
00137           geometry_msgs::Point current_pt = 
00138             srv.response.plan.poses[i].pose.position;
00139           distance += sqrt(pow(current_pt.x - old_pt.x, 2) + 
00140                            pow(current_pt.y - old_pt.y, 2));
00141           old_pt = current_pt;
00142         }
00143         if (distance < 3 * min_distance) {
00144           return true;
00145         } else {
00146           return false; // returned path probably through some other door
00147         }
00148       } else {
00149         return false; // this is ok. it means the door is closed
00150       }
00151     } else {
00152       return false; // shouldn't be here. the service has failed
00153     }
00154   }
00155 
00156   bool SegbotLogicalTranslator::getApproachPoint(size_t idx, 
00157       const bwi_mapper::Point2f& current_location,
00158       bwi_mapper::Point2f& point, float &yaw) {
00159 
00160     if (idx > doors_.size()) {
00161       return false;
00162     }
00163 
00164     for (size_t pt = 0; pt < 2; ++pt) {
00165       std::vector<std::string> approach_locations;
00166       boost::split(approach_locations, doors_[idx].approach_names[pt], 
00167           boost::is_any_of(","), boost::token_compress_on);
00168       BOOST_FOREACH(const std::string& location, approach_locations) {
00169         if (getLocationIdx(location) == 
00170             getLocationIdx(current_location)) {
00171           point = doors_[idx].approach_points[pt];
00172           yaw = doors_[idx].approach_yaw[pt];
00173           return true;
00174         }
00175       }
00176     }
00177 
00178     /* The door is not approachable from the current location */
00179     return false;
00180   }
00181 
00182   bool SegbotLogicalTranslator::getThroughDoorPoint(size_t idx, 
00183       const bwi_mapper::Point2f& current_location,
00184       bwi_mapper::Point2f& point, float& yaw) {
00185 
00186     if (idx > doors_.size()) {
00187       return false;
00188     }
00189 
00190     for (size_t pt = 0; pt < 2; ++pt) {
00191       std::vector<std::string> approach_locations;
00192       boost::split(approach_locations, doors_[idx].approach_names[pt], 
00193           boost::is_any_of(","), boost::token_compress_on);
00194       BOOST_FOREACH(const std::string& location, approach_locations) {
00195         if (getLocationIdx(location) == 
00196             getLocationIdx(current_location)) {
00197           point = doors_[idx].approach_points[1 - pt];
00198           yaw = M_PI + doors_[idx].approach_yaw[1 - pt];
00199           while (yaw > M_PI) yaw -= 2 * M_PI;
00200           while (yaw <= M_PI) yaw += 2 * M_PI;
00201           return true;
00202         }
00203       }
00204     }
00205 
00206     return false;
00207   }
00208 
00209   bool SegbotLogicalTranslator::isRobotFacingDoor(
00210       const bwi_mapper::Point2f& current_location,
00211       float yaw, float threshold, size_t idx) {
00212 
00213     bwi_mapper::Point2f center_pt = 0.5 * 
00214       (doors_[idx].approach_points[0] + doors_[idx].approach_points[1]);
00215     if (bwi_mapper::getMagnitude(center_pt - current_location) >
00216         threshold) {
00217       return false;
00218     }
00219 
00220     bwi_mapper::Point2f diff_pt = center_pt - current_location;
00221     float orientation_to_door = atan2f(diff_pt.y, diff_pt.x);
00222     while (orientation_to_door > yaw + M_PI) orientation_to_door -= 2*M_PI;
00223     while (orientation_to_door <= yaw - M_PI) orientation_to_door += 2*M_PI;
00224     if (fabs(orientation_to_door - yaw) > M_PI / 3) {
00225       return false;
00226     }
00227 
00228     return true;
00229   }
00230 
00231   bool SegbotLogicalTranslator::isRobotBesideDoor(
00232       const bwi_mapper::Point2f& current_location,
00233       float yaw, float threshold, size_t idx) {
00234 
00235     bwi_mapper::Point2f center_pt = 0.5 * 
00236       (doors_[idx].approach_points[0] + doors_[idx].approach_points[1]);
00237     if (bwi_mapper::getMagnitude(center_pt - current_location) >
00238         threshold) {
00239       return false;
00240     }
00241 
00242     return true;
00243   }
00244 
00245   size_t SegbotLogicalTranslator::getLocationIdx(
00246       const bwi_mapper::Point2f& current_location) {
00247 
00248     bwi_mapper::Point2f grid = bwi_mapper::toGrid(current_location, info_);
00249     size_t map_idx = MAP_IDX(info_.width, (int) grid.x, (int) grid.y);
00250     if (map_idx > location_map_.size()) {
00251       return (size_t) -1;
00252     }
00253     return (size_t) location_map_[map_idx];
00254 
00255   }
00256 
00257 } /* namespace segbot_logical_translator */


segbot_logical_translator
Author(s): Piyush Khandelwal
autogenerated on Mon Oct 6 2014 07:30:24