Package dics :: Module mechanism
[hide private]
[frames] | no frames]

Source Code for Module dics.mechanism

  1  import ConfigParserRT 
  2  import cortex 
  3  import logging 
  4  import time 
  5   
6 -class mechanism:
7 """ 8 Base clase for instrument mechanisms. Stores mechanism status 9 information and provides methods corresponding to basic mechanism 10 actions which dispacth the appropriate sequence of commands to a 11 cortex instance. 12 """
13 - def __init__(self, cortex, icu_num, axis_num, \ 14 base_speed, max_speed, acceleration, deceleration, \ 15 position, name='mechanism'):
16 """ 17 Initialiser for mechanism class. 18 19 Arguments: 20 cortex: The cortex based ICU daisy chain instance that this 21 mechanism is a part of. 22 icuNum: Which ICU in the chain this mechanism is connected 23 to. 24 axisNum: Which axis of the ICU the mechansism is connected 25 to. 26 baseSpeed: Starting speed (steps/half steps per sec?) 27 maxSpeed: Peak speed (steps/half steps per sec?) 28 acceleration:Acceleration (steps/half steps per sec^2?) 29 deceleration:Deceleration (steps/half steps per sec^2?) 30 position: Initial position of the mechanism (steps) 31 name: Label used for logging purposes. 32 """ 33 # Store basic 'identity' of the mechanism 34 self.name = name 35 self.cortex = cortex 36 self.icuNum = int(icu_num) 37 self.axisNum = int(axis_num) 38 # Store motor parameters 39 self.baseSpeed = int(base_speed) 40 self.maxSpeed = int(max_speed) 41 self.acceleration = int(acceleration) 42 self.deceleration = int(deceleration) 43 # Status of the mechanism 44 self.position = int(position) 45 # Set up logging 46 self.logger = logging.getLogger(name) 47 # Say something 48 self.logger.info('Assigned to ICU %i, axis %i of %s' \ 49 % (self.icuNum, self.axisNum, self.cortex.name))
50
51 - def updateConfig(self, config):
52 """ 53 Should be called by the parent instrument object's destructor 54 to enable status information to be saved to file on exit. 55 56 Takes a ConfigParserRT.SafeConfigParser object as argument. 57 """ 58 self.logger.debug("updateConfig() called.") 59 if isinstance(config, ConfigParserRT.SafeConfigParser): 60 config.set(self.name, 'base_speed', str(self.baseSpeed)) 61 config.set(self.name, 'max_speed', str(self.maxSpeed)) 62 config.set(self.name, 'acceleration', str(self.acceleration)) 63 config.set(self.name, 'deceleration', str(self.deceleration)) 64 config.set(self.name, 'position', str(self.position)) 65 else: 66 self.logger.critical("Invalid argument to updateConfig(%s)" \ 67 % repr(config)) 68 self.logger.critical("Unable to save status data")
69
70 - def getMotorParams(self):
71 """ 72 Returns a tuple of the four motor motion parameters, baseSpeed, 73 maxSpeed, acceleration, deceleration. 74 """ 75 params = (self.baseSpeed, self.maxSpeed, self.acceleration, \ 76 self.deceleration) 77 self.logger.debug('getMotorParams() called') 78 return params
79
80 - def getPosition(self):
81 """ 82 Returns the current motor position. 83 """ 84 self.logger.debug('getPosition() called') 85 return self.position
86
87 - def moveBy(self, steps, blocking=True):
88 """ 89 Initiates a movement of the mechanism by a given number of steps. 90 Second, optional, boolean argument specifies whether the call 91 should block until the movement has been completed or return 92 immediately (default is True). 93 """ 94 self.logger.debug('moveBy(%i, %i) called' % (steps, blocking)) 95 # First of all check that the ICU isn't busy. 96 if self.cortex.isActive(self.icuNum): 97 self.logger.critical(\ 98 'Attempt to move mechanism when ICU busy, ignored.') 99 return 100 # Activate the relevant axis 101 self.cortex.setOutput(self.axisNum, self.icuNum) 102 # Check the limit switches. If we're trying to move in the direction 103 # of a made limit then refuse to move at all. If it appears we're 104 # moving away from a limit log a warning but do it anyway. 105 # NB If both limits are made the cortex card will return an arbitrary 106 # result. 107 test = steps * self.cortex.getLimitStatus(self.icuNum) 108 if test > 0: 109 self.logger.critical(\ 110 'Attempt to move in direction of a made limit, ignored') 111 return 112 if test < 0: 113 self.logger.warning('Moving away from a made limit') 114 # Set the move going. 115 self.logger.debug('Moving %i steps' % steps) 116 self.cortex.setMotorParams(self.baseSpeed, self.maxSpeed, \ 117 self.acceleration, self.deceleration, 118 self.icuNum) 119 self.cortex.setDatum(self.position, self.icuNum) 120 self.cortex.move(steps, self.icuNum) 121 if blocking: 122 # Wait for an (under)estimate of the time it'll take to 123 # complete the move. 124 time.sleep(abs(steps)/self.maxSpeed) 125 # Periodically quiz the ICU to see if the move has finished. 126 while self.cortex.isActive(self.icuNum): 127 time.sleep(1) 128 # Check we didn't hit the limits during the move. 129 limit_status = self.cortex.getLimitStatus(self.icuNum) 130 if limit_status: 131 self.logger.warning('Limit switch made in direction %i' % \ 132 limit_status) 133 # Can now disable the axis 134 self.cortex.setOutput(7, self.icuNum) 135 # Get final position from ICU to update internal record 136 # May add some extra sanity checking here. 137 self.position = self.cortex.getPosition(self.icuNum) 138 else: 139 self.logger.critical('Non-blocking move not implemented!') 140 self.cortex.setOutput(7, self.icuNum)
141 # TODO: Fire off a worker thread to monitor the move before 142 # returning. 143
144 - def moveTo(self, new_position, blocking=True):
145 self.logger.debug('moveTo(%i, %i) called' % (new_position, blocking)) 146 self.moveBy((new_position - self.position), blocking)
147
148 - def setMotorParams(self, baseSpeed, maxSpeed, acceleration, deceleration):
149 """ 150 Sets the four motor motion parameters, baseSpeed, maxSpeed, 151 acceleration and deceleration. Takes 4 integer arguments. 152 """ 153 self.logger.debug('setMotorParams(%i, %i, %i, %i) called' % \ 154 (baseSpeed, maxSpeed, acceleration, deceleration)) 155 # TODO: Need some sanity checking of the numbers here, really... 156 self.baseSpeed = baseSpeed 157 self.maxSpeed = maxSpeed 158 self.acceleration = acceleration 159 self.deceleration = deceleration
160
161 - def setPosition(self, new_position=0):
162 """ 163 Defines the current mechanism position to be equal to the single 164 integer argument. If no argument is given, the mechanism position 165 is zeroed. 166 """ 167 self.logger.debug('setPosition(%i) called' % new_position) 168 # TODO: When non-blocking moves are implemented will want to 169 # prevent this being done during a move, or confusion 170 # will result. 171 self.position = int(new_position)
172