zenither.py
Go to the documentation of this file.
00001 # Copyright (c) 2009, Georgia Tech Research Corporation
00002 # All rights reserved.
00003 # 
00004 # Redistribution and use in source and binary forms, with or without
00005 # modification, are permitted provided that the following conditions are met:
00006 #     * Redistributions of source code must retain the above copyright
00007 #       notice, this list of conditions and the following disclaimer.
00008 #     * Redistributions in binary form must reproduce the above copyright
00009 #       notice, this list of conditions and the following disclaimer in the
00010 #       documentation and/or other materials provided with the distribution.
00011 #     * Neither the name of the Georgia Tech Research Corporation nor the
00012 #       names of its contributors may be used to endorse or promote products
00013 #       derived from this software without specific prior written permission.
00014 # 
00015 # THIS SOFTWARE IS PROVIDED BY GEORGIA TECH RESEARCH CORPORATION ''AS IS'' AND
00016 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00018 # DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH BE LIABLE FOR ANY DIRECT, INDIRECT,
00019 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00020 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00021 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00022 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00023 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00024 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 #
00026 ## code to control Animatics Smart Servos.
00027 ## author Cressel Anderson, Advait Jain, Hai Nguyen (Healthcare Robotics Lab, Georgia Tech.)
00028 
00029 import serial
00030 import sys,time
00031 from time import sleep
00032 from threading import RLock
00033 import threading
00034 
00035 #import util as ut
00036 #import math_util as mut
00037 
00038 import roslib; roslib.load_manifest('zenither')
00039 import rospy
00040 from hrl_msgs.msg import FloatArray
00041 import hrl_lib.rutils as ru
00042 import hrl_lib.util as ut
00043 
00044 import zenither_config as zc
00045 
00046 class ZenitherCollideException(Exception):
00047     def __init__(self):
00048         pass
00049 
00050 class ZenitherClient:
00051     def __init__(self):
00052         self.listener = ru.FloatArrayListener('zenither_client', 'zenither_pose', 10)
00053 
00054     def pose(self, fresh=True):
00055         v = self.listener.read(fresh)
00056         return v[0,0]
00057 
00058 class PoseBroadcast(threading.Thread):
00059     def __init__(self, zenither, frequency=100):
00060         threading.Thread.__init__(self)
00061         try:
00062             rospy.init_node('ZenitherPose')
00063             print 'ZenitherPose: ros is up!'
00064         except rospy.ROSException:
00065             pass
00066 
00067         self.frequency = frequency
00068         self.zenither  = zenither
00069         self.should_run = True
00070         self.pose       = self.zenither.get_position_meters() 
00071 
00072         name = 'zenither_pose'
00073         print 'PoseBroadcast: publishing', name, 'with type FloatArray'
00074         self.channel    = rospy.Publisher(name, FloatArray)
00075         self.start()
00076 
00077     def run(self): 
00078        print 'PoseBroadcast: started.'
00079        while self.should_run and not rospy.is_shutdown(): 
00080            sleep(1.0/self.frequency)
00081            self.pose = self.zenither.get_position_meters()
00082            self.channel.publish(FloatArray(None, [self.pose]))
00083 
00084     def stop(self):
00085        self.should_run = False 
00086        self.join(3) 
00087        if (self.isAlive()): 
00088            raise RuntimeError("PoseBroadcast: unable to stop thread")
00089 
00090 class Zenither(object):
00091     """
00092        Basic Zenither interface
00093        Note: servo controller will crash if two different processes try to write to
00094              the serial interface at the same time
00095     """
00096     zero_bias = -0.004 #actual height=height reported by zenither+zero_bias
00097     servo = None
00098 
00099     def __init__(self, robot, max_command_retries=15, dev="/dev/robot/zenither",pose_read_thread=False):
00100         ''' robot- 'El-E' or 'HRL2'
00101             pose_read_thread - if you want a separate thread that constantly reads zenither height
00102                                and publishes using ROS.
00103         '''
00104 
00105         if robot not in zc.calib:
00106             raise RuntimeError('unknown robot')
00107         self.robot = robot
00108 
00109         self.dev = dev
00110         self.serial_lock = RLock()
00111         self.servo_start(max_command_retries)
00112 
00113         self.calib = zc.calib[robot]
00114         if self.calib['HAS_BRAKE']:
00115             self.brake_engaged = False
00116 #            self.engage_brake()
00117             self.estop()
00118 
00119         # look at the log message for revision 287 for explanation.
00120         if self.get_variable('a') != '1':
00121             print 'WARNING: it seems that the Zenither has been power cycled'
00122             print 'WARNING: please set_origin for the zenither.'
00123             self.calibrated = False
00124         else:
00125             self.calibrated = True
00126 
00127         # This might cure the sound from the zenither. -- Advait Dec26,2008
00128         # Changes get_position_meters of Dec26,2008 to
00129         # get_motor_temperature_F. since get_position_meters raises
00130         # exception if the zenither is uncalibrated.   -- Advait Nov14,2009
00131         for i in range(10):
00132             self.get_motor_temperature_F()
00133 
00134         if pose_read_thread:
00135             self.broadcast()
00136 
00137     def broadcast(self):
00138         self.broadcaster = PoseBroadcast(self)
00139 
00140     def servo_start(self, max_command_retries):
00141         self.serial_lock.acquire()
00142         try:
00143             #self.servo = serial.Serial("/dev/robot/zenither", timeout=0)
00144             self.servo = serial.Serial(self.dev, timeout=0)
00145         except (serial.serialutil.SerialException), e:
00146             raise RuntimeError("Zenither: Serial port not found!\n")
00147         self.max_command_retries = max_command_retries
00148         if(self.servo == None):
00149             raise RuntimeError("Zenither: Serial port not found!\n")
00150 
00151         #Without this platform will fall while zenith'ing
00152         self.servo.timeout = 1
00153         check = self.get_status_byte()
00154         if(check == ''):
00155             raise RuntimeError("Animatics Servo isn't responding!\n")
00156             self.servo.close()
00157             self.servo = None
00158         else:
00159             t = self.get_motor_temperature_F()
00160             if self.get_motor_temperature_F() >= 140.0:
00161                 t = self.get_motor_temperature_F()
00162                 mesg = "Animatics Servo is too hot: " + t.__str__() + "F"
00163                 raise RuntimeError(mesg)
00164                 self.servo.close()
00165                 self.servo = None
00166             self.inputs_init()
00167             self.servo.write('o=0\n')        #set origin
00168             self.servo.write('E=10000\n')        #set error limit
00169 
00170             #These parameters are only used in position mode.
00171             self.servo.write('A=150\n')      #set accel
00172             self.servo.write('V=100000\n')    #set velocity
00173             self.servo.write('P=2000\n')        #set position
00174             self.servo.write('KG=50\n')      #set gravity compensation
00175             self.servo.write('F\n')          #apply new PID constants
00176 
00177         self.last_position = 0.0
00178             
00179         self.serial_lock.release()
00180 
00181     def reset_serial(self):
00182         self.serial_lock.acquire()
00183         self.servo.flushInput()
00184         self.servo.flushOutput()
00185         self.servo.close()
00186         self.servo_start(self.max_command_retries)
00187         self.serial_lock.release()
00188 
00189     def __del__(self):
00190         self.serial_lock.acquire()
00191         self.servo.close()
00192         self.serial_lock.release()
00193 
00194     def __lock_write(self, line):
00195         self.serial_lock.acquire()
00196         self.servo.write(line)
00197         #print 'Servo send: ',line
00198         self.serial_lock.release()
00199 
00200     def reset(self):
00201         self.__lock_write("Z\n")
00202 
00203     def set_timeout(self,timeout):
00204         self.serial_lock.acquire()
00205         self.servo.timeout = timeout
00206         self.serial_lock.release()
00207 
00208     def turn_off(self):
00209         self.__lock_write("OFF\n")
00210 
00211     def get_status_byte(self):
00212         self.serial_lock.acquire()
00213         self.servo.write("RS\n")
00214         s = self.servo.readline(eol='\r')
00215         self.serial_lock.release()
00216         return s
00217 
00218     def get_status_word(self):
00219         self.serial_lock.acquire()
00220         self.servo.write("RW\n")
00221         s = self.servo.readline(eol='\r')
00222         self.serial_lock.release()
00223         return s
00224 
00225     def report_and_clear(self):
00226         self.serial_lock.acquire()
00227         self.servo.write("RCS1\n")
00228         s = self.servo.readline(eol='\r')
00229         self.serial_lock.release()
00230         return s
00231 
00232     def get_mode(self):
00233         self.serial_lock.acquire()
00234         self.servo.write("RMODE\n")
00235         s = self.servo.readline(eol='\r')
00236         self.serial_lock.release()
00237         return s
00238 
00239     def use_position_mode(self):
00240         if self.calib['HAS_BRAKE']:
00241             self.engage_brake_on_without_trajectory()
00242         self.__lock_write("MP\n")
00243 
00244     def use_velocity_mode(self):
00245         if self.calib['HAS_BRAKE']:
00246             self.engage_brake_on_without_trajectory()
00247         self.__lock_write("MV\n")
00248 
00249     def use_torque_mode(self):
00250         self.__lock_write("MT\n")
00251 
00252     def get_factor(self,type='vel_factor'):
00253         #return self.calib[self.robot][type]
00254         return self.calib[type]
00255 
00256     def set_acceleration(self,a):
00257         '''Sets the acceleration in meters/sec^2'''
00258         factor = self.get_factor(type='acc_factor')
00259         a  = int(round(abs(a/ factor)))
00260         cmd = "A="+str(a)+"\n"
00261         self.__lock_write(cmd)
00262 
00263     def set_velocity(self,v):
00264         '''Sets the velocity in meters/sec'''
00265         factor = self.get_factor(type='vel_factor')
00266         v  = int(round(v/factor))
00267         cmd ="V="+str(v)+"\n"
00268         self.__lock_write(cmd)
00269 
00270     def set_origin(self):
00271         self.__lock_write("O=0\n")
00272         time.sleep(0.1)
00273         self.__lock_write("a 1\n") # zenither is now calibrated.
00274         self.calibrated = True
00275 
00276     def go(self):
00277         self.__lock_write("G\n")
00278 
00279     # This will cut power to the device causing it to fall
00280     # destroying the robot!
00281     # def stop(self):
00282     #     self.servo.write("X\n")
00283 
00284     def estop(self):
00285         self.__lock_write("S\n")
00286         if self.calib['HAS_BRAKE']:
00287             self.engage_brake_on_without_trajectory()
00288 
00289     def set_pos_absolute(self,p):
00290         '''Sets the absolute position in meters'''
00291         factor = self.get_factor(type='pos_factor')
00292         p = int(round(p/factor))
00293         cmd = "P="+str(p)+"\n"
00294         self.__lock_write(cmd)
00295 
00296     def set_pos_relative(self,p):
00297         '''Sets the relative position in meters'''
00298         factor = self.get_factor(type='pos_factor')
00299         p = int(round(p/factor))
00300         cmd = "D="+str(p)+"\n"
00301         self.__lock_write(cmd)
00302 
00303     ## reads a variable. (page 27 of animatics manual)
00304     # e.g. var = 'a' will read the variable a.
00305     def get_variable(self,var):
00306         self.serial_lock.acquire()
00307         self.servo.write('R'+var+'\n')
00308         s = self.servo.readline(eol='\r')
00309         self.serial_lock.release()
00310         return s.replace('\r','')
00311 
00312     def get_position(self):
00313         self.serial_lock.acquire()
00314         #print 'zenither.get_position: lock acquired'
00315         self.servo.write("RP\n")
00316         s = self.servo.readline(eol='\r')
00317         self.serial_lock.release()
00318         #print 'zenither.get_position: lock released'
00319         return s
00320 
00321     def get_position_meters(self):
00322         if self.calibrated == False:
00323             self.estop()
00324             raise RuntimeError('Zenither not calibrated. Please set_origin.')
00325         val = self.get_position().replace('\r','')
00326         while val == '':
00327             #print 'waiting on new position value'
00328             val = self.get_position().replace('\r','')
00329         #print 'val = ',val
00330 
00331         factor = self.get_factor(type='pos_factor')
00332         p = float(val)*factor + self.calib['ZERO_BIAS']
00333         return p
00334 
00335     def set_torque(self,t):
00336         self.__lock_write("T="+str(t)+"\n")
00337 
00338     # FOR TORQUE CONTROL MODE
00339     #
00340     # The motor does not operate as the manual leads one to
00341     # believe. Torque control mode does not control torque. It is a
00342     # very rough approximation to torque control. It is not possible
00343     # to have the motor operate with a specified torque if an external
00344     # torque is being applied to the motor. For instance:
00345     #
00346     # I have -1.0Nm applied to the shaft, and I want to keep the shaft
00347     # stationary. I should apply 1.0Nm to result in a net torque of
00348     # 0Nm (no rotation). This opperates as close to what is expected.
00349     #
00350     # If I want -1.0Nm to be the net force, then I would apply
00351     # 0Nm. The torque is not nearly 0Nm, but is continuous from the
00352     # positive regime to 0Nm.
00353     #
00354     # If I want -1.1Nm to be the net force, then I want to have the
00355     # motor apply -0.1Nm to the shaft. This is not possible with the
00356     # motor.
00357     # 
00358     # In the presence of the external torque it is impossible to
00359     # command a small torque in the same direction from the motor. I
00360     # beleive this is due to the internal control techniques of the
00361     # motor drive, specifically open loop control of torque. If
00362     # Animatics were to actively control the motor current, continuous
00363     # control of torque would be possible even in the presence of
00364     # external torques.
00365     # 
00366     # Additionally, I have explored other techniques to accurately
00367     # control motor current/torque such as monitoring current. The
00368     # only current available for monitoring is the input current to
00369     # the device. It includes power consumed by the drive and seems
00370     # unsuitible for motor control.
00371     # 
00372     # The positive regime works fine, but the transition can be
00373     # atrocious under external torques. Position mode is the only
00374     # possible control mode for smooth quick motion downward for the
00375     # zenither. I suspect we could do better for collision detection
00376     # with the actuator in position control mode, but it does not
00377     # involve the use of torque mode. This is the case unless
00378     # operating exclusively in the positive torque mode is an
00379     # acceptible solution. This is the case for the SM2315DT and I
00380     # suspect all SmartMotor servos from Animatics.
00381 
00382 
00383     def zenith(self, torque=None):
00384         if torque == None:
00385             torque=self.calib['zenith_torque']
00386 
00387         #print "Zenither: going up at torque", torque
00388         self.serial_lock.acquire()
00389         if self.robot == 'El-E':
00390             self.servo.write('KGOFF\n')       #disable gravity compensation
00391         self.use_torque_mode()
00392         factor = self.get_factor(type='pos_factor')
00393         self.set_torque(int(torque*factor/abs(factor))) #use factor to determine sign
00394         if self.calib['HAS_BRAKE']:
00395             self.disengage_brake()
00396         #print 'setting torque ',int(torque*factor/abs(factor)) #use factor to determine sign
00397         self.serial_lock.release()
00398 
00399     def nadir(self, torque=None):
00400         self.serial_lock.acquire()
00401         if torque == None:
00402             torque = self.calib['nadir_torque']
00403         if self.robot == 'El-E':
00404             self.servo.write('KGOFF\n')       #disable gravity compensation
00405         self.use_torque_mode()
00406         factor = self.get_factor(type='pos_factor')
00407         #print 'torque', int(torque*factor/abs(factor))
00408         self.set_torque(int(torque*factor/abs(factor))) #use factor to determine sign)
00409         if self.calib['HAS_BRAKE']:
00410             self.disengage_brake()
00411         else:
00412             print 'no brake'
00413         #print 'setting torque ',int(torque*factor/abs(factor)) #use factor to determine sign
00414         self.serial_lock.release()
00415 
00416     def torque_move_position(self,height,speed='fast',exception=True):
00417         ''' speed - 'fast','slow','snail'
00418             exception - if True then throws exception in case of collision.
00419             moves till height or if it detects collision.
00420             height - height of the bottom point of carriage above the ground.
00421         '''
00422         #if self.calib['robot'] == 'El-E':
00423         #    raise RuntimeError('Advait, please check this function on El-E')
00424 
00425         position_zenither_coord = height - self.calib['ZERO_BIAS']
00426         position_zenither_coord = self.limit_position(position_zenither_coord)
00427 
00428         if height>self.calib['max_height']:
00429             height = self.calib['max_height']
00430 
00431         if height<self.calib['min_height']:
00432             height = self.calib['min_height']
00433         
00434         curr_height = self.get_position_meters()
00435 
00436         if abs(curr_height-height)<0.002:
00437             return
00438 
00439         if curr_height>height:
00440             if speed=='fast':
00441                 torque=self.calib['down_fast_torque']
00442             elif speed=='slow':
00443                 torque=self.calib['down_slow_torque']
00444             elif speed=='snail':
00445                 torque=self.calib['down_snail_torque']
00446             else:
00447                 print 'zenither.torque_move_position: unknown speed- ',speed
00448                 sys.exit()
00449             self.torque_go_down(height,torque)
00450 
00451         if curr_height<height:
00452             if speed=='fast':
00453                 torque=self.calib['up_fast_torque']
00454             elif speed=='slow':
00455                 torque=self.calib['up_slow_torque']
00456             elif speed=='snail':
00457                 torque=self.calib['up_snail_torque']
00458             else:
00459                 print 'zenither.torque_move_position: unknown speed- ',speed
00460                 sys.exit()
00461             self.torque_go_up(height,torque)
00462         error = height-self.get_position_meters()
00463         if abs(error)>0.005 and exception == True:
00464             raise ZenitherCollideException
00465 
00466     def torque_go_down(self,height,start_torque,dist_list=[0.15,0.05]):
00467         ''' dist list - how much distance to move slow and snail.
00468             height - is in zenither coord. not height of carriage above the
00469                      ground.
00470         '''
00471         #if self.calib['robot'] == 'El-E':
00472         #    raise RuntimeError('Advait, please check this function on El-E')
00473 
00474         slow_torque = self.calib['down_slow_torque']
00475         if self.calib['robot'] == 'HRL2':
00476             slow_torque = self.calib['down_fast_torque']
00477         snail_torque = self.calib['down_snail_torque']
00478 
00479         h_start = self.get_position_meters()
00480         h_start = self.get_position_meters()
00481 
00482         if (h_start-height) < (dist_list[1]+0.01):
00483             self.nadir(snail_torque)
00484             current_torque = snail_torque
00485         elif (h_start-height) < (dist_list[0]+0.02):
00486             self.nadir(slow_torque)
00487             current_torque = slow_torque
00488         else:
00489             self.nadir(start_torque)
00490             current_torque = start_torque
00491 
00492         h_start = self.get_position_meters()
00493         h_start = self.get_position_meters()
00494 
00495         while h_start > height:
00496             time.sleep(0.01)
00497             h_now = self.get_position_meters()
00498             if (h_now-height) < dist_list[1]:
00499                 if current_torque != snail_torque:
00500                     self.nadir(snail_torque)
00501                     current_torque = snail_torque
00502             elif (h_now-height) < dist_list[0]:
00503                 if current_torque != slow_torque:
00504                     self.nadir(slow_torque)
00505                     current_torque = slow_torque
00506 
00507             if h_now == h_start:
00508                 # stopped moving due to a collision
00509                 break
00510             h_start = h_now
00511 
00512         self.estop()
00513         #print self.get_position_meters()
00514 
00515     def torque_go_up(self,height,start_torque,dist_list=[0.15,0.05]):
00516         ''' dist list - how much distance to move slow and snail.
00517             height - is in zenither coord. not height of carriage above the
00518                      ground.
00519         '''
00520         #if self.calib['robot'] == 'El-E':
00521         #    raise RuntimeError('Advait, please check this function on El-E')
00522 
00523         slow_torque  = self.calib['up_slow_torque']
00524         snail_torque = self.calib['up_snail_torque']
00525 
00526         h_start = self.get_position_meters()
00527         h_start = self.get_position_meters()
00528 
00529         if (height-h_start) < (dist_list[1]+0.01):
00530             self.zenith(snail_torque)
00531             current_torque = snail_torque
00532         elif (height-h_start) < (dist_list[0]+0.02):
00533             self.zenith(slow_torque)
00534             current_torque = slow_torque
00535         else:
00536             self.zenith(start_torque)
00537             current_torque = start_torque
00538 
00539         h_start = self.get_position_meters()
00540         h_start = self.get_position_meters()
00541 
00542         while h_start < height:
00543             h_now = self.get_position_meters()
00544             time.sleep(0.01)
00545             if (height-h_now) < dist_list[1]:
00546                 if current_torque != snail_torque:
00547                     self.zenith(snail_torque)
00548                     current_torque = snail_torque
00549             elif (height-h_now) < dist_list[0]:
00550                 if current_torque != slow_torque:
00551                     self.zenith(slow_torque)
00552                     current_torque = slow_torque
00553 
00554             if h_now == h_start:
00555                 # stopped moving due to a collision
00556                 break
00557             h_start = h_now
00558 
00559         self.estop()
00560         #print self.get_position_meters()
00561 
00562     def go_height_blocking(self, height):
00563         """ takes zenither up or down to height (moves slowly)
00564             blocking call
00565         """
00566         curHeight = self.get_position_meters()
00567         height = height-curHeight
00568         self.go_relative_blocking(height)
00569 
00570     def go_height(self, z, function=None, down_torque=0, up_torque=200):
00571         if self.robot != 'El-E':
00572             raise RuntimeError(
00573                 'This function is unemplemented on robot\'s other than El-E')
00574         #z = mut.bound(z,0.0, .89)
00575         z = ut.bound(z,0.0, .89)
00576 
00577         initial_direction = None
00578         #if not ut.approx_equal(z, self.broadcaster.pose):
00579         if not ut.approx_equal(z, self.get_position_meters()):
00580             #if z > self.broadcaster.pose:
00581             if z > self.get_position_meters():
00582                 self.zenith(torque = up_torque)
00583                 initial_direction = 'up'
00584             else:
00585                 self.zenith(torque = down_torque)
00586                 initial_direction = 'down'
00587         else:
00588             return
00589 
00590         there         = False
00591         #while not ut.approx_equal(z, self.broadcaster.pose):
00592         while not ut.approx_equal(z, self.get_position_meters()):
00593             if function != None:
00594                 #ret = function(self.broadcaster.pose)
00595                 ret = function(self.get_position_meters())
00596                 if ret:
00597                     break
00598 
00599             #if initial_direction == 'up' and self.broadcaster.pose > z:
00600             if initial_direction == 'up' and self.get_position_meters() > z:
00601                 break
00602 
00603             if initial_direction == 'down' and self.get_position_meters() < z:
00604                 break
00605 
00606         self.estop()
00607 
00608     def limit_position(self, position):
00609 
00610         position = ut.unipolar_limit(position, 
00611                                      self.calib['POS_MAX'])
00612         return position
00613 
00614     def limit_velocity(self,velocity):
00615         if velocity == None:
00616             velocity = self.calib['VEL_DEFAULT']
00617             return velocity
00618 
00619         velocity = ut.unipolar_limit(velocity, 
00620                                      self.calib['VEL_MAX'])
00621 
00622         return velocity
00623 
00624     def limit_acceleration(self,acceleration):
00625         if acceleration == None:
00626             acceleration = self.calib['ACC_DEFAULT']
00627             return acceleration
00628 
00629         acceleration = ut.unipolar_limit(acceleration, 
00630                                      self.calib['ACC_MAX'])
00631 
00632         return acceleration
00633 
00634     def move_position(self,position, velocity=None , acceleration=None, 
00635                       blocking = True, relative=False, approximate_pose = True):
00636 
00637         if self.robot != 'El-E' and self.robot != 'test_rig':
00638             raise RuntimeError(
00639                 'This function is unemplemented on robot\'s other than El-E, test_rig')
00640         if self.calib['HAS_BRAKE']:
00641             self.disengage_brake()
00642 
00643         if position>self.calib['max_height']:
00644             position = self.calib['max_height']
00645 
00646         if position<self.calib['min_height']:
00647             position = self.calib['min_height']
00648 
00649         self.use_position_mode()       #position mode
00650 
00651         if relative:
00652             position = self.get_position_meters() + position
00653         
00654         position_zenither_coord = position - self.calib['ZERO_BIAS']
00655         position_zenither_coord = self.limit_position(position_zenither_coord)
00656         
00657         acceleration = self.limit_acceleration( acceleration )
00658         velocity = self.limit_velocity( velocity )
00659 
00660         p = self.get_position_meters()
00661 
00662         if p >= position:
00663             #needs to go down
00664             #print 'needs to go down'
00665             self.serial_lock.acquire()
00666             self.servo.write('KGON\n')       #enable gravity compensation
00667             self.serial_lock.release()
00668             if velocity > 4.0 or velocity < -4.0:
00669                 velocity = 4.0               #not faulting here, just caution
00670 
00671         else:
00672             #needs to go up
00673             #print 'needs to go up'
00674             self.serial_lock.acquire()
00675             self.servo.write('KGOFF\n')       #disable gravity compensation
00676             self.serial_lock.release()
00677             if velocity > 3.0 or velocity < -3.0:
00678                 velocity = 3.0               #ascent faults if velocity is too high
00679 
00680         self.set_pos_absolute(position_zenither_coord)
00681 
00682         self.set_velocity(velocity)
00683         self.set_acceleration(acceleration)
00684         self.go()
00685 
00686         if blocking:
00687             have_not_moved = 0
00688             #current_pose = self.broadcaster.pose
00689             current_pose = self.get_position_meters()
00690             last_pose = None
00691             print 'zenither.move_position: blocking...'
00692             while abs(current_pose - position) > 0.01:
00693                 time.sleep(200/1000.0)
00694                 current_pose = self.get_position_meters()
00695                 #print abs(current_pose - position)
00696             print 'zenither.move_position: done'
00697 
00698         if self.calib['HAS_BRAKE']:
00699             self.engage_brake()
00700 
00701 
00702     def check_mode(self):
00703         pass
00704 
00705     def checkbits(self):
00706         self.serial_lock.acquire()
00707         self.servo.write("c=UCI\n")
00708         self.servo.write("Rc\n")
00709         c = self.servo.readline(eol='\r')
00710         self.servo.write("d=UDI\n")
00711         self.servo.write("Rd\n")
00712         d = self.servo.readline(eol='\r')
00713         self.serial_lock.release()
00714         return [c,d]
00715 
00716     def get_motor_torque(self):
00717         self.serial_lock.acquire()
00718         self.servo.write("t=T\n")
00719         self.servo.write("Rt\n")
00720         t = self.servo.readline(eol='\r')
00721         self.serial_lock.release()
00722         return t
00723 
00724     def get_motor_temperature_F(self):
00725         return self.get_motor_temperature_C()*9.0/5.0 + 32.0
00726 
00727     def get_motor_temperature_C(self):
00728         self.serial_lock.acquire()
00729         self.servo.write("t=TEMP\n")
00730         self.servo.write("Rt\n")
00731         t = float(self.servo.readline(eol='\r'))
00732         self.serial_lock.release()
00733         return t
00734 
00735     def inputs_init(self):
00736         self.serial_lock.acquire()
00737         self.servo.write("UCI\n")#Set pin C to input
00738         self.servo.write("UDI\n")#Set pin D to input
00739         self.serial_lock.release()
00740 
00741     def engage_brake(self):
00742         self.serial_lock.acquire()
00743         if self.brake_engaged == False:
00744             self.servo.write("BRKENG\n") #Engage the brake
00745             self.brake_engaged = True
00746         self.serial_lock.release()
00747 
00748     def disengage_brake(self):
00749         self.serial_lock.acquire()
00750         if self.brake_engaged:
00751             self.servo.write("BRKRLS\n") #Disengage the brake
00752             self.brake_engaged = False
00753         self.serial_lock.release()
00754 
00755     def engage_brake_when_not_servoing(self):
00756         self.serial_lock.acquire()
00757         if self.brake_engaged == False:
00758             self.servo.write("BRKSRV\n") #Engage the brake when not
00759                                          #servoing
00760             self.brake_engaged = True
00761         self.serial_lock.release()
00762 
00763     def engage_brake_on_without_trajectory(self):
00764         self.serial_lock.acquire()
00765         if self.brake_engaged == False:
00766             self.servo.write("BRKTRJ\n") #Engage the brake when not
00767                                          #executing a trajectory
00768             self.brake_engaged = True
00769         self.serial_lock.release()
00770 
00771 
00772 #    def test_cam_mode(self):
00773 #        cmd='MF4\n'
00774 #        self.__lock_write(cmd)
00775 #        cmd='BASE=10000\n'
00776 #        self.__lock_write(cmd)
00777 #        cmd='SIZE=4\n'
00778 #        self.__lock_write(cmd)
00779 #        cmd='E=10000\n'
00780 #        self.__lock_write(cmd)
00781 #        cmd='aw[0] 0 5000 10000.\n'
00782 #        self.__lock_write(cmd)
00783 #        cmd='MC\n'
00784 #        self.__lock_write(cmd)
00785 #        print 'Sleeping before issuing the go command.'
00786 #        time.sleep(1.)
00787 #        cmd='G\n'
00788 #        self.__lock_write(cmd)
00789 #        print 'sent the go command.'
00790 
00791 
00792 
00793 


zenither
Author(s): Cressel Anderson, Advait Jain, Hai Nguyen, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab at Georgia Tech
autogenerated on Wed Nov 27 2013 11:54:59