00001 import rospy
00002 import roslib.message
00003
00004 from lama_interfaces.srv import ActOnMap
00005 from lama_interfaces.srv import ActOnMapRequest
00006
00007 _default_map_agent_name = '/lama_map_agent'
00008
00009
00010 def map_agent_name():
00011 return rospy.get_param('map_agent', _default_map_agent_name)
00012
00013
00014 def clean_tuple(lama_objects):
00015 """Transform references from tuples to list in a list of LamaObject
00016
00017 rospy deserializes arrays as tuples, transform them back in place to lists.
00018 """
00019 for lama_object in lama_objects:
00020 lama_object.references = list(lama_object.references)
00021
00022
00023 class MapAgent(object):
00024 """Class to interact with the map through service calls
00025
00026 The service calls must be done through MapAgent.proxy.
00027 Example of database request through service call:
00028 map_action = ActOnMapRequest()
00029 map_action.action = map_action.GET_DESCRIPTOR_LINKS
00030 map_action.object.id = request_object_id
00031 map_action.interface_name = request_interface_name
00032 response = MapAgent().proxy(map_action)
00033 A few function members are provided to facilitate such requests
00034 (get_vertex_list, get_edge_list).
00035 """
00036 def __init__(self, timeout=None):
00037 """
00038 Parameters
00039 ----------
00040 - timeout: None or double. Timeout for contacting service. If None,
00041 the service is supposed to be up and wait_for_service will not be
00042 called. If 0, wait_for_service() is called, i.e. wait undefinitely.
00043 Otherwise, wait_for_service(timeout) is called.
00044 """
00045 self._timeout = timeout
00046 action_srv_type = 'lama_interfaces/ActOnMap'
00047 srv_action_class = roslib.message.get_service_class(action_srv_type)
00048
00049 self.action_service_name = map_agent_name()
00050 self.action_service_class = srv_action_class
00051 self.proxy = rospy.ServiceProxy(self.action_service_name, ActOnMap)
00052
00053 @property
00054 def timeout(self):
00055 return self._timeout
00056
00057 @timeout.setter
00058 def timeout(self, value):
00059 self._timeout = value
00060
00061 def wait_for_service(self):
00062 if self.timeout is not None:
00063 if self.timeout == 0:
00064 rospy.logdebug('Waiting for service {}'.format(
00065 self.action_service_name))
00066 self.proxy.wait_for_service()
00067 rospy.logdebug('Service {} replied'.format(
00068 self.action_service_name))
00069 return True
00070 else:
00071 try:
00072 self.proxy.wait_for_service(self.timeout)
00073 except rospy.ROSException:
00074 rospy.logerr('Service {} not available'.format(
00075 self.action_service_name))
00076 return False
00077 return True
00078
00079 def get_lama_object_list(self, criteria=None):
00080 """Return the list of vertices and edges as LamaObject"""
00081 if not self.wait_for_service():
00082 return
00083 vertices = self.get_vertex_list(criteria)
00084 if vertices is None:
00085 return
00086 edges = self.get_edge_list(criteria)
00087 if edges is None:
00088 return
00089 return vertices + edges
00090
00091 def get_edge_list(self, criteria=None):
00092 """Return the list of edges as LamaObject that match the search criteria
00093
00094 Retrieve all edges that match the search criteria.
00095
00096 Search criteria are attributes of criteria with non-default values
00097 (defaults are 0 or '').
00098 Return a list of LamaObject, an empty list of no LamaObject matches, or
00099 None on service error.
00100
00101 Parameters
00102 ----------
00103 - criteria: an instance of LamaObject, supposed of type EDGE.
00104 """
00105 if not self.wait_for_service():
00106 return
00107 map_action = ActOnMapRequest()
00108 map_action.action = map_action.GET_EDGE_LIST
00109 if criteria is not None:
00110 lama_object_attr = ['id', 'id_in_world', 'name', 'emitter_id',
00111 'emitter_name', 'type', 'references']
00112 for attr in lama_object_attr:
00113 setattr(map_action.object, attr, getattr(criteria, attr))
00114 response = self.proxy(map_action)
00115 clean_tuple(response.objects)
00116 return response.objects
00117
00118 def get_vertex_list(self, criteria=None):
00119 """Return the list of vertices as LamaObject that match the criteria
00120
00121 Retrieve all vertices that match the search criteria.
00122
00123 Search criteria are attributes of criteria with non-default values
00124 (defaults are 0 or '').
00125 Return a list of LamaObject, an empty list of no LamaObject matches, or
00126 None on service error.
00127
00128 Parameters
00129 ----------
00130 - criteria: an instance of LamaObject, supposed of type VERTEX.
00131 """
00132 if not self.wait_for_service():
00133 return
00134
00135 map_action = ActOnMapRequest()
00136 map_action.action = map_action.GET_VERTEX_LIST
00137 if criteria is not None:
00138 lama_object_attr = ['id', 'id_in_world', 'name', 'emitter_id',
00139 'emitter_name', 'type', 'references']
00140 for attr in lama_object_attr:
00141 setattr(map_action.object, attr, getattr(criteria, attr))
00142 response = self.proxy(map_action)
00143 clean_tuple(response.objects)
00144 return response.objects
00145
00146 def get_descriptor_links(self, id_, interface_name=None):
00147 """Retrieve the list of DescriptorLink associated with a Lama object
00148
00149 Return a list of DescriptorLink. If interface_name is given, return
00150 all DescriptorLink corresponding to this interface_name, otherwise, and
00151 if interface_name is '' or '*', return all DescriptorLink.
00152
00153 Parameters
00154 ----------
00155 - id_: int, lama object id in the database.
00156 - interface_name: string, default to None.
00157 If None, '', or '*', all DescriptorLink are returned.
00158 Otherwise, only DescriptorLink from this interface are returned.
00159 """
00160 if not self.wait_for_service():
00161 return
00162
00163 map_action = ActOnMapRequest()
00164 map_action.action = map_action.GET_DESCRIPTOR_LINKS
00165 map_action.object.id = id_
00166 if interface_name and interface_name != '*':
00167 map_action.interface_name = interface_name
00168 response = self.proxy(map_action)
00169 if not response:
00170 return
00171 return response.descriptor_links