service_utils.cpp
Go to the documentation of this file.
1 #include <chrono>
2 #include <future>
3 
4 #include <ros/connection.h>
6 #include <ros/poll_manager.h>
7 #include <ros/service_manager.h>
8 #include <ros/this_node.h>
10 
12 
13 namespace foxglove_bridge {
14 
24 std::string retrieveServiceType(const std::string& serviceName, std::chrono::milliseconds timeout) {
25  std::string srvHost;
26  uint32_t srvPort;
27  if (!ros::ServiceManager::instance()->lookupService(serviceName, srvHost, srvPort)) {
28  throw std::runtime_error("Failed to lookup service " + serviceName);
29  }
30 
31  auto transport =
32  boost::make_shared<ros::TransportTCP>(&ros::PollManager::instance()->getPollSet());
33  auto connection = boost::make_shared<ros::Connection>();
34  ros::ConnectionManager::instance()->addConnection(connection);
35  connection->initialize(transport, false, ros::HeaderReceivedFunc());
36 
37  if (!transport->connect(srvHost, srvPort)) {
38  throw std::runtime_error("Failed to connect to service server of service " + serviceName);
39  }
40 
41  std::promise<std::string> promise;
42  auto future = promise.get_future();
43 
44  connection->setHeaderReceivedCallback(
45  [&promise](const ros::ConnectionPtr& conn, const ros::Header& header) {
46  std::string serviceType;
47  if (header.getValue("type", serviceType)) {
48  promise.set_value(serviceType);
49  } else {
50  promise.set_exception(std::make_exception_ptr(
51  std::runtime_error("Key 'type' not found in service connection header")));
52  }
53  // Close connection since we don't need it any more.
54  conn->drop(ros::Connection::DropReason::Destructing);
55  return true;
56  });
57 
59  header["service"] = serviceName;
60  header["md5sum"] = "*";
61  header["callerid"] = ros::this_node::getName();
62  header["persistent"] = "0";
63  header["probe"] = "1";
64  connection->writeHeader(header, [](const ros::ConnectionPtr&) {});
65 
66  if (future.wait_for(timeout) != std::future_status::ready) {
67  // Drop the connection here to prevent that the header-received callback is called after the
68  // promise has already been destroyed.
69  connection->drop(ros::Connection::DropReason::Destructing);
70  throw std::runtime_error("Timed out when retrieving service type");
71  }
72 
73  return future.get();
74 }
75 
76 } // namespace foxglove_bridge
boost::shared_ptr< Connection >
ros::Header
transport_tcp.h
connection_manager.h
ros::ServiceManager::instance
static const ServiceManagerPtr & instance()
foxglove_bridge::retrieveServiceType
std::string retrieveServiceType(const std::string &serviceName, std::chrono::milliseconds timeout_ms)
Definition: service_utils.cpp:24
service_manager.h
foxglove_bridge
Definition: generic_service.hpp:9
service_utils.hpp
ros::PollManager::instance
static const PollManagerPtr & instance()
poll_manager.h
ros::this_node::getName
const ROSCPP_DECL std::string & getName()
this_node.h
connection.h
ros::HeaderReceivedFunc
boost::function< bool(const ConnectionPtr &, const Header &)> HeaderReceivedFunc
ros::ConnectionManager::instance
static const ConnectionManagerPtr & instance()
header
const std::string header
ros::M_string
std::map< std::string, std::string > M_string


foxglove_bridge
Author(s): Foxglove
autogenerated on Tue May 20 2025 02:34:26