pr2_device_check.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # Software License Agreement (BSD License)
00004 #
00005 # Copyright (c) 2010, Willow Garage, Inc.
00006 # All rights reserved.
00007 #
00008 # Redistribution and use in source and binary forms, with or without
00009 # modification, are permitted provided that the following conditions
00010 # are met:
00011 #
00012 #  * Redistributions of source code must retain the above copyright
00013 #    notice, this list of conditions and the following disclaimer.
00014 #  * Redistributions in binary form must reproduce the above
00015 #    copyright notice, this list of conditions and the following
00016 #    disclaimer in the documentation and/or other materials provided
00017 #    with the distribution.
00018 #  * Neither the name of the Willow Garage nor the names of its
00019 #    contributors may be used to endorse or promote products derived
00020 #    from this software without specific prior written permission.
00021 #
00022 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 # POSSIBILITY OF SUCH DAMAGE.
00034 
00035 ##\author Kevin Watts
00036 ##\brief Checks that all devices in a PR2 are properly associated to robot
00037 
00038 PKG = 'qualification'
00039 import roslib; roslib.load_manifest(PKG)
00040 
00041 import os, sys
00042 from optparse import OptionParser
00043 
00044 import getpass
00045 import subprocess
00046 
00047 from wg_invent_client import Invent
00048 
00049 class GetIDException(Exception): pass
00050 
00051 WGE100_PN = '68050' # Prefix for all wge100 camera PN's
00052 
00053 FWPROG_PATH = os.path.join(roslib.packages.get_pkg_dir(PKG), 'fwprog')
00054 PR2_GRANT = 'pr2-grant'
00055 
00056 def get_wge100_serials():
00057     cmd = '%s/bin/discover lan1' % roslib.packages.get_pkg_dir('wge100_camera')
00058     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr = subprocess.PIPE, shell=True)
00059     (o, e) = p.communicate()
00060     if p.returncode != 0:
00061         raise GetIDException("Unable to run \"discover\" to find camera serials!")
00062     
00063     serials = []
00064 
00065     lines = o.split('\n')
00066     for ln in lines:
00067         if len(ln.split()) < 5:
00068             continue
00069 
00070         serial_start = 'serial://'
00071         idx = ln.find(serial_start)
00072         if idx < 0:
00073             continue
00074         ser = ln[idx + len(serial_start): idx + len(serial_start) + 7]
00075         
00076         serial = WGE100_PN + ser
00077 
00078         serials.append(serial)    
00079 
00080     return serials
00081 
00082 def get_prosilica_ref():
00083     cmd = '%s/bin/ListAttributes' % roslib.packages.get_pkg_dir('prosilica_gige_sdk')
00084     p = subprocess.Popen([cmd, '10.68.0.20'], stdout = subprocess.PIPE, 
00085                          stderr= subprocess.PIPE)
00086     
00087     (o, e) = p.communicate()
00088     if p.returncode != 0:
00089         raise GetIDException("Unable to get Prosilica ID")
00090 
00091     lines = o.split('\n')
00092     for ln in lines:
00093         if ln.find('UniqueId') == -1:
00094             continue
00095         
00096         return ln.split()[-1]
00097     
00098     return ''
00099 
00100 def get_imu_ref():
00101     cmd = '%s/get_id' % roslib.packages.get_pkg_dir('microstrain_3dmgx2_imu')
00102     p = subprocess.Popen([cmd, '/etc/ros/sensors/imu', '-q'], stdout = subprocess.PIPE, 
00103                          stderr= subprocess.PIPE)
00104     
00105     (o, e) = p.communicate()
00106     if p.returncode != 0:
00107         raise GetIDException("Unable to get IMU device ID")
00108 
00109     lines = o.split('\n')
00110     return lines[0].strip()
00111 
00112 
00113 def get_hk_refs():
00114     ids = []
00115     for port in [ 'base_hokuyo', 'tilt_hokuyo' ]:
00116         cmd = 'source /etc/ros/setup.sh; rosrun hokuyo_node getID /etc/ros/sensors/' + port
00117         p = subprocess.Popen(['ssh', 'c2', cmd], stdout = subprocess.PIPE,
00118                              stderr = subprocess.PIPE)
00119         (o, e) = p.communicate()
00120         if p.returncode != 0:
00121             raise GetIDException("Unable to get HK ID for %s" % port)
00122         
00123         if len(o.split()) < 3:
00124             raise GetIDException("Unable to get HK ID for %s. Output invalid: %s" % (port, o))
00125 
00126         hk_id = o.split()[-1]
00127         ids.append(hk_id)
00128 
00129     return ids 
00130 
00131 def get_mcb_serials():
00132     serials = []
00133 
00134     count_cmd = PR2_GRANT + ' ' + os.path.join(FWPROG_PATH, 'eccount') + ' -iecat0'
00135 
00136     count = subprocess.call(count_cmd, shell=True)
00137     if count != 37:
00138         raise Exception("Invalid MCB count. Should be 37. Count: %d" % count)
00139 
00140     ##\todo Use motorconf to pull MCB SN's so it's not so slow
00141     for dev in range(1, 38):
00142         cmd = PR2_GRANT + ' ' + os.path.join(FWPROG_PATH, 'device') + ' -iecat0 -K -p %d' % dev
00143         p = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE,
00144                              shell = True)
00145         o, e = p.communicate()
00146         if p.returncode != 0:
00147             raise Exception("Unable to recover serial number from device %d. Returned %d" % (dev, p.returncode))
00148         
00149         for ln in o.split('\n'):
00150             if ln.startswith('serial :'):
00151                 sn = ln[9:].strip()
00152                 if sn not in serials:
00153                     serials.append(sn)
00154 
00155     return serials
00156 
00157 def get_wan0_mac():
00158     p = subprocess.Popen(['ifconfig', 'wan0'], stdout=subprocess.PIPE,
00159                          stderr=subprocess.PIPE)
00160 
00161     (o, e) = p.communicate()
00162     if p.returncode != 0:
00163         raise GetIDException("Unable to recover wan0 mac address")
00164 
00165     lines = o.split('\n')
00166     first = lines[0]
00167 
00168     words = first.split()
00169     if len(words) < 5 or not words[3].strip() == 'HWaddr':
00170         raise GetIDException("Unable to parse mac address output: %s. Got: %s. Length: %d" % (first, words[3], len(words)))
00171     mac = words[4].replace(':', '').lower()
00172 
00173     if not len(mac) == 12:
00174         raise GetIDException("Unable to parse mac address output: %s. Recovered: %s" % (first, mac))
00175     
00176     return mac
00177     
00178 
00179 if __name__ == '__main__':
00180     parser = OptionParser(usage="%prog -u USERNAME -r ROBOT\nMust be run on c1 of PR2")
00181     parser.add_option('-u', '--username', action="store", dest="username",
00182                       default=None, metavar="USERNAME",
00183                       help="Username for WG inventory system")
00184     parser.add_option('-r', '--robot', action="store", dest="robot",
00185                       default=None, metavar="ROBOT",
00186                       help="Robot SN (10XX) to store data.")
00187 
00188     options,args = parser.parse_args()
00189     if not options.username:
00190         parser.error("Must provide username to WG inverntory system")
00191     if not options.robot:
00192         parser.error("Must provide valid robot SN to log")
00193 
00194     robot = '68029670' + options.robot
00195     
00196     if not len(robot) == 12:
00197         parser.error("%s is not a valid robot serial number" % options.robot)
00198 
00199     print 'Enter your password to the Willow Garage Inventory system'
00200     my_pass = getpass.getpass()
00201 
00202     iv = Invent(options.username, my_pass)
00203     if not iv.login():
00204         parser.error("Must provide valid username and password to WG inventory system")
00205     if not iv.check_serial_valid(robot):
00206         parser.error("Robot serial number %s is invalid" % options.robot)
00207 
00208     print 'Pulling devices from robot'
00209 
00210     ok = True
00211 
00212     wan0_mac = get_wan0_mac()
00213     imu_id = get_imu_ref()
00214     prosilica = get_prosilica_ref()
00215     hks = get_hk_refs()
00216     wge100s = get_wge100_serials()
00217     mcbs = get_mcb_serials()
00218 
00219     print 'Getting parts from Invent'
00220     my_parts = iv.get_sub_items(robot, True)
00221 
00222     # Check wan0 mac address
00223     mac_serials = iv.lookup_by_reference(wan0_mac)
00224     if not len(mac_serials) == 1 and mac_serials[0] == robot:
00225         print >> sys.stderr, "Mac address for wan0 doesn't match robot. Mac address: %s" % wan0_mac
00226         ok = False
00227 
00228     # Check IMU
00229     serials = iv.lookup_by_reference(imu_id)
00230     if not len(serials) == 1:
00231         print >> sys.stderr, "Invalid serial numbers listed for IMU. %s" % ', '.join(serials)
00232         ok = False
00233 
00234     if len(serials) == 1 and serials[0] not in my_parts:
00235         print >> sys.stderr, "IMU serial %s is not listed in Invent. ID: %s" % (serials[0], imu_id)
00236         ok = False
00237 
00238     # Check prosilica
00239     serials = iv.lookup_by_reference(prosilica)
00240     if not len(serials) == 1:
00241         print >> sys.stderr, "Invalid serial numbers listed for Prosilica camera. %s" % ', '.join(serials)
00242         ok = False
00243 
00244     if len(serials) == 1 and serials[0] not in my_parts:
00245         print >> sys.stderr, "Prosilica serial %s is not listed in Invent. ID: %s" % (serials[0], prosilica)
00246         ok = False
00247 
00248     # Check wge100 cameras
00249     for wge in wge100s:
00250         if not wge in my_parts:
00251             print >> sys.stderr, "Camera %s was not found in parts list" % wge
00252             ok = False
00253 
00254     if not len(wge100s) == 6:
00255         print >> sys.stderr, "Not all wge100's found on robot. Expected 6, found %d" % len(wge100s)
00256         ok = False
00257     
00258     # Check HK's
00259     for hk in hks:
00260         serials = iv.lookup_by_reference(hk)
00261         if not len(serials) == 1:
00262             print >> sys.stderr, "Invalid serial numbers for HK reference %s. Serials: %s" % (hk, ', '.join(serials))
00263             ok = False
00264             continue
00265 
00266         if not serials[0] in my_parts:
00267             print >> sys.stderr, "Hokuyo %s not found in parts list. Device ID: %s" % (serials[0], hk)
00268             ok = False
00269 
00270     # Check etherCAT chain
00271     for mcb in mcbs:
00272         if not mcb in my_parts:
00273             print >> sys.stderr, "EtherCAT device %s was not found in parts list" % mcb
00274             ok = False
00275 
00276     if ok:
00277         print "All devices matched robot."
00278         sys.exit()
00279     
00280     print >> sys.stderr, "Error matching devices to robot"
00281     sys.exit(1)


qualification
Author(s): Kevin Watts (watts@willowgarage.com), Josh Faust (jfaust@willowgarage.com)
autogenerated on Sat Dec 28 2013 17:57:34