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
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
00055 std::vector<std::string> rtt_uri_tokens;
00056 boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00057
00058
00059 if(rtt_uri_tokens.size() < 1) {
00060 return NULL;
00061 }
00062
00063
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
00077 return required->getOperationCaller(rtt_uri_tokens.back());
00078 }
00079
00081 RTT::OperationInterfacePart* get_owner_operation(const std::string rtt_uri)
00082 {
00083
00084 std::vector<std::string> rtt_uri_tokens;
00085 boost::split(rtt_uri_tokens, rtt_uri, boost::is_any_of("."));
00086
00087
00088 if(rtt_uri_tokens.size() < 1) {
00089 return NULL;
00090 }
00091
00092
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
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
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
00124 RTT::base::OperationCallerBaseInvoker*
00125 operation_caller = this->get_owner_operation_caller(rtt_operation_name);
00126
00127 if(operation_caller) {
00128
00129 if(client_proxies_.find(ros_service_name) == client_proxies_.end()) {
00130
00131 client_proxies_[ros_service_name] =
00132 get_service_factory(ros_service_type)->create_client_proxy(ros_service_name);
00133 }
00134
00135
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
00144 RTT::OperationInterfacePart*
00145 operation = this->get_owner_operation(rtt_operation_name);
00146
00147 if(operation) {
00148
00149 if(server_proxies_.find(ros_service_name) == server_proxies_.end()) {
00150
00151 server_proxies_[ros_service_name] =
00152 get_service_factory(ros_service_type)->create_server_proxy(ros_service_name);
00153 }
00154
00155
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
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
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")