jockey.cpp
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   // Initialize the clients for the getter and setter services (interface to map).
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   // Initialize the client for the setter service (interface to map).
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   /* Wait a bit to avoid the first throttled message. */
00080   // TODO: simplify with ROS_INFO_STREAM_DELAYED_THROTTLE, when available.
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 // TODO: Discuss with Karel the exact role of onGetVertexDescriptor
00111 // TODO: in particular: should it save something in the database? This jockey
00112 // is not a learning jockey.
00113 void Jockey::onGetVertexDescriptor()
00114 {
00115   if (server_.isPreemptRequested() && !ros::ok())
00116   {
00117     ROS_INFO("%s: Preempted", jockey_name_.c_str());
00118     // set the action state to preempted
00119     server_.setPreempted();
00120     return;
00121   }
00122 
00123   getLiveData();
00124 
00125   // Add the PlaceProfile to the descriptor list.
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   // Add the Crossing to the descriptor list.
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   // Get the requested PlaceProfile from database.
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   // Initialize the client for the localize_in_vertex service.
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   // Compare both polygons by calling the localize service.
00197   result_.idata.clear();
00198   result_.fdata.clear();
00199   result_.fdata.reserve(7);  // x, y, z, qx, qy, qz, qw.
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   // Initialize the client for the dissimilarity server.
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   // Get all PlaceProfile from database.
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   // Iterate over vertices and get the associated Polygon (from the PlaceProfile).
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     // Get all PlaceProfile descriptors associated with the current vertex.
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     // Get the first linked PlaceProfile.
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   // Compare them to the current polygon by calling one of the polygon_matcher service.
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 } // namespace lj_costmap


lj_costmap
Author(s): Gaƫl Ecorchard
autogenerated on Sat Jun 8 2019 20:58:41