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
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
00069
00070 num_obstacles_ = 0;
00071
00072
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 }