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
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;
00147 }
00148 } else {
00149 return false;
00150 }
00151 } else {
00152 return false;
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
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 }