test_param.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2009, 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 
00034 ##\author Kevin Watts
00035 ##\brief Test variables and parameters container classes
00036 
00037 PKG = 'life_test'
00038 import roslib
00039 roslib.load_manifest(PKG)
00040 
00041 import rospy
00042 
00043 from writing_core import *
00044 
00045 
00046 class LifeTest(object):
00047     """
00048     Holds parameters, info for each life test
00049     """
00050     def __init__(self, short = '', testid = '', name = '', desc = '', serial = '',
00051                  duration = 0, launch_script = '', test_type = '', power = False, params = None):
00052         """
00053         Use **kwargs in constructor. Preferred option is to initialize from XML
00054         """
00055         self._short_serial = serial
00056         self._id = testid
00057         self._name = name
00058         self._short = short
00059         self._duration = duration
00060         self._desc = desc
00061         self._launch_script = launch_script
00062         self._test_type = test_type
00063         self._power = power
00064 
00065         self._params = params if params else []
00066 
00067         self._debug_ok = False
00068         
00069         self._has_init = self._short_serial != '' and self._id != '' and self._name != '' \
00070             and self._launch_script != ''
00071 
00072 
00073     def init_xml(self, xml):
00074         """
00075         Initialize LifeTest from XML value. 
00076         
00077         Required tags:
00078         serial - Short value only
00079         name - Full name of test
00080         id - Test ID
00081         desc - Description
00082         script - Path to launch script
00083         type - Ex: 'Burn In'
00084         power - Needs power or not (bool)
00085         
00086         Optional:
00087         debug - "true" if can run outside debug mode
00088         duration - Default: 0
00089 
00090         TestParam's are initialized using nested XML nodes
00091         @raise Exception : If parameters are duplicated, or required attributes don't exist
00092         @return bool : True if init OK
00093         """
00094         self._short_serial = xml.attributes['serial'].value # Short serial only
00095         self._name = xml.attributes['name'].value
00096         self._id = xml.attributes['id'].value
00097         self._desc = xml.attributes['desc'].value
00098         self._launch_script = xml.attributes['script'].value
00099         self._test_type = xml.attributes['type'].value
00100         self._short = xml.attributes['short'].value
00101         self._power = xml.attributes['power'].value != 'false'
00102 
00103         self._debug_ok = xml.attributes.has_key('debug') and \
00104             xml.attributes['debug'].value.lower() == "true"
00105         
00106         if xml.attributes.has_key('duration'):
00107             self._duration = int(xml.attributes['duration'].value)
00108 
00109         params_xml = xml.getElementsByTagName('param')
00110         for param_xml in params_xml:
00111             my_param = TestParam()
00112             my_param.init_xml(param_xml)
00113 
00114             names = [ p.name for p in self._params ]
00115             if my_param.name in names:
00116                 raise Exception("Param %s already exists in param list! XML: %s" % (my_param.name, xml.toprettyxml()))
00117 
00118             self._params.append(my_param)
00119 
00120         self._has_init = True
00121         return True
00122     
00123     @property
00124     def debug_ok(self): return self._debug_ok
00125 
00126     @property
00127     def need_power(self): return self._power
00128 
00129     @property
00130     def short(self):
00131         return self._short
00132 
00133     @property
00134     def desc(self):
00135         """Get description of test"""
00136         return self._desc
00137 
00138     @property
00139     def params(self): 
00140         """Get the parameters list. Read-only"""
00141         return self._params
00142 
00143     @property
00144     def duration(self): return self._duration
00145 
00146     @property
00147     def name(self): return self._name
00148 
00149     @property
00150     def id(self): return self._id
00151 
00152     @property
00153     def type(self): return self._test_type
00154 
00155     @property
00156     def needs_power(self):
00157         return self.need_power
00158     
00159     @property
00160     def launch_file(self):
00161         return self._launch_script
00162 
00163     def set_params(self, namespace):
00164         """
00165         Sets parameters in given namespace
00166         """
00167         for param in self._params:
00168             param.set_namespace(namespace)
00169 
00170 
00171     def get_title(self, serial):
00172         """
00173         Return a human readable title of the test/item. Used as tab name
00174         """
00175         if len(serial) == 12: # Take last few digits of SN to ID part
00176             return "%s %s" % (self._short, 
00177                                  serial[len(serial) - 3: 
00178                                         len(serial)])
00179         # Or just return the short name
00180         return self._short
00181 
00182 
00183     def validate(self):
00184         """
00185         Called during unit testing only. Checks all files exist, are valid
00186         @return bool : True if OK
00187         """
00188         if not self._has_init:
00189             return False
00190 
00191         import os, sys
00192 
00193         full_path = os.path.join(roslib.packages.get_pkg_dir(PKG), self._launch_script)
00194 
00195         if not os.path.exists(full_path):
00196             print >> sys.stderr, "Test %s, path %s doesn't exist" % (self._name, full_path)
00197             return False
00198         if not full_path.endswith('.launch'):
00199             print >> sys.stderr, "Test %s, path %s is not a launch file" % (self._name, full_path)
00200             return False
00201 
00202         return True
00203 
00204     def make_param_table(self):
00205         """
00206         Writes parameters to HTML table form for logging
00207         @return str : Table as a string
00208         """
00209         if len(self._params) == 0:
00210             return '<p>No test parameters defined.</p>\n'
00211 
00212         html = '<table border="1" cellpadding="2" cellspacing="0">\n'
00213         html += write_table_row(['Name', 'Value', 'Key', 'Description'], True)
00214         for param in self._params:
00215             html += write_table_row([param._name, param._value, param._param_name, param._desc])
00216         html += '</table>\n'
00217 
00218         return html
00219             
00220         
00221 ## Stores parameter data for each test
00222 ## Parameters are ROS parameters, and are updated in test log
00223 ## Examples: cycle rate, joint torque, roll on/off
00224 ## Allows changes in test setup or implementation to be logged automatically
00225 class TestParam(object):
00226     def __init__(self):
00227         self._value = ''
00228         self._desc = ''
00229 
00230         self._cumulative = ''
00231         self._param_name = ''
00232         self._name = ''
00233         self._namespace = ''
00234 
00235     def init_xml(self, param_xml):
00236         """
00237         Initialize from XML
00238 
00239         Required elements:
00240         name - Name of param
00241         param_name - ROS name of param
00242         desc - Description
00243         value - Value of param
00244         rate = "true" if parameters is cumulative, or a rate
00245         
00246         @raise Exception : If required attribs aren't present
00247         @return bool : True if OK
00248         """
00249         self._name = param_xml.attributes['name'].value
00250         self._param_name = param_xml.attributes['param_name'].value
00251         self._desc = param_xml.attributes['desc'].value
00252         self._value = param_xml.attributes['val'].value
00253         self._cumulative = param_xml.attributes['rate'].value == 'true'
00254 
00255         return True
00256  
00257     def set_namespace(self, ns):
00258         """
00259         Set parameter's value in appropriate namespace
00260         """
00261         self._namespace = ns
00262         rospy.set_param('/' + self._namespace + '/' + self._param_name, self._value)
00263 
00264     @property
00265     def value(self):
00266         try:
00267             val = float(self._value)
00268             return val
00269         except:
00270             return str(self._value)
00271 
00272     @property
00273     def name(self): return self._name
00274 
00275     @property
00276     def rate(self):
00277         return self._cumulative
00278 


life_test
Author(s): Kevin Watts
autogenerated on Sat Dec 28 2013 17:56:37