mtrace_recorder.py
Go to the documentation of this file.
00001 from __future__ import with_statement
00002 
00003 PKG = 'mtrace_tools'
00004 import roslib; roslib.load_manifest(PKG)
00005 import rospy
00006 from ethercat_hardware.msg import MotorTrace
00007 import rosbag
00008 import threading
00009 import time
00010 import copy
00011 
00012 class MotorTraceTopicException(Exception): pass
00013 
00014 def _succeed(args):
00015     code, msg, val = args
00016     if code != 1:
00017         raise MotorTraceTopicException("remote call failed: %s"%msg)
00018     return val
00019 
00020 
00021 ##\brief Gets list of published motor trace topics
00022 def get_mtrace_topics(type = 'ethercat_hardware/MotorTrace'):
00023     master = roslib.scriptutil.get_master()
00024     # Need try/catch here
00025     try:
00026         pub_topics = _succeed(master.getPublishedTopics('/mtrace_plotter', '/'))
00027     except MotorTraceTopicException:
00028         rospy.logerr('Unable to get list of motor trace topics')
00029         return []
00030 
00031     valid_topics = []
00032     for topic,topic_type in pub_topics:
00033         if topic_type == type:
00034             valid_topics.append(topic)
00035 
00036     return valid_topics
00037 
00038 
00039 
00040 class MotorTraceDesc:
00041     """ Simple wrapper class around motor trace messages that generates descriptions for each message"""
00042     def __init__(self, topic, msg):
00043         self.topic = topic
00044         self.msg = msg
00045         t = time.strftime("%a, %b %d, %I:%M.%S %p", time.localtime(msg.header.stamp.to_sec()))
00046         self.description = "%s : %s : %s" % (t, msg.actuator_info.name, msg.reason)    
00047 
00048 
00049 class MtraceCallback:
00050     """ Wrapper class around callback so topic can be provided"""
00051     def __init__(self, callback, topic):
00052         self.topic = topic
00053         self.callback = callback
00054         
00055     def mtraceCallback(self, msg):
00056         self.callback(msg,self.topic)
00057     
00058 
00059 class MtraceRecorder:
00060     """ Class to record and keep trace of MotorTrace messages"""
00061     def __init__(self):
00062         self._mutex = threading.Lock()
00063         self._msg_list = []
00064         self._topic_subs = {}
00065         self._ros_topic_thread = None
00066 
00067     def getMsgList(self):
00068         with self._mutex:
00069             msg_list = copy.copy(self._msg_list)
00070         return msg_list
00071 
00072     def clearMsgList(self):
00073         with self._mutex:
00074             self._msg_list = []
00075 
00076     def loadBagFileInternal(self, bag):
00077         """ Internal, loads all MotorTrace messages from a given bag file """
00078         for topic, msg, t in bag.read_messages():
00079             # use some simple heristic to determine if message is true MotorTrace message
00080             if hasattr(msg, 'reason') and hasattr(msg, 'board_info') and hasattr(msg, 'samples'):
00081                 with self._mutex:
00082                     self._msg_list.append(MotorTraceDesc(topic,msg))
00083                 #rospy.sleep(0.5)
00084 
00085     def loadBagFile(self, bag_filename):
00086         """ Loads all MotorTrace messages from a given bag file """
00087         bag = rosbag.Bag(bag_filename)
00088         self.loadBagFileInternal(self, bag)
00089 
00090     def loadBagFileAsync(self, bag_filename):
00091         """ Starts background thread that loads all MotorTrace messages from a given bag file """
00092         # open bag file before starting thread so this easily pass onerrors that occurred while opening file
00093         bag = rosbag.Bag(bag_filename)
00094         t = threading.Thread(group=None, target=self.loadBagFileInternal, args=[bag])
00095         t.start()
00096         
00097 
00098     def mtraceCallback(self, msg, topic):
00099         desc_msg = MotorTraceDesc(topic, msg)
00100         with self._mutex:
00101             self._msg_list.append(desc_msg)
00102 
00103 
00104     def rosTopicThread(self):
00105         while not rospy.is_shutdown():
00106             # gets list of all topic with MotorTrace type
00107             topics = get_mtrace_topics()
00108             with self._mutex:                
00109                 self_topics = self._topic_subs
00110             # find any new topics
00111             new_topics = []
00112             for topic in topics:
00113                 if topic not in self_topics:
00114                     print "New MotorTrace topic", topic
00115                     new_topics.append(topic)
00116             # subscribe to new topics
00117             new_topic_subs = []
00118             for topic in new_topics:
00119                 callbackWrapper = MtraceCallback(self.mtraceCallback, topic)
00120                 sub = rospy.Subscriber(topic, MotorTrace, callbackWrapper.mtraceCallback)
00121                 new_topic_subs.append( (topic, sub) )
00122             # add new subscribers to internal map 
00123             with self._mutex:
00124                 for topic,sub in new_topic_subs:
00125                     self._topic_subs[topic] = sub
00126             # wait before doing this again
00127             rospy.sleep(1.0)
00128 
00129 
00130     def startRosRecording(self):
00131         """ Starts recoarding messages from any ROS topic that has a MotorTrace type
00132         scans for new ROS MotorModel topics every second and subscribes to every new one
00133         """
00134         if self._ros_topic_thread is not None:
00135             raise Exception("Already monitoring ROS topics")
00136         
00137         self._ros_topic_thread = threading.Thread(group=None, target=self.rosTopicThread)
00138         self._ros_topic_thread.start()
00139 
00140 


mtrace_tools
Author(s): Derek
autogenerated on Sat Dec 28 2013 17:58:08