Go to the documentation of this file.00001 #include <lj_costmap/jockey.h>
00002
00003 namespace lj_costmap
00004 {
00005
00006 Jockey::Jockey(std::string name, double frontier_width, double max_frontier_angle) :
00007 LocalizingJockey(name),
00008 range_cutoff_(0),
00009 data_received_(false),
00010 place_profile_interface_name_(name + "_place_profile"),
00011 crossing_interface_name_(name + "_crossing"),
00012 localize_service_("localize_in_vertex"),
00013 dissimilarity_server_name_("compute_dissimilarity"),
00014 crossing_detector_(frontier_width, max_frontier_angle)
00015 {
00016 private_nh_.getParam("place_profile_interface_name", place_profile_interface_name_);
00017 private_nh_.getParam("crossing_interface_name", crossing_interface_name_);
00018 private_nh_.getParam("localize_service", localize_service_);
00019 private_nh_.getParam("dissimilarity_server_name", dissimilarity_server_name_);
00020 range_cutoff_set_ = private_nh_.getParam("range_cutoff", range_cutoff_);
00021
00022 initMapPlaceProfileInterface();
00023 initMapCrossingInterface();
00024 }
00025
00028 void Jockey::initMapPlaceProfileInterface()
00029 {
00030 ros::ServiceClient client = nh_.serviceClient<lama_interfaces::AddInterface>("interface_factory");
00031 while (ros::ok() && !client.waitForExistence(ros::Duration(5.0)))
00032 {
00033 ROS_WARN("Waiting for service /interface_factory");
00034 }
00035 lama_interfaces::AddInterface srv;
00036 srv.request.interface_name = place_profile_interface_name_;
00037 srv.request.interface_type = lama_interfaces::AddInterfaceRequest::SERIALIZED;
00038 srv.request.get_service_message = "lama_msgs/GetPlaceProfile";
00039 srv.request.set_service_message = "lama_msgs/SetPlaceProfile";
00040 if (!client.call(srv))
00041 {
00042 ROS_ERROR_STREAM("Failed to create the LaMa interface " << place_profile_interface_name_);
00043 return;
00044 }
00045
00046 place_profile_getter_ = nh_.serviceClient<lama_msgs::GetPlaceProfile>(srv.response.get_service_name);
00047 place_profile_setter_ = nh_.serviceClient<lama_msgs::SetPlaceProfile>(srv.response.set_service_name);
00048 }
00049
00052 void Jockey::initMapCrossingInterface()
00053 {
00054 ros::ServiceClient client = nh_.serviceClient<lama_interfaces::AddInterface>("interface_factory");
00055 while (ros::ok() && !client.waitForExistence(ros::Duration(5.0)))
00056 {
00057 ROS_WARN("Waiting for service /interface_factory");
00058 }
00059 lama_interfaces::AddInterface srv;
00060 srv.request.interface_name = crossing_interface_name_;
00061 srv.request.interface_type = lama_interfaces::AddInterfaceRequest::SERIALIZED;
00062 srv.request.get_service_message = "lama_msgs/GetCrossing";
00063 srv.request.set_service_message = "lama_msgs/SetCrossing";
00064 if (!client.call(srv))
00065 {
00066 ROS_ERROR("Failed to create the LaMa interface %s", crossing_interface_name_.c_str());
00067 }
00068
00069 crossing_setter_ = nh_.serviceClient<lama_msgs::SetCrossing>(srv.response.set_service_name);
00070 }
00071
00074 void Jockey::getLiveData()
00075 {
00076 ros::Subscriber costmap_handler;
00077 costmap_handler = private_nh_.subscribe<nav_msgs::OccupancyGrid>("local_costmap", 1, &Jockey::handleMap, this);
00078
00079
00080
00081 ros::Duration(0.3).sleep();
00082 ros::spinOnce();
00083 ros::Rate r(100);
00084 while (ros::ok())
00085 {
00086 ros::spinOnce();
00087 if (data_received_)
00088 {
00089 data_received_ = false;
00090 break;
00091 }
00092 ROS_INFO_STREAM_THROTTLE(5, "Did not received any map on " << costmap_handler.getTopic());
00093 r.sleep();
00094 }
00095 }
00096
00099 void Jockey::handleMap(const nav_msgs::OccupancyGridConstPtr& msg)
00100 {
00101 map_ = *msg;
00102 profile_ = lama_common::costmapToPlaceProfile(map_);
00103 data_received_ = true;
00104 }
00105
00110
00111
00112
00113 void Jockey::onGetVertexDescriptor()
00114 {
00115 if (server_.isPreemptRequested() && !ros::ok())
00116 {
00117 ROS_INFO("%s: Preempted", jockey_name_.c_str());
00118
00119 server_.setPreempted();
00120 return;
00121 }
00122
00123 getLiveData();
00124
00125
00126 lama_msgs::SetPlaceProfile profile_setter_srv;
00127 profile_setter_srv.request.descriptor = profile_;
00128 if (!place_profile_setter_.call(profile_setter_srv))
00129 {
00130 ROS_ERROR("Failed to add PlaceProfile to the map");
00131 server_.setAborted();
00132 return;
00133 }
00134 ROS_DEBUG("Added PlaceProfile with id %d to the map", profile_setter_srv.response.id);
00135 result_.descriptor_links.push_back(placeProfileDescriptorLink(profile_setter_srv.response.id));
00136
00137
00138 lama_msgs::SetCrossing crossing_setter_srv;
00139 lama_msgs::Crossing crossing;
00140 if (range_cutoff_set_)
00141 {
00142 crossing = crossing_detector_.crossingDescriptor(map_, range_cutoff_);
00143 }
00144 else
00145 {
00146 crossing = crossing_detector_.crossingDescriptor(map_);
00147 }
00148 crossing_setter_srv.request.descriptor = crossing;
00149 if (!crossing_setter_.call(crossing_setter_srv))
00150 {
00151 ROS_DEBUG("Failed to add Crossing to the map");
00152 server_.setAborted();
00153 return;
00154 }
00155 ROS_DEBUG("Added Crossing with id %d to the map", crossing_setter_srv.response.id);
00156 result_.descriptor_links.push_back(crossingDescriptorLink(crossing_setter_srv.response.id));
00157
00158 result_.state = lama_jockeys::LocalizeResult::DONE;
00159 result_.completion_time = getCompletionDuration();
00160 server_.setSucceeded(result_);
00161 }
00162
00165 void Jockey::onLocalizeInVertex()
00166 {
00167 getLiveData();
00168
00169
00170 if (goal_.descriptor_link.interface_name != place_profile_interface_name_)
00171 {
00172 ROS_ERROR_STREAM("Expected a descriptor_link with interface " <<
00173 place_profile_interface_name_ << " got " <<
00174 goal_.descriptor_link.interface_name);
00175 server_.setAborted();
00176 return;
00177 }
00178 lama_msgs::GetPlaceProfile profile_srv;
00179 profile_srv.request.id = goal_.descriptor_link.descriptor_id;
00180 if (!place_profile_getter_.call(profile_srv))
00181 {
00182 ROS_ERROR_STREAM(jockey_name_ << ": failed to call service \"" <<
00183 place_profile_interface_name_ << "\"");
00184 server_.setAborted();
00185 return;
00186 }
00187
00188
00189 ros::ServiceClient localize_client;
00190 localize_client = nh_.serviceClient<place_matcher_msgs::PolygonDissimilarity>(localize_service_);
00191 while (ros::ok() && !localize_client.waitForExistence(ros::Duration(5.0)))
00192 {
00193 ROS_WARN_STREAM("Waiting for service " << localize_client.getService());
00194 }
00195
00196
00197 result_.idata.clear();
00198 result_.fdata.clear();
00199 result_.fdata.reserve(7);
00200 place_matcher_msgs::PolygonDissimilarity dissimi_srv;
00201 dissimi_srv.request.polygon1 = profile_srv.response.descriptor.polygon;
00202 dissimi_srv.request.polygon2 = profile_.polygon;
00203 if (!localize_client.call(dissimi_srv))
00204 {
00205 ROS_ERROR_STREAM(jockey_name_ << ": failed to call service \"" <<
00206 localize_client.getService() << "\"");
00207 server_.setAborted();
00208 return;
00209 }
00210 result_.fdata.push_back(dissimi_srv.response.pose.position.x);
00211 result_.fdata.push_back(dissimi_srv.response.pose.position.y);
00212 result_.fdata.push_back(dissimi_srv.response.pose.position.z);
00213 result_.fdata.push_back(dissimi_srv.response.pose.orientation.x);
00214 result_.fdata.push_back(dissimi_srv.response.pose.orientation.y);
00215 result_.fdata.push_back(dissimi_srv.response.pose.orientation.z);
00216 result_.fdata.push_back(dissimi_srv.response.pose.orientation.w);
00217
00218 result_.state = lama_jockeys::LocalizeResult::DONE;
00219 result_.completion_time = getCompletionDuration();
00220 server_.setSucceeded(result_);
00221 }
00222
00223 void Jockey::onGetDissimilarity()
00224 {
00225 getLiveData();
00226
00227
00228 ros::ServiceClient dissimilarity_client;
00229 dissimilarity_client = nh_.serviceClient<place_matcher_msgs::PolygonDissimilarity>(dissimilarity_server_name_);
00230 while (ros::ok() && !dissimilarity_client.waitForExistence(ros::Duration(5.0)))
00231 {
00232 ROS_WARN_STREAM("Waiting for service " << dissimilarity_client.getService());
00233 }
00234
00235
00236 lama_interfaces::ActOnMap srv;
00237 srv.request.action = lama_interfaces::ActOnMapRequest::GET_VERTEX_LIST;
00238 if (!map_agent_.call(srv))
00239 {
00240 ROS_ERROR_STREAM("Failed to call map agent \"" << map_agent_.getService() << "\"");
00241 server_.setAborted();
00242 return;
00243 }
00244
00245
00246 std::vector<int32_t> vertices;
00247 vertices.reserve(srv.response.objects.size());
00248 std::vector<geometry_msgs::Polygon> polygons;
00249 polygons.reserve(srv.response.objects.size());
00250 for (size_t i = 0; i < srv.response.objects.size(); ++i)
00251 {
00252
00253 lama_interfaces::ActOnMap desc_srv;
00254 desc_srv.request.action = lama_interfaces::ActOnMapRequest::GET_DESCRIPTOR_LINKS;
00255 desc_srv.request.object.id = srv.response.objects[i].id;
00256 desc_srv.request.interface_name = place_profile_interface_name_;
00257 if (!map_agent_.call(desc_srv))
00258 {
00259 ROS_ERROR_STREAM("Failed to call map agent \"" << map_agent_.getService() << "\"");
00260 server_.setAborted();
00261 return;
00262 }
00263 if (desc_srv.response.descriptor_links.empty())
00264 {
00265 continue;
00266 }
00267 if (desc_srv.response.descriptor_links.size() > 1)
00268 {
00269 ROS_WARN_STREAM("More than one descriptor with interface " <<
00270 place_profile_interface_name_ << " for vertex " <<
00271 desc_srv.request.object.id << ", taking the first one");
00272 }
00273
00274 lama_msgs::GetPlaceProfile profile_srv;
00275 profile_srv.request.id = desc_srv.response.descriptor_links[0].descriptor_id;
00276 if (!place_profile_getter_.call(profile_srv))
00277 {
00278 ROS_ERROR_STREAM(jockey_name_ << ": failed to call service \"" <<
00279 place_profile_interface_name_ << "\"");
00280 server_.setAborted();
00281 return;
00282 }
00283 vertices.push_back(desc_srv.request.object.id);
00284 polygons.push_back(profile_srv.response.descriptor.polygon);
00285 }
00286
00287
00288 place_matcher_msgs::PolygonDissimilarity dissimi_srv;
00289 dissimi_srv.request.polygon1 = profile_.polygon;
00290 result_.idata.clear();
00291 result_.fdata.clear();
00292 result_.idata.reserve(vertices.size());
00293 result_.fdata.reserve(vertices.size());
00294 for (size_t i = 0; i < vertices.size(); ++i)
00295 {
00296 dissimi_srv.request.polygon2 = polygons[i];
00297 if (!dissimilarity_client.call(dissimi_srv))
00298 {
00299 ROS_ERROR_STREAM(jockey_name_ << ": failed to call service \"" <<
00300 dissimilarity_client.getService() << "\"");
00301 server_.setAborted();
00302 return;
00303 }
00304 result_.idata.push_back(vertices[i]);
00305 result_.fdata.push_back(dissimi_srv.response.raw_dissimilarity);
00306 }
00307
00308 ROS_INFO_STREAM(jockey_name_ << ": computed " << result_.idata.size() << " dissimilarities");
00309 result_.state = lama_jockeys::LocalizeResult::DONE;
00310 result_.completion_time = getCompletionDuration();
00311 server_.setSucceeded(result_);
00312 }
00313
00316 lama_msgs::DescriptorLink Jockey::placeProfileDescriptorLink(int32_t id)
00317 {
00318 lama_msgs::DescriptorLink descriptor_link;
00319 descriptor_link.descriptor_id = id;
00320 descriptor_link.interface_name = place_profile_interface_name_;
00321 return descriptor_link;
00322 }
00323
00326 lama_msgs::DescriptorLink Jockey::crossingDescriptorLink(int32_t id)
00327 {
00328 lama_msgs::DescriptorLink descriptor_link;
00329 descriptor_link.descriptor_id = id;
00330 descriptor_link.interface_name = crossing_interface_name_;
00331 return descriptor_link;
00332 }
00333
00334 }