def call_service(service_name, service_args): """ Call a service. Mostly extracted from rosservice. """ service_class = rosservice.get_service_class_by_name(service_name) request = service_class._request_class() try: now = rospy.get_rostime() keys = {'now': now, 'auto': std_msgs.msg.Header(stamp=now)} genpy.message.fill_message_args(request, service_args, keys=keys) except genpy.MessageException as e: def argsummary(args): if type(args) in [tuple, list]: return '\n'.join( [' * %s (type %s)' % (a, type(a).__name__) for a in args]) else: return ' * %s (type %s)' % (args, type(args).__name__) raise rosservice.ROSServiceException( "Incompatible arguments to call service:\n%s\n" + "Provided arguments are:\n%s\n\n" + "Service arguments are: [%s]" % (e, argsummary(service_args), genpy.message.get_printable_message_args(request))) try: return request, rospy.ServiceProxy(service_name, service_class)(request) except rospy.ServiceException as e: raise rosservice.ROSServiceException(str(e)) except genpy.SerializationError as e: raise rosservice.ROSServiceException( "Unable to send request. One of the fields has an incorrect type:\n" + " %s\n\nsrv file:\n%s" % (e, rosmsg.get_srv_text(service_class._type))) except rospy.ROSSerializationException as e: raise rosservice.ROSServiceException( "Unable to send request. One of the fields has an incorrect type:\n" + " %s\n\nsrv file:\n%s" % (e, rosmsg.get_srv_text(service_class._type)))
def get_service_class(self, allow_get_type=False): ''' Get the service class using the type of the service. NOTE: this method is from `rosservice` and changed to avoid a probe call to the service. :param allow_get_type: allow to connect to service and get the type if the type is not valid (in case of other host) :type allow_get_type: bool :return: service class :rtype: ServiceDefinition: service class :raise: ``ROSServiceException``, if service class cannot be retrieved ''' if self.__service_class is not None: return self.__service_class srv_type = self.type # request the type if it is empty and allowed if not srv_type and allow_get_type and self.uri: dest_addr = dest_port = None try: dest_addr, dest_port = rospy.parse_rosrpc_uri(self.uri) except: pass else: import socket import cStringIO s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # connect to service and probe it to get the headers s.settimeout(0.5) s.connect((dest_addr, dest_port)) header = { 'probe': '1', 'md5sum': '*', 'callerid': rospy.get_name(), 'service': self.name } roslib.network.write_ros_handshake_header(s, header) srv_type = roslib.network.read_ros_handshake_header( s, cStringIO.StringIO(), 2048) srv_type = srv_type['type'] except socket.error: pass except: pass finally: if s is not None: s.close() import rosservice if not srv_type: raise rosservice.ROSServiceException( "Not valid type of service [%s]." % str(srv_type)) # get the Service class so we can populate the request service_class = roslib.message.get_service_class(srv_type) # #1083: roscpp services are currently returning the wrong type if service_class and self.type.endswith('Request') and \ not hasattr(service_class, "_request_class"): srv_type = srv_type[:-7] service_class = roslib.message.get_service_class(srv_type) if service_class is None: pkg = roslib.names.resource_name_package(self.type) raise rosservice.ROSServiceException( "Unable to load type [%s].\n" % self.type + "Have you typed 'make' in [%s]?" % pkg) self.__service_class = service_class return service_class