00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import numpy
00034 import random
00035 from math import sqrt, atan, pi, degrees, radians
00036
00037 import rospy
00038 import tf
00039 import unique_id
00040 from tf.transformations import quaternion_from_euler
00041
00042 import nav_msgs.msg as nav_msgs
00043 import visualization_msgs.msg as visualization_msgs
00044
00045
00046 from python_qt_binding.QtCore import Signal, QObject, pyqtSlot
00047 import rocon_qt_library.utils as utils
00048 from world_canvas_client import AnnotationCollection, WCFError
00049 from visualization_msgs.msg import Marker
00050
00051
00052 class MapAnnotationInterface(QObject):
00053
00054 scene_update = Signal(str, dict, name='scene_update')
00055
00056 def __init__(self, scene_update_slot=None, wc_namespace='world_canvas', _tf=None):
00057 super(MapAnnotationInterface, self).__init__()
00058 if scene_update_slot is not None:
00059 self.scene_update.connect(scene_update_slot)
00060 self.destroyed.connect(self.close)
00061
00062 if _tf is None:
00063 self._tf = tf.TransformListener()
00064 else:
00065 self._tf = _tf
00066
00067 self.w = 0
00068 self.h = 0
00069 self.ori_x = 0
00070 self.ori_y = 0
00071 self.resolution = 1
00072 self.map_frame = None
00073
00074 self._annotations = None
00075 self.map_msg = None
00076 self.wc_namespace = wc_namespace
00077 self.ac_handler_map = AnnotationCollection(srv_namespace=self.wc_namespace)
00078 self.ac_handler_others = AnnotationCollection(srv_namespace=self.wc_namespace)
00079
00080 self._new_annotations = []
00081 self._new_annotations_data = []
00082
00083 def get_list_world(self):
00084 try:
00085 world_names = self.ac_handler_map.get_world_list()
00086 except WCFError as e:
00087 return False, str(e), []
00088
00089 return True, "Success", world_names
00090
00091
00092 def load_world(self, world):
00093 '''
00094 loading world information from world canvas server
00095
00096 :returns: Map annotation
00097 '''
00098
00099
00100
00101 message, map_name_list = self._load_map(world)
00102
00103 if len(map_name_list) > 0:
00104 message, annotation_name_list = self._load_annotations(world)
00105 else:
00106 return False, message, [], []
00107
00108 self._world = world
00109 self._new_annotations = []
00110 self._new_annotations_data = []
00111 return True, message, map_name_list, annotation_name_list
00112
00113 def load_map(self, selected_name):
00114 try:
00115 map_name, map_id = selected_name.split('-')
00116 for annot in self._map_annotations:
00117 if map_name == annot.name and map_id == str(annot.id):
00118 map_msg = self.ac_handler_map.get_data(annot)
00119 self._update_map(map_msg)
00120 annotations_tmp = self.ac_handler_others.get_annotations()
00121 annotations = [a for a in annotations_tmp if not a.type == 'nav_msgs/OccupancyGrid']
00122 self._annotations = annotations
00123 self._update_annotations('annotations',annotations)
00124 self._update_annotations('new_annotations', self._new_annotations)
00125 except WCFError as e:
00126 return False, str(e)
00127
00128 return True, "Success"
00129
00130 def _load_map(self, world):
00131 message = "Success"
00132 try:
00133 self.ac_handler_map.filter_by(world=world, types=['nav_msgs/OccupancyGrid'])
00134 self.ac_handler_map.load_data()
00135 map_annotations = self.ac_handler_map.get_annotations(type='nav_msgs/OccupancyGrid')
00136 self._map_annotations = map_annotations
00137 except WCFError as e:
00138 message = str(e)
00139 return message, []
00140
00141 if len(map_annotations) < 1:
00142 message = "No map available"
00143 return message, []
00144
00145 map_msg = self.ac_handler_map.get_data(self._map_annotations[0])
00146 self._update_map(map_msg)
00147 map_names = [a.name+"-"+str(a.id) for a in self._map_annotations]
00148 return message, map_names
00149
00150 def _update_map(self,map_msg):
00151 draw_data = {}
00152 self._map = map_msg
00153
00154
00155 self.map_frame = self._map.header.frame_id
00156 self.resolution = self._map.info.resolution
00157 self.w = self._map.info.width
00158 self.h = self._map.info.height
00159 self.ori_x = self._map.info.origin.position.x
00160 self.ori_y = self._map.info.origin.position.y
00161
00162 draw_data["map"] = self._map
00163 self.scene_update.emit('map', draw_data)
00164
00165 def _load_annotations(self, world):
00166 message = "Success"
00167 try:
00168 self.ac_handler_others.filter_by(world=world)
00169 self.ac_handler_others.load_data()
00170 annotations_tmp = self.ac_handler_others.get_annotations()
00171 annotations = [a for a in annotations_tmp if not a.type == 'nav_msgs/OccupancyGrid']
00172 self._annotations = annotations
00173 except WCFError as e:
00174 message = str(e)
00175
00176 if len(annotations) < 1:
00177 message = "No annotations available"
00178 return message, []
00179
00180 self._update_annotations('annotations',annotations)
00181 self._update_annotations('new_annotations', self._new_annotations)
00182
00183 names = [a.name for a in annotations]
00184 return message, names
00185
00186 def _update_annotations(self, key, annotations):
00187 viz_marker_items = []
00188 markers = utils.annotations_to_viz_markers(annotations)
00189 for marker in markers.markers:
00190 viz_marker = {}
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 trans_pose = marker
00203
00204 if trans_pose:
00205 dx = (trans_pose.pose.position.x - self.ori_x) / self.resolution - self.w
00206 dy = (trans_pose.pose.position.y - self.ori_y) / self.resolution
00207 (droll, dpitch, dyaw) = tf.transformations.euler_from_quaternion([trans_pose.pose.orientation.x,
00208 trans_pose.pose.orientation.y,
00209 trans_pose.pose.orientation.z,
00210 trans_pose.pose.orientation.w])
00211 viz_marker['x'] = dx
00212 viz_marker['y'] = dy
00213 viz_marker['yaw'] = degrees(dyaw)
00214 else:
00215 viz_marker['x'] = None
00216 viz_marker['y'] = None
00217 viz_marker['yaw'] = None
00218
00219 viz_marker['scale'] = (marker.scale.x / self.resolution, marker.scale.y / self.resolution, marker.scale.z / self.resolution)
00220 viz_marker['type'] = marker.type
00221 viz_marker['color'] = (marker.color.r, marker.color.g, marker.color.b, marker.color.a)
00222 viz_marker['text'] = marker.text
00223 viz_marker_items.append(viz_marker)
00224
00225 draw_data = {}
00226 draw_data[key] = viz_marker_items
00227 self.scene_update.emit(key, draw_data)
00228
00229 def add_annotation(self, annotation_info, annotation_type):
00230 if annotation_type == "ar_track_alvar_msgs/AlvarMarker":
00231 anno, data = utils.create_alvar_marker_from_info(annotation_info, self._world, self._map.header.frame_id)
00232 elif annotation_type == "yocs_msgs/Waypoint":
00233 anno, data = utils.create_waypoint_from_info(annotation_info, self._world, self._map.header.frame_id)
00234
00235 self._new_annotations.append(anno)
00236 self._new_annotations_data.append(data)
00237
00238 self._update_annotations('new_annotations', self._new_annotations)
00239
00240 self.ac_handler_others.add(anno, data)
00241 new_annotation_names = [a.name for a in self._new_annotations]
00242
00243 return new_annotation_names
00244
00245 def remove_annotation(self, annotation_name):
00246 for a in self._annotations:
00247 if a.name == annotation_name:
00248 self.ac_handler_others.remove(a.id)
00249 self._annotations.remove(a)
00250 self._update_annotations('annotations', self._annotations)
00251 return 'annotations', [a.name for a in self._annotations]
00252
00253 for a in self._new_annotations:
00254 if a.name == annotation_name:
00255 self.ac_handler_others.remove(a.id)
00256 self._new_annotations.remove(a)
00257 self._update_annotations('new_annotations', self._new_annotations)
00258 return 'new_annotations', [a.name for a in self._new_annotations]
00259
00260 def save_annotations(self):
00261 try:
00262 self.ac_handler_others.save()
00263 for a in self._new_annotations:
00264 self.ac_handler_others.remove(a.id)
00265 self._new_annotations = []
00266 self._new_annotations_data = []
00267
00268 except WCFError as e:
00269 message = str(e)
00270 return False, message
00271 return True, "Success"
00272
00273 def get_annotation_info(self, annotation_name):
00274 annotations = []
00275 for a in self._annotations:
00276 if a.name == annotation_name:
00277 annotations = self.ac_handler_others.get_annotations(annotation_name)
00278 break
00279
00280 for a in self._new_annotations:
00281 if a.name == annotation_name:
00282 annotations = self.ac_handler_others.get_annotations(annotation_name)
00283 break
00284 if annotations:
00285 annotation = annotations[0]
00286 name = annotation.name
00287 anno_type = annotation.shape
00288 x = annotation.pose.pose.pose.position.x
00289 y = annotation.pose.pose.pose.position.y
00290 (roll, pitch, yaw) = tf.transformations.euler_from_quaternion([annotation.pose.pose.pose.orientation.x,
00291 annotation.pose.pose.pose.orientation.y,
00292 annotation.pose.pose.pose.orientation.z,
00293 annotation.pose.pose.pose.orientation.w])
00294 height = annotation.pose.pose.pose.position.z
00295 radius = annotation.size.x
00296 return (anno_type, name, x, y, yaw, radius, roll, pitch, height)
00297 else:
00298 return ()
00299
00300 def close(self):
00301 super(MapAnnotationInterface, self).close()
00302
00303 def save_settings(self, plugin_settings, instance_settings):
00304
00305 pass
00306
00307 def restore_settings(self, plugin_settings, instance_settings):
00308
00309 pass