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 
00035     // Get the global ros service registry
00036     rosservice_registry_ = ROSServiceRegistryService::Instance();
00037     has_service_factory = rosservice_registry_->getOperation("hasServiceFactory");
00038     get_service_factory = rosservice_registry_->getOperation("getServiceFactory");
00039   }
00040 
00042   RTT::base::OperationCallerBaseInvoker* get_owner_operation_caller(const std::string rtt_uri)
00043   {
00044     // Split up the service uri
00045     std::vector<std::string> rtt_uri_tokens;
00046     boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00047 
00048     // Make sure the uri has at least one token
00049     if(rtt_uri_tokens.size() < 1) {
00050       return NULL;
00051     }
00052 
00053     // Iterate through the tokens except for the last one (the operation name)
00054     boost::shared_ptr<RTT::ServiceRequester> required = this->getOwner()->requires();
00055     for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
00056         it+1 != rtt_uri_tokens.end();
00057         ++it)
00058     {
00059       if(required->requiresService(*it)) {
00060         required = required->requires(*it);
00061       } else {
00062         return NULL;
00063       }
00064     }
00065 
00066     // Get the operation caller
00067     return required->getOperationCaller(rtt_uri_tokens.back());
00068   }
00069 
00071   RTT::OperationInterfacePart* get_owner_operation(const std::string rtt_uri)
00072   {
00073     // Split up the service uri
00074     std::vector<std::string> rtt_uri_tokens;
00075     boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00076 
00077     // Make sure the uri has at least one token
00078     if(rtt_uri_tokens.size() < 1) {
00079       return NULL;
00080     }
00081 
00082     // Iterate through the tokens except for the last one (the operation name)
00083     RTT::Service::shared_ptr provided = this->getOwner()->provides();
00084     for(std::vector<std::string>::iterator it = rtt_uri_tokens.begin();
00085         it+1 != rtt_uri_tokens.end();
00086         ++it)
00087     {
00088       if(provided->hasService(*it)) {
00089         provided = provided->provides(*it);
00090       } else {
00091         return NULL;
00092       }
00093     }
00094 
00095     // Get the operation 
00096     return provided->getOperation(rtt_uri_tokens.back());
00097   }
00098 
00102   bool connect(
00103     const std::string &rtt_operation_name,
00104     const std::string &ros_service_name,
00105     const std::string &ros_service_type)
00106   {
00107     // Make sure the factory for this service type exists
00108     if(!this->has_service_factory(ros_service_type)) {
00109       RTT::log(RTT::Error) << "Unknown service type '" << ros_service_type << "'" << RTT::endlog();
00110       return false;
00111     }
00112 
00113     // Check if the operation is required by the owner
00114     RTT::base::OperationCallerBaseInvoker* 
00115       operation_caller = this->get_owner_operation_caller(rtt_operation_name);
00116 
00117     if(operation_caller) {
00118       // Check if the client proxy already exists
00119       if(client_proxies_.find(ros_service_name) == client_proxies_.end()) {
00120         // Create a new client proxy
00121         client_proxies_[ros_service_name] =
00122           get_service_factory(ros_service_type)->create_client_proxy(ros_service_name);
00123       }
00124 
00125       // Associate an RTT operation caller with a ROS service client
00126       if (!client_proxies_[ros_service_name]->connect(this->getOwner(), operation_caller)) {
00127         RTT::log(RTT::Error) << "Could not connect OperationCaller '" << rtt_operation_name << "' to ROS service client '" << ros_service_name << "'" << RTT::endlog();
00128         return false;
00129       }
00130       return true;
00131     }
00132     
00133     // Check if the operation is provided by the owner
00134     RTT::OperationInterfacePart*
00135       operation = this->get_owner_operation(rtt_operation_name);
00136     
00137     if(operation) {
00138       // Check if the server proxy already exists
00139       if(server_proxies_.find(ros_service_name) == server_proxies_.end()) {
00140         // Create a new server proxy
00141         server_proxies_[ros_service_name] =
00142           get_service_factory(ros_service_type)->create_server_proxy(ros_service_name);
00143       }
00144 
00145       // Associate an RTT operation with a ROS service server 
00146       if (!server_proxies_[ros_service_name]->connect(this->getOwner(), operation)) {
00147         RTT::log(RTT::Error) << "Could not connect Operation '" << rtt_operation_name << "' to ROS service server '" << ros_service_name << "'" << RTT::endlog();
00148         return false;
00149       }
00150       return true;
00151     }
00152 
00153     RTT::log(RTT::Error) << "No such Operation or OperationCaller '" << rtt_operation_name << "' in '" << getOwner()->getName() << "'" << RTT::endlog();
00154     return false;
00155   }
00156 
00157   RTT::Service::shared_ptr rosservice_registry_;
00158   RTT::OperationCaller<bool(const std::string&)> has_service_factory;
00159   RTT::OperationCaller<ROSServiceProxyFactoryBase*(const std::string&)> get_service_factory;
00160 
00161   std::map<std::string, ROSServiceServerProxyBase*> server_proxies_;
00162   std::map<std::string, ROSServiceClientProxyBase*> client_proxies_;
00163 };
00164 
00165 ORO_SERVICE_NAMED_PLUGIN(ROSServiceService, "rosservice")


rtt_roscomm
Author(s): Ruben Smits, Jonathan Bohren
autogenerated on Wed Sep 16 2015 06:58:09