map_annotation_interface.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the name of Willow Garage, Inc. nor the names of its
00017 #    contributors may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
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         # Loading map.
00099         # Load the first map on map view
00100         # return list of available maps
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         # map data
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             # This is to support markers which are not in map frame. since map annotation is offlince tool. We don't know if we have to suport annotation in different frame
00193             #trans_pose = None
00194             #if not (marker.header.frame_id == self.map_frame or marker.header.frame_id == ''):
00195             #    try:
00196             #        self._tf.waitForTransform(marker.header.frame_id, self.map_frame, rospy.Time(), rospy.Duration(10))
00197             #        trans_pose = self._tf.transformPose(self.map_frame, marker.pose)
00198             #    except tf.Exception:
00199             #        rospy.logerr("TF Error")
00200             #        trans_pose = None
00201             #else:
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         # TODO add any settings to be saved
00305         pass
00306 
00307     def restore_settings(self, plugin_settings, instance_settings):
00308         # TODO add any settings to be restored
00309         pass


rocon_qt_library
Author(s): Donguk Lee
autogenerated on Fri Feb 12 2016 02:50:13