def callService(self, service_uri, service, type, *args, **kwds): ''' Calls the service and return the response. To call the service the ServiceProxy can't be used, because it uses environment variables to determine the URI of the running service. In our case this service can be running using another ROS master. The changes on the environment variables is not thread safe. So the source code of the rospy.SerivceProxy (tcpros_service.py) was modified. @param service_uri: the URI of the service @type service_uri: C{str} @param service: full service name (with name space) @type service: C{str} @param type: service class @type type: ServiceDefinition: service class @param args: arguments to remote service @param kwds: message keyword arguments @return: the tuple of request and response. @rtype: C{(request object, response object)} @raise StartException: on error @see: L{rospy.SerivceProxy} ''' from rospy.core import parse_rosrpc_uri, is_shutdown from rospy.msg import args_kwds_to_message from rospy.exceptions import TransportInitError, TransportException from rospy.impl.tcpros_base import TCPROSTransport, TCPROSTransportProtocol, DEFAULT_BUFF_SIZE from rospy.impl.tcpros_service import TCPROSServiceClient from rospy.service import ServiceException request = args_kwds_to_message(type._request_class, args, kwds) transport = None protocol = TCPROSServiceClient(service, type, headers={}) transport = TCPROSTransport(protocol, service) # initialize transport dest_addr, dest_port = parse_rosrpc_uri(service_uri) # connect to service transport.buff_size = DEFAULT_BUFF_SIZE try: transport.connect(dest_addr, dest_port, service_uri) except TransportInitError as e: # can be a connection or md5sum mismatch raise StartException("unable to connect to service: %s"%e) transport.send_message(request, 0) try: responses = transport.receive_once() if len(responses) == 0: raise StartException("service [%s] returned no response"%service) elif len(responses) > 1: raise StartException("service [%s] returned multiple responses: %s"%(service, len(responses))) except TransportException as e: # convert lower-level exception to exposed type if is_shutdown(): raise StartException("node shutdown interrupted service call") else: raise StartException("transport error completing service call: %s"%(str(e))) except ServiceException, e: raise StartException("Service error: %s"%(str(e)))
def test_parse_rosrpc_uri(self): from rospy.core import parse_rosrpc_uri valid = [('rosrpc://localhost:1234/', 'localhost', 1234), ('rosrpc://localhost2:1234', 'localhost2', 1234), ('rosrpc://third:1234/path/bar', 'third', 1234), ('rosrpc://foo.com:1/', 'foo.com', 1), ('rosrpc://foo.com:1/', 'foo.com', 1)] for t, addr, port in valid: paddr, pport = rospy.core.parse_rosrpc_uri(t) self.assertEquals(addr, paddr) self.assertEquals(port, pport) # validate that it's a top-level API method self.assertEquals(rospy.core.parse_rosrpc_uri(t), rospy.parse_rosrpc_uri(t)) invalid = ['rosrpc://:1234/', 'rosrpc://localhost', 'http://localhost:1234/'] for i in invalid: try: parse_rosrpc_uri(i) self.fail("%s was an invalid rosrpc uri"%i) except: pass
def callService(self, service_uri, service, service_type, service_args=[]): ''' Calls the service and return the response. To call the service the ServiceProxy can't be used, because it uses environment variables to determine the URI of the running service. In our case this service can be running using another ROS master. The changes on the environment variables is not thread safe. So the source code of the rospy.SerivceProxy (tcpros_service.py) was modified. :param str service_uri: the URI of the service :param str service: full service name (with name space) :param service_type: service class :type service_type: ServiceDefinition: service class :param service_args: arguments :return: the tuple of request and response. :rtype: (request object, response object) :raise StartException: on error :see: rospy.SerivceProxy<http://docs.ros.org/kinetic/api/rospy/html/rospy.impl.tcpros_service.ServiceProxy-class.html> ''' service = str(service) rospy.loginfo("Call service %s[%s]: %s, %s", utf8(service), utf8(service_uri), utf8(service_type), utf8(service_args)) from rospy.core import parse_rosrpc_uri, is_shutdown # from rospy.msg import args_kwds_to_message from rospy.exceptions import TransportInitError, TransportException from rospy.impl.tcpros_base import TCPROSTransport, DEFAULT_BUFF_SIZE # ,TCPROSTransportProtocol from rospy.impl.tcpros_service import TCPROSServiceClient from rospy.service import ServiceException request = service_type._request_class() import genpy try: now = rospy.get_rostime() import std_msgs.msg keys = {'now': now, 'auto': std_msgs.msg.Header(stamp=now)} genpy.message.fill_message_args(request, service_args, 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 StartException( "Incompatible arguments to call service:\n%s\nProvided arguments are:\n%s\n\nService arguments are: [%s]" % (e, argsummary(service_args), genpy.message.get_printable_message_args(request))) # request = args_kwds_to_message(type._request_class, args, kwds) protocol = TCPROSServiceClient(service, service_type, headers={}) transport = TCPROSTransport(protocol, service) # initialize transport dest_addr, dest_port = parse_rosrpc_uri(service_uri) # connect to service transport.buff_size = DEFAULT_BUFF_SIZE try: transport.connect(dest_addr, dest_port, service_uri, timeout=5) except TransportInitError as e: # can be a connection or md5sum mismatch raise StartException(''.join( ["unable to connect to service: ", utf8(e)])) transport.send_message(request, 0) try: responses = transport.receive_once() if len(responses) == 0: raise StartException("service [%s] returned no response" % service) elif len(responses) > 1: raise StartException( "service [%s] returned multiple responses: %s" % (service, len(responses))) except TransportException as e: # convert lower-level exception to exposed type if is_shutdown(): raise StartException("node shutdown interrupted service call") else: raise StartException( "transport error completing service call: %s" % (utf8(e))) except ServiceException as e: raise StartException("Service error: %s" % (utf8(e))) finally: transport.close() transport = None return request, responses[0] if len(responses) > 0 else None
def callService(self, service_uri, service, service_type, service_args=[]): ''' Calls the service and return the response. To call the service the ServiceProxy can't be used, because it uses environment variables to determine the URI of the running service. In our case this service can be running using another ROS master. The changes on the environment variables is not thread safe. So the source code of the rospy.SerivceProxy (tcpros_service.py) was modified. @param service_uri: the URI of the service @type service_uri: C{str} @param service: full service name (with name space) @type service: C{str} @param service_type: service class @type service_type: ServiceDefinition: service class @param service_args: arguments @return: the tuple of request and response. @rtype: C{(request object, response object)} @raise StartException: on error @see: U{rospy.SerivceProxy<http://docs.ros.org/kinetic/api/rospy/html/rospy.impl.tcpros_service.ServiceProxy-class.html>} ''' service = str(service) rospy.loginfo("Call service %s[%s]: %s, %s", utf8(service), utf8(service_uri), utf8(service_type), utf8(service_args)) from rospy.core import parse_rosrpc_uri, is_shutdown # from rospy.msg import args_kwds_to_message from rospy.exceptions import TransportInitError, TransportException from rospy.impl.tcpros_base import TCPROSTransport, DEFAULT_BUFF_SIZE # ,TCPROSTransportProtocol from rospy.impl.tcpros_service import TCPROSServiceClient from rospy.service import ServiceException request = service_type._request_class() import genpy try: now = rospy.get_rostime() import std_msgs.msg keys = {'now': now, 'auto': std_msgs.msg.Header(stamp=now)} genpy.message.fill_message_args(request, service_args, 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 StartException("Incompatible arguments to call service:\n%s\nProvided arguments are:\n%s\n\nService arguments are: [%s]" % (e, argsummary(service_args), genpy.message.get_printable_message_args(request))) # request = args_kwds_to_message(type._request_class, args, kwds) protocol = TCPROSServiceClient(service, service_type, headers={}) transport = TCPROSTransport(protocol, service) # initialize transport dest_addr, dest_port = parse_rosrpc_uri(service_uri) # connect to service transport.buff_size = DEFAULT_BUFF_SIZE try: transport.connect(dest_addr, dest_port, service_uri, timeout=5) except TransportInitError as e: # can be a connection or md5sum mismatch raise StartException(''.join(["unable to connect to service: ", utf8(e)])) transport.send_message(request, 0) try: responses = transport.receive_once() if len(responses) == 0: raise StartException("service [%s] returned no response" % service) elif len(responses) > 1: raise StartException("service [%s] returned multiple responses: %s" % (service, len(responses))) except TransportException as e: # convert lower-level exception to exposed type if is_shutdown(): raise StartException("node shutdown interrupted service call") else: raise StartException("transport error completing service call: %s" % (utf8(e))) except ServiceException, e: raise StartException("Service error: %s" % (utf8(e)))
def callService(self, service_uri, service, type, *args, **kwds): ''' Calls the service and return the response. To call the service the ServiceProxy can't be used, because it uses environment variables to determine the URI of the running service. In our case this service can be running using another ROS master. The changes on the environment variables is not thread safe. So the source code of the rospy.SerivceProxy (tcpros_service.py) was modified. @param service_uri: the URI of the service @type service_uri: C{str} @param service: full service name (with name space) @type service: C{str} @param type: service class @type type: ServiceDefinition: service class @param args: arguments to remote service @param kwds: message keyword arguments @return: the tuple of request and response. @rtype: C{(request object, response object)} @raise StartException: on error @see: L{rospy.SerivceProxy} ''' from rospy.core import parse_rosrpc_uri, is_shutdown from rospy.msg import args_kwds_to_message from rospy.exceptions import TransportInitError, TransportException from rospy.impl.tcpros_base import TCPROSTransport, TCPROSTransportProtocol, DEFAULT_BUFF_SIZE from rospy.impl.tcpros_service import TCPROSServiceClient from rospy.service import ServiceException request = args_kwds_to_message(type._request_class, args, kwds) transport = None protocol = TCPROSServiceClient(service, type, headers={}) transport = TCPROSTransport(protocol, service) # initialize transport dest_addr, dest_port = parse_rosrpc_uri(service_uri) # connect to service transport.buff_size = DEFAULT_BUFF_SIZE try: transport.connect(dest_addr, dest_port, service_uri) except TransportInitError as e: # can be a connection or md5sum mismatch raise StartException("unable to connect to service: %s" % e) transport.send_message(request, 0) try: responses = transport.receive_once() if len(responses) == 0: raise StartException("service [%s] returned no response" % service) elif len(responses) > 1: raise StartException( "service [%s] returned multiple responses: %s" % (service, len(responses))) except TransportException as e: # convert lower-level exception to exposed type if is_shutdown(): raise StartException("node shutdown interrupted service call") else: raise StartException( "transport error completing service call: %s" % (str(e))) except ServiceException, e: raise StartException("Service error: %s" % (str(e)))