rtt_rosservice_service.cpp
Go to the documentation of this file.
1 #include <boost/algorithm/string.hpp>
2 
3 #include <rtt/RTT.hpp>
5 
8 
9 using namespace RTT;
10 using namespace std;
11 
16 {
17 public:
23  : Service("rosservice", owner)
24  {
25  if(owner) {
26  this->doc("RTT Service for connecting the operations of "+owner->getName()+" to ROS service clients and servers.");
27  }
28 
29  this->addOperation("connect", &ROSServiceService::connect, this)
30  .doc( "Connects an RTT operation or operation caller to an associated ROS service server or client.")
31  .arg( "operation_name", "The RTT operation name (like \"some_provided_service.another.operation\").")
32  .arg( "service_name", "The ROS service name (like \"/my_robot/ns/some_service\").")
33  .arg( "service_type", "The ROS service type (like \"std_srvs/Empty\").");
34  this->addOperation("disconnect", &ROSServiceService::disconnect, this)
35  .doc( "Disconnects an RTT operation or operation caller from an associated ROS service server or client.")
36  .arg( "service_name", "The ROS service name (like \"/my_robot/ns/some_service\").");
37  this->addOperation("disconnectAll", &ROSServiceService::disconnectAll, this)
38  .doc( "Disconnects all RTT operations and operation callers from associated ROS service servers or clients.");
39 
40  // Get the global ros service registry
41  rosservice_registry_ = ROSServiceRegistryService::Instance();
42  has_service_factory = rosservice_registry_->getOperation("hasServiceFactory");
43  get_service_factory = rosservice_registry_->getOperation("getServiceFactory");
44  }
45 
47  {
48  disconnectAll();
49  }
50 
53  {
54  // Split up the service uri
55  std::vector<std::string> rtt_uri_tokens;
56  boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
57 
58  // Make sure the uri has at least one token
59  if(rtt_uri_tokens.size() < 1) {
60  return NULL;
61  }
62 
63  // Iterate through the tokens except for the last one (the operation name)
64  boost::shared_ptr<RTT::ServiceRequester> required = this->getOwner()->requires();
65  for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
66  it+1 != rtt_uri_tokens.end();
67  ++it)
68  {
69  if(required->requiresService(*it)) {
70  required = required->requires(*it);
71  } else {
72  return NULL;
73  }
74  }
75 
76  // Get the operation caller
77  return required->getOperationCaller(rtt_uri_tokens.back());
78  }
79 
82  {
83  // Split up the service uri
84  std::vector<std::string> rtt_uri_tokens;
85  boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
86 
87  // Make sure the uri has at least one token
88  if(rtt_uri_tokens.size() < 1) {
89  return NULL;
90  }
91 
92  // Iterate through the tokens except for the last one (the operation name)
93  RTT::Service::shared_ptr provided = this->getOwner()->provides();
94  for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
95  it+1 != rtt_uri_tokens.end();
96  ++it)
97  {
98  if(provided->hasService(*it)) {
99  provided = provided->provides(*it);
100  } else {
101  return NULL;
102  }
103  }
104 
105  // Get the operation
106  return provided->getOperation(rtt_uri_tokens.back());
107  }
108 
112  bool connect(
113  const std::string &rtt_operation_name,
114  const std::string &ros_service_name,
115  const std::string &ros_service_type)
116  {
117  // Make sure the factory for this service type exists
118  if(!this->has_service_factory(ros_service_type)) {
119  RTT::log(RTT::Error) << "Unknown service type '" << ros_service_type << "'" << RTT::endlog();
120  return false;
121  }
122 
123  // Check if the operation is required by the owner
125  operation_caller = this->get_owner_operation_caller(rtt_operation_name);
126 
127  if(operation_caller) {
128  // Check if the client proxy already exists
129  if(client_proxies_.find(ros_service_name) == client_proxies_.end()) {
130  // Create a new client proxy
131  client_proxies_[ros_service_name] =
132  get_service_factory(ros_service_type)->create_client_proxy(ros_service_name);
133  }
134 
135  // Associate an RTT operation caller with a ROS service client
136  if (!client_proxies_[ros_service_name]->connect(this->getOwner(), operation_caller)) {
137  RTT::log(RTT::Error) << "Could not connect OperationCaller '" << rtt_operation_name << "' to ROS service client '" << ros_service_name << "'" << RTT::endlog();
138  return false;
139  }
140  return true;
141  }
142 
143  // Check if the operation is provided by the owner
145  operation = this->get_owner_operation(rtt_operation_name);
146 
147  if(operation) {
148  // Check if the server proxy already exists
149  if(server_proxies_.find(ros_service_name) == server_proxies_.end()) {
150  // Create a new server proxy
151  server_proxies_[ros_service_name] =
152  get_service_factory(ros_service_type)->create_server_proxy(ros_service_name);
153  }
154 
155  // Associate an RTT operation with a ROS service server
156  if (!server_proxies_[ros_service_name]->connect(this->getOwner(), operation)) {
157  RTT::log(RTT::Error) << "Could not connect Operation '" << rtt_operation_name << "' to ROS service server '" << ros_service_name << "'" << RTT::endlog();
158  return false;
159  }
160  return true;
161  }
162 
163  RTT::log(RTT::Error) << "No such Operation or OperationCaller '" << rtt_operation_name << "' in '" << getOwner()->getName() << "'" << RTT::endlog();
164  return false;
165  }
166 
167  bool disconnect(const std::string &ros_service_name)
168  {
169  bool found = false;
170 
171  // Cleanup ROS service or client named ros_service_name
172  std::map<std::string, ROSServiceServerProxyBase*>::iterator iter_s
173  = server_proxies_.find(ros_service_name);
174  if (iter_s != server_proxies_.end()) {
175  delete iter_s->second;
176  server_proxies_.erase(iter_s);
177  found = true;
178  }
179 
180  std::map<std::string, ROSServiceClientProxyBase*>::iterator iter_c
181  = client_proxies_.find(ros_service_name);
182  if (iter_c != client_proxies_.end())
183  {
184  delete iter_c->second;
185  client_proxies_.erase(iter_c);
186  found = true;
187  }
188 
189  return found;
190  }
191 
193  {
194  // Cleanup registered ROS services and clients
195  std::map<std::string, ROSServiceServerProxyBase*>::iterator iter_s;
196  for(iter_s = server_proxies_.begin(); iter_s != server_proxies_.end(); iter_s = server_proxies_.begin())
197  {
198  delete iter_s->second;
199  server_proxies_.erase(iter_s);
200  }
201 
202  std::map<std::string, ROSServiceClientProxyBase*>::iterator iter_c;
203  for(iter_c = client_proxies_.begin(); iter_c != client_proxies_.end(); iter_c = client_proxies_.begin())
204  {
205  delete iter_c->second;
206  client_proxies_.erase(iter_c);
207  }
208  }
209 
213 
214  std::map<std::string, ROSServiceServerProxyBase*> server_proxies_;
215  std::map<std::string, ROSServiceClientProxyBase*> client_proxies_;
216 };
217 
std::map< std::string, ROSServiceServerProxyBase * > server_proxies_
RTT::Service::shared_ptr rosservice_registry_
#define ORO_SERVICE_NAMED_PLUGIN(SERVICE, NAME)
RTT::OperationInterfacePart * get_owner_operation(const std::string rtt_uri)
Get an RTT operation from a string identifier.
RTT::OperationCaller< ROSServiceProxyFactoryBase *(const std::string &)> get_service_factory
static ROSServiceRegistryServicePtr Instance()
RTT::OperationCaller< bool(const std::string &)> has_service_factory
const std::string & doc() const
ROSServiceService(TaskContext *owner)
bool connect(const std::string &rtt_operation_name, const std::string &ros_service_name, const std::string &ros_service_type)
Connect an RTT operation or operation caller to a ROS service server or service client.
std::map< std::string, ROSServiceClientProxyBase * > client_proxies_
RTT::base::OperationCallerBaseInvoker * get_owner_operation_caller(const std::string rtt_uri)
Get an RTT operation caller from a string identifier.
static Logger & log()
bool disconnect(const std::string &ros_service_name)
static Logger::LogFunction endlog()
virtual const std::string & getName() const


rtt_roscomm
Author(s): Ruben Smits, Jonathan Bohren
autogenerated on Mon May 10 2021 02:45:04