slam_widget_interface.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # License: BSD
00004 #   https://raw.github.com/robotics-in-concert/rocon_qt_gui/license/LICENSE
00005 #
00006 ##############################################################################
00007 
00008 
00009 import numpy
00010 import random
00011 from math import sqrt, atan, pi, degrees
00012 
00013 import rospy
00014 import tf
00015 from tf.transformations import quaternion_from_euler
00016 from world_canvas_client import AnnotationCollection, WCFError
00017 
00018 import nav_msgs.msg as nav_msgs
00019 import sensor_msgs.msg as sensor_msgs
00020 import geometry_msgs.msg as geometry_msgs
00021 
00022 from python_qt_binding.QtCore import Signal, QObject, pyqtSlot
00023 import rocon_qt_library.utils as utils
00024 
00025 
00026 class SlamWidgetInterface(QObject):
00027 
00028     map_received = Signal(nav_msgs.OccupancyGrid, name='map_received')
00029     scan_received = Signal(list)
00030     robot_pose_received = Signal(dict)
00031 
00032     def __init__(self, map_received_slot=None, map_topic='map', scan_received_slot=None, scan_topic='scan', robot_pose_received_slot=None, robot_pose_topic='robot_pose', wc_namespace='world_canvas', map_saved_callbacks=None,_tf=None):
00033         super(SlamWidgetInterface, self).__init__()
00034         if map_received_slot is not None:
00035             self.map_received.connect(map_received_slot)
00036         if scan_received_slot is not None:
00037             self.scan_received.connect(scan_received_slot)
00038         if robot_pose_received_slot is not None:
00039             self.robot_pose_received.connect(robot_pose_received_slot)
00040         
00041         self.map_saved_callbacks=[]
00042         if map_saved_callbacks is not None:
00043             self.map_saved_callbacks = map_saved_callbacks
00044 
00045         self.destroyed.connect(self.close)
00046 
00047         if _tf is None:
00048             self._tf = tf.TransformListener()
00049         else:
00050             self._tf = _tf
00051         self.wc_namespace = wc_namespace
00052         self.ac_handler = AnnotationCollection(srv_namespace=self.wc_namespace)
00053         
00054         self.sub_map = rospy.Subscriber(map_topic, nav_msgs.OccupancyGrid, self.map_cb)
00055         self.sub_scan = rospy.Subscriber(scan_topic, sensor_msgs.LaserScan, self.scan_cb)
00056         self.sub_robot_pose = rospy.Subscriber(robot_pose_topic, geometry_msgs.PoseStamped, self.robot_pose_cb)
00057 
00058         self.w = 0
00059         self.h = 0
00060         self.ori_x = 0
00061         self.ori_y = 0
00062         self.map_frame = None
00063 
00064     def save_map(self, world='world', map_name='map'):
00065         annotation = utils.create_map_annotation(world, map_name, self.map_msg)
00066         success = True
00067         message = "Success"
00068         try:
00069             self.ac_handler.add(annotation, self.map_msg)
00070             self.ac_handler.save()
00071         except WCFError as e:
00072             success = False
00073             message = str(e)
00074             
00075         for callback in self.map_saved_callbacks:
00076             callback((success, message))
00077 
00078     def map_cb(self, msg):
00079         """
00080         Update the map 
00081         
00082         :param nav_msgs.OccupancyGrid msg: a map from system
00083         """
00084         self.map_frame = msg.header.frame_id
00085         self.resolution = msg.info.resolution
00086         self.w = msg.info.width
00087         self.h = msg.info.height
00088         self.ori_x = msg.info.origin.position.x
00089         self.ori_y = msg.info.origin.position.y
00090         self.map_msg = msg
00091         self.map_received.emit(msg)
00092 
00093     def scan_cb(self, msg):
00094         """
00095         Update the scan
00096 
00097         :param sensor_msgs.LaserScan msg: scans data from system
00098         """
00099         scans = []
00100         trans_ptc = None
00101         if self.map_frame:
00102             if not (msg.header.frame_id == self.map_frame or msg.header.frame_id == ''):
00103                 try:
00104                     self._tf.waitForTransform(msg.header.frame_id, self.map_frame, rospy.Time(), rospy.Duration(10))
00105                     point_cloud = utils.laser_scan_to_point_cloud(msg,10)
00106                     trans_ptc = self._tf.transformPointCloud(self.map_frame, point_cloud)
00107                 except tf.Exception:
00108                     rospy.logerr("TF Error")
00109                     trans_ptc = None
00110             else:
00111                 trans_ptc = utils.laser_scan_to_point_cloud(msg)
00112 
00113         if trans_ptc:
00114             for pt in trans_ptc.points:
00115                 dx = (pt.x - self.ori_x) / self.resolution - self.w
00116                 dy = (pt.y - self.ori_y) / self.resolution
00117                 scans.append((dx, dy))
00118         self.scan_received.emit(scans)
00119 
00120     def robot_pose_cb(self, msg):
00121         """
00122         Update the robot_pose
00123 
00124         :param geometry_msgs.PoseStamped msg: robot pose data from system
00125         """
00126         # Transform everything in to the map frame
00127         trans_pose = None
00128         if self.map_frame:
00129             if not (msg.header.frame_id == self.map_frame or msg.header.frame_id == ''):
00130                 try:
00131                     self._tf.waitForTransform(msg.header.frame_id, self.map_frame, rospy.Time(), rospy.Duration(10))
00132                     trans_pose = self._tf.transformPose(self.map_frame, msg)
00133                 except tf.Exception:
00134                     rospy.logerr("TF Error")
00135                     trans_pose = None
00136             else:
00137                 trans_pose = msg
00138 
00139         if trans_pose:
00140             dx = (trans_pose.pose.position.x - self.ori_x) / self.resolution - self.w
00141             dy = (trans_pose.pose.position.y - self.ori_y) / self.resolution
00142             (droll, dpitch, dyaw) = tf.transformations.euler_from_quaternion([trans_pose.pose.orientation.x,
00143                                                                              trans_pose.pose.orientation.y,
00144                                                                              trans_pose.pose.orientation.z,
00145                                                                              trans_pose.pose.orientation.w])
00146             translated_robot_pose = {}
00147             translated_robot_pose['x'] = dx
00148             translated_robot_pose['y'] = dy
00149             translated_robot_pose['yaw'] = degrees(dyaw)
00150 
00151             self.robot_pose_received.emit(translated_robot_pose)
00152 
00153     def close(self):
00154         if self.sub_map:
00155             self.sub_map.unregister()
00156 
00157         if self.sub_scan:
00158             self.sub_scan.unregister()
00159 
00160         if self.sub_robot_pose:
00161             self.sub_robot_pose.unregister()
00162 
00163         super(SlamWidgetInterface, self).close()
00164 
00165     def save_settings(self, plugin_settings, instance_settings):
00166         # TODO add any settings to be saved
00167         pass
00168 
00169     def restore_settings(self, plugin_settings, instance_settings):
00170         # TODO add any settings to be restored
00171         pass


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