rtt_rosservice_service.cpp
Go to the documentation of this file.
00001 #include <boost/algorithm/string.hpp>
00002 
00003 #include <rtt/RTT.hpp>
00004 #include <rtt/plugin/ServicePlugin.hpp>
00005 
00006 #include <rtt_roscomm/rtt_rosservice_registry_service.h>
00007 #include <rtt_roscomm/rtt_rosservice_proxy.h>
00008 
00009 using namespace RTT;
00010 using namespace std;
00011 
00015 class ROSServiceService : public RTT::Service 
00016 {
00017 public:
00022   ROSServiceService(TaskContext* owner) 
00023     : Service("rosservice", owner)
00024   {
00025     if(owner) {
00026       this->doc("RTT Service for connecting the operations of "+owner->getName()+" to ROS service clients and servers.");
00027     }
00028 
00029     this->addOperation("connect", &ROSServiceService::connect, this)
00030       .doc( "Connects an RTT operation or operation caller to an associated ROS service server or client.")
00031       .arg( "operation_name", "The RTT operation name (like \"some_provided_service.another.operation\").")
00032       .arg( "service_name", "The ROS service name (like \"/my_robot/ns/some_service\").")
00033       .arg( "service_type", "The ROS service type (like \"std_srvs/Empty\").");
00034     this->addOperation("disconnect", &ROSServiceService::disconnect, this)
00035       .doc( "Disconnects an RTT operation or operation caller from an associated ROS service server or client.")
00036       .arg( "service_name", "The ROS service name (like \"/my_robot/ns/some_service\").");
00037     this->addOperation("disconnectAll", &ROSServiceService::disconnectAll, this)
00038       .doc( "Disconnects all RTT operations and operation callers from associated ROS service servers or clients.");
00039 
00040     // Get the global ros service registry
00041     rosservice_registry_ = ROSServiceRegistryService::Instance();
00042     has_service_factory = rosservice_registry_->getOperation("hasServiceFactory");
00043     get_service_factory = rosservice_registry_->getOperation("getServiceFactory");
00044   }
00045 
00046   ~ROSServiceService()
00047   {
00048     disconnectAll();
00049   }
00050 
00052   RTT::base::OperationCallerBaseInvoker* get_owner_operation_caller(const std::string rtt_uri)
00053   {
00054     // Split up the service uri
00055     std::vector<std::string> rtt_uri_tokens;
00056     boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00057 
00058     // Make sure the uri has at least one token
00059     if(rtt_uri_tokens.size() < 1) {
00060       return NULL;
00061     }
00062 
00063     // Iterate through the tokens except for the last one (the operation name)
00064     boost::shared_ptr<RTT::ServiceRequester> required = this->getOwner()->requires();
00065     for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
00066         it+1 != rtt_uri_tokens.end();
00067         ++it)
00068     {
00069       if(required->requiresService(*it)) {
00070         required = required->requires(*it);
00071       } else {
00072         return NULL;
00073       }
00074     }
00075 
00076     // Get the operation caller
00077     return required->getOperationCaller(rtt_uri_tokens.back());
00078   }
00079 
00081   RTT::OperationInterfacePart* get_owner_operation(const std::string rtt_uri)
00082   {
00083     // Split up the service uri
00084     std::vector<std::string> rtt_uri_tokens;
00085     boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00086 
00087     // Make sure the uri has at least one token
00088     if(rtt_uri_tokens.size() < 1) {
00089       return NULL;
00090     }
00091 
00092     // Iterate through the tokens except for the last one (the operation name)
00093     RTT::Service::shared_ptr provided = this->getOwner()->provides();
00094     for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
00095         it+1 != rtt_uri_tokens.end();
00096         ++it)
00097     {
00098       if(provided->hasService(*it)) {
00099         provided = provided->provides(*it);
00100       } else {
00101         return NULL;
00102       }
00103     }
00104 
00105     // Get the operation 
00106     return provided->getOperation(rtt_uri_tokens.back());
00107   }
00108 
00112   bool connect(
00113     const std::string &rtt_operation_name,
00114     const std::string &ros_service_name,
00115     const std::string &ros_service_type)
00116   {
00117     // Make sure the factory for this service type exists
00118     if(!this->has_service_factory(ros_service_type)) {
00119       RTT::log(RTT::Error) << "Unknown service type '" << ros_service_type << "'" << RTT::endlog();
00120       return false;
00121     }
00122 
00123     // Check if the operation is required by the owner
00124     RTT::base::OperationCallerBaseInvoker* 
00125       operation_caller = this->get_owner_operation_caller(rtt_operation_name);
00126 
00127     if(operation_caller) {
00128       // Check if the client proxy already exists
00129       if(client_proxies_.find(ros_service_name) == client_proxies_.end()) {
00130         // Create a new client proxy
00131         client_proxies_[ros_service_name] =
00132           get_service_factory(ros_service_type)->create_client_proxy(ros_service_name);
00133       }
00134 
00135       // Associate an RTT operation caller with a ROS service client
00136       if (!client_proxies_[ros_service_name]->connect(this->getOwner(), operation_caller)) {
00137         RTT::log(RTT::Error) << "Could not connect OperationCaller '" << rtt_operation_name << "' to ROS service client '" << ros_service_name << "'" << RTT::endlog();
00138         return false;
00139       }
00140       return true;
00141     }
00142     
00143     // Check if the operation is provided by the owner
00144     RTT::OperationInterfacePart*
00145       operation = this->get_owner_operation(rtt_operation_name);
00146     
00147     if(operation) {
00148       // Check if the server proxy already exists
00149       if(server_proxies_.find(ros_service_name) == server_proxies_.end()) {
00150         // Create a new server proxy
00151         server_proxies_[ros_service_name] =
00152           get_service_factory(ros_service_type)->create_server_proxy(ros_service_name);
00153       }
00154 
00155       // Associate an RTT operation with a ROS service server 
00156       if (!server_proxies_[ros_service_name]->connect(this->getOwner(), operation)) {
00157         RTT::log(RTT::Error) << "Could not connect Operation '" << rtt_operation_name << "' to ROS service server '" << ros_service_name << "'" << RTT::endlog();
00158         return false;
00159       }
00160       return true;
00161     }
00162 
00163     RTT::log(RTT::Error) << "No such Operation or OperationCaller '" << rtt_operation_name << "' in '" << getOwner()->getName() << "'" << RTT::endlog();
00164     return false;
00165   }
00166 
00167   bool disconnect(const std::string &ros_service_name)
00168   {
00169     bool found = false;
00170 
00171     // Cleanup ROS service or client named ros_service_name
00172     std::map<std::string, ROSServiceServerProxyBase*>::iterator iter_s
00173         = server_proxies_.find(ros_service_name);
00174     if (iter_s != server_proxies_.end()) {
00175       delete iter_s->second;
00176       server_proxies_.erase(iter_s);
00177       found = true;
00178     }
00179 
00180     std::map<std::string, ROSServiceClientProxyBase*>::iterator iter_c
00181         = client_proxies_.find(ros_service_name);
00182     if (iter_c != client_proxies_.end())
00183     {
00184       delete iter_c->second;
00185       client_proxies_.erase(iter_c);
00186       found = true;
00187     }
00188 
00189     return found;
00190   }
00191 
00192   void disconnectAll()
00193   {
00194     // Cleanup registered ROS services and clients
00195     std::map<std::string, ROSServiceServerProxyBase*>::iterator iter_s;
00196     for(iter_s = server_proxies_.begin(); iter_s != server_proxies_.end(); iter_s = server_proxies_.begin())
00197     {
00198       delete iter_s->second;
00199       server_proxies_.erase(iter_s);
00200     }
00201 
00202     std::map<std::string, ROSServiceClientProxyBase*>::iterator iter_c;
00203     for(iter_c = client_proxies_.begin(); iter_c != client_proxies_.end(); iter_c = client_proxies_.begin())
00204     {
00205       delete iter_c->second;
00206       client_proxies_.erase(iter_c);
00207     }
00208   }
00209 
00210   RTT::Service::shared_ptr rosservice_registry_;
00211   RTT::OperationCaller<bool(const std::string&)> has_service_factory;
00212   RTT::OperationCaller<ROSServiceProxyFactoryBase*(const std::string&)> get_service_factory;
00213 
00214   std::map<std::string, ROSServiceServerProxyBase*> server_proxies_;
00215   std::map<std::string, ROSServiceClientProxyBase*> client_proxies_;
00216 };
00217 
00218 ORO_SERVICE_NAMED_PLUGIN(ROSServiceService, "rosservice")


rtt_roscomm
Author(s): Ruben Smits, Jonathan Bohren
autogenerated on Mon Apr 3 2017 03:34:43