Esempio n. 1
0
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)))
Esempio n. 2
0
    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