glass_monitor.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # copyright 2014 UNL Nimbus Lab 
00003 #
00004 #  Licensed under the Apache License, Version 2.0 (the "License");
00005 #     you may not use this file except in compliance with the License.
00006 #    You may obtain a copy of the License at
00007 #  
00008 #        http://www.apache.org/licenses/LICENSE-2.0
00009 #  
00010 #    Unless required by applicable law or agreed to in writing, software
00011 #  distributed under the License is distributed on an "AS IS" BASIS,
00012 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 #   See the License for the specific language governing permissions and
00014 #   limitations under the License.
00015 import rospy, rostopic
00016 from std_msgs.msg import String
00017 
00018 class GlassMonitor:
00019     '''Class to monitor desired topics and feilds and send out messages
00020         when the value on that topic exceeds a defined threshold value
00021         in order to build the monitor it requires the needed information 
00022         to be input as a parameter when the node is launched
00023         The input contains a list of dictonaries that have each of the following defined
00024 
00025         topic: The rostopic to monitor
00026         field: The fully named field within the message to check
00027         op: Comparison to make can be one of the following: gt, lt, eq, ne,within, outside 
00028         val: The value to check against
00029         msg: The message to display when the check has been violated
00030        
00031         And example .launch input is below: 
00032 
00033         <node name="monitor" type="glass_monitor.py" pkg="ros_glass_tools" output="s
00034             <rosparam param="monitors">
00035             [
00036             { topic: '/a/pose', field: 'translation/x', op: 'gt', val : 2 , msg: 'UAV is too far to the left'},
00037             { topic: '/a/pose', field: 'translation/z', op: 'gt', val : 2 , msg: 'UAV is too high!'}
00038             ]
00039             </rosparam>
00040         </node>
00041     '''
00042 
00043     def __init__(self):
00044         #init nodes and services
00045         rospy.init_node("glass_monitor")
00046         self.warn_pub =  rospy.Publisher('/glass_warn', String)
00047         #read lists
00048         input_list =  rospy.get_param('~monitors', None)
00049         self.monitor_list = self.process_input(input_list)
00050         
00051 
00052 
00053     def process_input(self, input_list):
00054         '''this method takes the input parameter to create the monitors
00055             the topic must already be published so that this method 
00056             can determine the message type
00057         '''
00058         sub_list = []
00059         for monitor in input_list:
00060             msg_type = rostopic.get_topic_class(monitor['topic'])[0]
00061             #check to see we can get a valid message class
00062             #if so we create a subscriver and pass along the extra information
00063             #diectonary so comparisions can be made
00064             if msg_type != None:
00065                 sub_list.append(rospy.Subscriber(monitor['topic'],msg_type, self.callback, monitor))
00066                 rospy.logerr('Started for topic %s', monitor['topic'])
00067             else:
00068                 rospy.logerr("Cannot determine type of topic %s", monitor['topic'])
00069         return sub_list
00070                 
00071     def callback(self, msg, info):
00072         '''generic callback for the monitor topics
00073             this will get the desired comparison and check that value
00074             if it is violated than the node will publish warning message
00075             to the glass topic'''
00076         #get data from the message
00077         data = float(self.get_msg_data(msg, info['field']) )
00078         op = info['op']
00079         check_val = float(info['val'])
00080         #comparisons
00081         if op == 'lt':
00082             if data < check_val:
00083                 st = String(info['msg'])
00084                 self.warn_pub.publish(st)
00085 
00086         elif op == 'gt':
00087             if data > check_val:
00088                 st = String(info['msg'])
00089                 self.warn_pub.publish(st)
00090 
00091         elif op == 'ne':
00092             if data != check_val:
00093                 st = String(info['msg'])
00094                 self.warn_pub.publish(st)
00095 
00096         elif op == 'eq':
00097             if data == check_val:
00098                 st = String(info['msg'])
00099                 self.warn_pub.publish(st)
00100         elif op == 'within':
00101             if abs(data) > check_val:
00102                 st = String(info['msg'])
00103                 self.warn_pub.publish(st)
00104         elif op == 'outside':
00105             if abs(data) < check_val:
00106                 st = String(info['msg'])
00107                 self.warn_pub.publish(st)
00108         else:
00109             rospy.logerr("Invalid operation %s", info['op'])
00110 
00111         
00112     def get_msg_data(self, msg, key):
00113         '''Have to slpit the keys up and recursivly call to get
00114         the desired information out of all the messages'''
00115         idx = key.find('/')
00116         if idx  == -1: 
00117             return msg.__getattribute__(key)
00118         else:
00119         #split the key
00120             sub_key = key[idx+1:]
00121             key = key[:idx]
00122             msg = msg.__getattribute__(key)
00123             return self.get_msg_data(msg, sub_key)
00124 
00125 
00126 
00127 if __name__ == '__main__':
00128     rm =GlassMonitor() 
00129     rospy.spin();


ros_glass_tools
Author(s):
autogenerated on Thu Aug 27 2015 14:47:21