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
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
00045 std::vector<std::string> rtt_uri_tokens;
00046 boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00047
00048
00049 if(rtt_uri_tokens.size() < 1) {
00050 return NULL;
00051 }
00052
00053
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
00067 return required->getOperationCaller(rtt_uri_tokens.back());
00068 }
00069
00071 RTT::OperationInterfacePart* get_owner_operation(const std::string rtt_uri)
00072 {
00073
00074 std::vector<std::string> rtt_uri_tokens;
00075 boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00076
00077
00078 if(rtt_uri_tokens.size() < 1) {
00079 return NULL;
00080 }
00081
00082
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
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
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
00114 RTT::base::OperationCallerBaseInvoker*
00115 operation_caller = this->get_owner_operation_caller(rtt_operation_name);
00116
00117 if(operation_caller) {
00118
00119 if(client_proxies_.find(ros_service_name) == client_proxies_.end()) {
00120
00121 client_proxies_[ros_service_name] =
00122 get_service_factory(ros_service_type)->create_client_proxy(ros_service_name);
00123 }
00124
00125
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
00134 RTT::OperationInterfacePart*
00135 operation = this->get_owner_operation(rtt_operation_name);
00136
00137 if(operation) {
00138
00139 if(server_proxies_.find(ros_service_name) == server_proxies_.end()) {
00140
00141 server_proxies_[ros_service_name] =
00142 get_service_factory(ros_service_type)->create_server_proxy(ros_service_name);
00143 }
00144
00145
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")