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
00022 def get_mtrace_topics(type = 'ethercat_hardware/MotorTrace'):
00023 master = roslib.scriptutil.get_master()
00024
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
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
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
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
00107 topics = get_mtrace_topics()
00108 with self._mutex:
00109 self_topics = self._topic_subs
00110
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
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
00123 with self._mutex:
00124 for topic,sub in new_topic_subs:
00125 self._topic_subs[topic] = sub
00126
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