door_handler.cpp
Go to the documentation of this file.
00001 #include <boost/algorithm/string/join.hpp>
00002 #include <boost/regex.hpp>
00003 #include <gazebo_msgs/GetModelState.h>
00004 #include <gazebo_msgs/SetModelState.h>
00005 #include <gazebo_msgs/SpawnModel.h>
00006 #include <stdexcept>
00007 #include <tf/transform_datatypes.h>
00008 
00009 #include <bwi_tools/point.h>
00010 #include <segbot_simulation_apps/door_handler.h>
00011 
00012 namespace segbot_simulation_apps {
00013 
00014   DoorHandler::DoorHandler() {
00015 
00016     ros::NodeHandle nh, private_nh("~");
00017 
00018     std::vector<std::string> unavailable_parameters;
00019     std::string door_file;
00020     if (!(private_nh.getParam("door_file", door_file))) {
00021       unavailable_parameters.push_back("door_file");
00022     }
00023     if (!(private_nh.getParam("obstacle_urdf", obstacle_urdf_))) {
00024       unavailable_parameters.push_back("obstacle_urdf");
00025     }
00026     if (!(private_nh.getParam("door_urdf", door_urdf_))) {
00027       unavailable_parameters.push_back("door_urdf");
00028     }
00029 
00030     if (unavailable_parameters.size() != 0) {
00031       std::string message = "Following neccessary params not available: " +
00032         boost::algorithm::join(unavailable_parameters, ", ");
00033       ROS_INFO_STREAM(message);
00034       throw std::runtime_error(message);
00035     }
00036 
00037     readDoorFile(door_file, doors_);
00038 
00039     get_gazebo_model_client_ =
00040       nh.serviceClient<gazebo_msgs::GetModelState>(
00041           "/gazebo/get_model_state");
00042     bool gazebo_available = 
00043       get_gazebo_model_client_.waitForExistence(ros::Duration(30));
00044 
00045     if (!gazebo_available) {
00046       ROS_FATAL_STREAM("ClingoGazeboHandler: Gazebo is NOT AVAILABLE");
00047       throw 
00048         std::runtime_error("ClingoGazeboHandler: Gazebo is NOT AVAILABLE");
00049     }
00050 
00051     set_gazebo_model_client_ =
00052       nh.serviceClient<gazebo_msgs::SetModelState>(
00053           "/gazebo/set_model_state");
00054     set_gazebo_model_client_.waitForExistence();
00055 
00056     spawn_model_client_ =
00057       nh.serviceClient<gazebo_msgs::SpawnModel>(
00058           "/gazebo/spawn_urdf_model");
00059     set_gazebo_model_client_.waitForExistence();
00060 
00061     // Spawn all necessary doors
00062     door_open_status_.resize(doors_.size());
00063     for (unsigned i = 0; i < doors_.size(); ++i) {
00064       spawnObject(true, i);
00065       door_open_status_[i] = false;
00066     }
00067 
00068     // Don't use obstacles for now
00069     // Spawn 30 obstacle objects
00070     num_obstacles_ = 0;
00071     // for (unsigned i = 0; i < 30; ++i) {
00072     //   spawnObject(false, i);
00073     // }
00074 
00075   }
00076 
00077   geometry_msgs::Pose DoorHandler::getDefaultLocation(bool is_door, int index) {
00078     geometry_msgs::Pose retval;
00079     retval.position.y = 500.0f + index * 2;
00080     retval.position.z = 0.0f;
00081     retval.orientation.x = 0.0f;
00082     retval.orientation.y = 0.0f;
00083     retval.orientation.z = 0.0f;
00084     retval.orientation.w = 1.0f;
00085     if (is_door) {
00086       retval.position.x = 500.0f;
00087     } else {
00088       retval.position.x = 600.0f;
00089     }
00090     return retval;
00091   }
00092 
00093   float DoorHandler::getDoorWidth(int index) {
00094     return (0.75f/0.9f) * doors_[index].width;
00095   }
00096 
00097   geometry_msgs::Pose DoorHandler::getDoorLocation(int index) {
00098     geometry_msgs::Pose retval;
00099 
00100     bwi::Point2f door_center = 0.5 *
00101       (doors_[index].approach_points[0] +
00102        doors_[index].approach_points[1]);
00103     retval.position.x = door_center.x;
00104     retval.position.y = door_center.y;
00105     retval.position.z = 0;
00106 
00107     bwi::Point2f diff = 
00108       (doors_[index].approach_points[0] -
00109        doors_[index].approach_points[1]);
00110     float door_yaw = atan2f(diff.y, diff.x);
00111     retval.orientation = tf::createQuaternionMsgFromYaw(door_yaw);
00112 
00113     return retval;
00114   }
00115 
00116   bool DoorHandler::openDoor(const std::string& door) {
00117     size_t idx = bwi_planning_common::resolveDoor(door, doors_);
00118     if (idx == bwi_planning_common::NO_DOOR_IDX) {
00119       return false;
00120     }
00121     return openDoor(idx); 
00122   }
00123 
00124   bool DoorHandler::openDoor(int index) {
00125     if (index >= doors_.size()) {
00126       return false;
00127     }
00128     if (door_open_status_[index]) 
00129       return true;
00130     std::string prefix = "auto_door_";
00131     std::string model_name = prefix +
00132       boost::lexical_cast<std::string>(index);
00133     geometry_msgs::Pose pose = getDefaultLocation(true, index);
00134     bool success = teleportEntity(model_name, pose);
00135     door_open_status_[index] = true;
00136     return success;
00137   }
00138 
00139   void DoorHandler::openAllDoors() {
00140     for (unsigned i = 0; i < doors_.size(); ++i) {
00141       openDoor(i);
00142     }
00143   }
00144 
00145   bool DoorHandler::closeDoor(const std::string& door) {
00146     size_t idx = bwi_planning_common::resolveDoor(door, doors_);
00147     if (idx == bwi_planning_common::NO_DOOR_IDX) {
00148       return false;
00149     }
00150     return closeDoor(idx); 
00151   }
00152 
00153   bool DoorHandler::closeDoor(int index) {
00154     if (index >= doors_.size()) {
00155       return false;
00156     }
00157     if (!door_open_status_[index]) 
00158       return true;
00159     ROS_INFO_STREAM("Closing door " << index);
00160     std::string prefix = "auto_door_";
00161     std::string model_name = prefix +
00162       boost::lexical_cast<std::string>(index);
00163     geometry_msgs::Pose pose = getDoorLocation(index);
00164     bool success = teleportEntity(model_name, pose);
00165     door_open_status_[index] = false;
00166     return success;
00167   }
00168 
00169   void DoorHandler::closeAllDoors() {
00170     ROS_INFO_STREAM("Closing all doors");
00171     for (unsigned i = 0; i < doors_.size(); ++i) {
00172       closeDoor(i);
00173     }
00174   }
00175 
00176 
00177   bool DoorHandler::isDoorOpen(const std::string& door) {
00178     size_t idx = bwi_planning_common::resolveDoor(door, doors_);
00179     if (idx == bwi_planning_common::NO_DOOR_IDX) {
00180       return false;
00181     }
00182     return isDoorOpen(idx); 
00183   }
00184 
00185   bool DoorHandler::isDoorOpen(int index) {
00186     if (index >= doors_.size()) {
00187       return false;
00188     }
00189     return door_open_status_[index];
00190   }
00191 
00192   void DoorHandler::closeAllDoorsFarAwayFromPoint(
00193       const geometry_msgs::Pose& point, float distance) {
00194     for (unsigned i = 0; i < doors_.size(); ++i) {
00195       if (!door_open_status_[i])
00196         continue;
00197       bool is_door_near = 
00198         checkClosePoses(point, getDoorLocation(i), distance, false);
00199       if (!is_door_near) 
00200         closeDoor(i);
00201     }
00202   }
00203 
00204   bool DoorHandler::checkClosePoses(const geometry_msgs::Pose& p1,
00205       const geometry_msgs::Pose& p2, float threshold,
00206       bool check_yaw) {
00207     float dist_diff = 
00208       sqrtf(pow((p1.position.x - p2.position.x), 2) +
00209           pow((p1.position.y - p2.position.y), 2));
00210     if (dist_diff > threshold) {
00211       return false;
00212     }
00213     double yaw1 = tf::getYaw(p1.orientation);
00214     double yaw2 = tf::getYaw(p2.orientation);
00215     if (check_yaw && fabs(yaw1 - yaw2) > 0.1) {
00216       return false;
00217     }
00218     return true;
00219   }
00220 
00221   bool DoorHandler::teleportEntity(const std::string& entity,
00222       const geometry_msgs::Pose& pose) {
00223 
00224     int count = 0;
00225     int attempts = 5;
00226     bool location_verified = false;
00227     while (count < attempts and !location_verified) {
00228       gazebo_msgs::GetModelState get_srv;
00229       get_srv.request.model_name = entity;
00230       get_gazebo_model_client_.call(get_srv);
00231       location_verified = checkClosePoses(get_srv.response.pose, pose);
00232       if (!location_verified) {
00233         gazebo_msgs::SetModelState set_srv;
00234         set_srv.request.model_state.model_name = entity;
00235         set_srv.request.model_state.pose = pose;
00236         set_gazebo_model_client_.call(set_srv);
00237         if (!set_srv.response.success) {
00238           ROS_WARN_STREAM("SetModelState service call failed for " << entity
00239               << " to " << pose);
00240         }
00241       }
00242       ++count;
00243     }
00244     if (!location_verified) {
00245       ROS_ERROR_STREAM("Unable to teleport " << entity << " to " << pose
00246           << " despite " << attempts << " attempts.");
00247       return false;
00248     }
00249     return true;
00250   }
00251 
00252   void DoorHandler::spawnObject(bool is_door, int index) {
00253 
00254     gazebo_msgs::SpawnModel spawn;
00255     std::string prefix;
00256     if (is_door) {
00257       prefix = "auto_door_";
00258       spawn.request.model_xml = boost::regex_replace(door_urdf_, 
00259           boost::regex("@WIDTH@"),
00260           boost::lexical_cast<std::string>(getDoorWidth(index)));
00261       spawn.request.initial_pose = getDoorLocation(index);
00262     } else {
00263       prefix = "auto_obs_";
00264       index = num_obstacles_;
00265       spawn.request.model_xml = obstacle_urdf_;
00266       spawn.request.initial_pose = getDefaultLocation(false, index);
00267     }
00268 
00269     spawn.request.model_name = prefix +
00270       boost::lexical_cast<std::string>(index);
00271 
00272     if (spawn_model_client_.call(spawn)) {
00273       if (spawn.response.success) {
00274         ++num_obstacles_;
00275         return;
00276       }
00277       ROS_WARN_STREAM("Received error message while spawning object: " <<
00278           spawn.response.status_message);
00279     }
00280 
00281     ROS_ERROR_STREAM("Unable to spawn: " << spawn.request.model_name);
00282   }      
00283 
00284 
00285 }


segbot_simulation_apps
Author(s): Piyush Khandelwal
autogenerated on Mon Oct 6 2014 07:31:00