Package rosh :: Package impl :: Module service
[frames] | no frames]

Source Code for Module rosh.impl.service

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2010, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: service.py 13210 2011-02-14 01:05:08Z kwc $ 
 34   
 35  from __future__ import with_statement 
 36   
 37  import sys 
 38   
 39  import roslib.message 
 40   
 41  import rosgraph.masterapi 
 42  import rosmsg 
 43  import rosservice 
 44  import rospy 
 45   
 46  from rosh.impl.exceptions import ROSHException 
 47  from rosh.impl.namespace import Namespace, Concept 
 48   
49 -def Service(service_name, service_type, handler):
50 if type(service_name) == Namespace: 51 return rospy.Service(service_name._name, service_type, handler) 52 else: 53 return rospy.Service(service_name, service_type, handler)
54
55 -def get_service_class_by_service_name(service_name):
56 #TODO: this is technically a bug because it doesn't use the ctx's 57 #master handle 58 type_name = rosservice.get_service_type(service_name) 59 if type_name: 60 val = roslib.message.get_service_class(type_name, reload_on_error=True) 61 if not val: 62 pkg, base_type = roslib.names.package_resource_name(type_name) 63 print >> sys.stderr, """Cannot retrieve type [%s]. 64 Please type 'rosmake %s' 65 """%(type_name, pkg) 66 else: 67 return val
68
69 -class ServiceInfo(object):
70 - def __init__(self, name, node, uri):
71 self.name, self.node, self.uri = name, node, uri
72 - def __repr__(self):
73 return self.__str__()
74 - def __str__(self):
75 return "Name: %s\nNode: %s\nURI: %s"%(self.name, self.node, self.uri)
76 77
78 -def service_info(config, name):
79 master = config.ctx.master 80 try: 81 uri = master.lookupService(name) 82 except rosgraph.masterapi.Error: 83 return None 84 85 #TODO: convert rosservice to take in master handle 86 #can't use rosservice because it doesn't let us pass in master 87 #handle 88 _, _, srvs = master.getSystemState() 89 l = [nodelist for s, nodelist in srvs if s == name][0] 90 node_name = l[0] 91 node = config.ctx.nodes[node_name] 92 return ServiceInfo(name, node, uri)
93
94 -class ServiceNS(Namespace):
95
96 - def __init__(self, name, config):
97 """ 98 ctor. 99 @param config: Namespace configuration instance. Safe to set 100 to None if self._config is initialize proper to calling any 101 methods. 102 @type config: L{NamespaceConfig} 103 """ 104 super(ServiceNS, self).__init__(name, config) 105 self._type = self._service_info = None 106 self._init_type() 107 self._is_wait_for_service = True # per API review
108
109 - def _info(self):
110 """ 111 info() API 112 """ 113 if self._service_info is None: 114 self._service_info = service_info(self._config, self._name) 115 return self._service_info
116
117 - def _list(self):
118 """ 119 Override Namespace._list() 120 """ 121 # hide rosh services 122 return [s for s in rosservice.get_service_list(namespace=self._ns) if not s.startswith('/rosh_')]
123
124 - def _get_type(self):
125 "rostype() API" 126 return self._type
127
128 - def _set_type(self, type_):
129 "rostype() API" 130 self._init_type(type_)
131
132 - def _init_type(self, t=None):
133 if self._type is not None and t is None: 134 # already initialized 135 return 136 137 if t is None: 138 try: 139 self._type = get_service_class_by_service_name(self._name) 140 self._type_name = self._type._type 141 except: 142 # right now the contract of init_type is to 143 # soft-fail and require callers to check _type 144 # state 145 self._type = self._type_name = None 146 else: 147 if type(t) == str: 148 t = roslib.message.get_service_class(t) 149 if t is None: 150 raise ValueError("cannot load service type: %s"%(t)) 151 else: 152 if not type(t) == type: 153 raise ValueError("invalid service type: %s"%(type(t))) 154 if not issubclass(t, roslib.message.ServiceDefinition): 155 raise ValueError("invalid service type: %s"%(t.__class__.__name__)) 156 self._type = t 157 self._type_name = t._type
158
159 - def __repr__(self):
160 return self.__str__()
161
162 - def __str__(self):
163 if self._type is None: 164 self._init_type() 165 if self._type is None: 166 return self._ns 167 else: 168 return rosmsg.get_srv_text(self._type._type)
169
170 - def _props(self):
171 return ['wait_for_service']
172
173 - def _set_wait_for_service(self, val):
174 self._is_wait_for_service = val
175
176 - def __call__(self, *args, **kwds):
177 """ 178 Call service 179 """ 180 # lazy-init 181 if self._type is None: 182 self._init_type() 183 if self._type is None: 184 raise ROSHException("cannot call service [%s]: unknown type"%(self._ns)) 185 # TODO: cache ServiceProxy objects for faster creation 186 # TODO: optimize wait_for_service to use ctx.master for faster calling 187 if self._is_wait_for_service: 188 rospy.wait_for_service(self._ns) 189 request = self._type._request_class(*args, **kwds) 190 return rospy.ServiceProxy(self._ns, self._type)(request)
191
192 -class Services(Concept):
193
194 - def __init__(self, ctx, lock):
195 super(Services, self).__init__(ctx, lock, ServiceNS)
196