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

Source Code for Module dics.linear

  1  from mechanism import mechanism 
  2  import ConfigParserRT 
  3  import cortex 
  4  import logging 
  5  import time 
  6   
7 -class linear(mechanism):
8 """Class representing a general linear mechanism, based on the 9 generic mechanism class from mechanism.py. It adds software motion 10 limits and a units/gear ratio property, with corresponding move 11 commands enabling moves in terms of physical units rather than motor 12 steps."""
13 - def __init__(self, cortex, icu_num, axis_num, \ 14 base_speed, max_speed, acceleration, deceleration, \ 15 position, lower_limit, upper_limit, units, name='linear'):
16 """ 17 Initialiser for linear mechanism class. 18 19 Arguments: 20 cortex: String containing the name of the cortex based 21 ICU daisy chain instance that this mechanism is a 22 part of. 23 icuNum: Which ICU in the chain this mechanism is connected 24 to. 25 axisNum: Which axis of the ICU the mechansism is connected 26 to. 27 baseSpeed: Starting speed (units per sec) 28 maxSpeed: Peak speed (units per sec?) 29 acceleration:Acceleration (units per sec^2) 30 deceleration:Deceleration (units per sec^2) 31 position: Initial position of the mechanism (units) 32 lower_limit: Lower limit of allowed movement range (units) 33 upper_limit: Upper limit of allowed movement range (units) 34 units: Number of steps corresponding to one unit of movement 35 name: Label used for logging purposes. 36 """ 37 # Store the units 38 self.units = float(units) 39 # Convert the limits into step based units and store them 40 self.lowerLimit = int(float(lower_limit) * self.units) 41 self.upperLimit = int(float(upper_limit) * self.units) 42 # Convert the remaining parameters into step based units. 43 base_speed = int(float(base_speed) * self.units) 44 max_speed = int(float(max_speed) * self.units) 45 acceleration = int(float(acceleration) * self.units) 46 deceleration = int(float(deceleration) * self.units) 47 position = int(float(position) * self.units) 48 # Call the base class initialiser to deal with the remaining params. 49 mechanism.__init__(self, cortex, icu_num, axis_num, \ 50 base_speed, max_speed, acceleration, deceleration, \ 51 position, name)
52
53 - def updateConfig(self, config):
54 """ 55 Should be called by the parent instrument object's destructor 56 to enable status information to be saved to file on exit. 57 58 Takes a ConfigParserRT.SafeConfigParser object as argument. 59 """ 60 self.logger.debug("updateConfig() called") 61 if isinstance(config, ConfigParserRT.SafeConfigParser): 62 config.set(self.name, 'units', str(self.units)) 63 config.set(self.name, 'lower_limit', \ 64 str(self.lowerLimit / self.units)) 65 config.set(self.name, 'upper_limit', \ 66 str(self.upperLimit / self.units)) 67 config.set(self.name, 'base_speed', \ 68 str(self.baseSpeed / self.units)) 69 config.set(self.name, 'max_speed', \ 70 str(self.maxSpeed / self.units)) 71 config.set(self.name, 'acceleration', \ 72 str(self.acceleration / self.units)) 73 config.set(self.name, 'deceleration', \ 74 str(self.deceleration / self.units)) 75 config.set(self.name, 'position', \ 76 str(self.position / self.units)) 77 else: 78 self.logger.critical("Invalid argument to updateConfig(%s)" \ 79 % repr(config)) 80 self.logger.critical("Unable to save status data")
81
82 - def setupLinear(self):
83 """ 84 Performs an automatic setup procedure. It is important that the 85 limit switches are working correctly otherwise this routine might 86 result in damage. 87 """ 88 self.logger.debug('setupLinear() called.') 89 # First check that the ICU isn't busy doing something else. 90 if self.cortex.isActive(): 91 self.logger.critical(\ 92 'Attempt to move mechanism when ICU busy, ignored.') 93 self.logger.critical('setupLinear() failed.') 94 return 95 96 # Ensure that we're not already against the lower limit. 97 lstatus = self.cortex.getLimitStatus(self.icuNum) 98 while lstatus == -1: 99 mechanism.moveBy(self, +10) 100 lstatus = self.cortex.getLimitStatus(self.icuNum) 101 102 # Now find the position of the lower limit switch. 103 self.logger.debug('Moving to lower limit.') 104 self.cortex.setOutput(self.axisNum, self.icuNum) 105 self.cortex.setMotorParams(self.baseSpeed, self.maxSpeed, \ 106 self.acceleration, self.deceleration, 107 self.icuNum) 108 self.cortex.setDatum(self.position) 109 self.cortex.moveLimit(-1, self.icuNum) 110 while self.cortex.isActive(self.icuNum): 111 # Wait until the move is complete. 112 time.sleep(1) 113 self.position = self.cortex.getPosition(self.icuNum) 114 # Quick check we're at the limit we expect to be at... 115 lstatus = self.cortex.getLimitStatus(self.icuNum) 116 if lstatus == +1: 117 self.cortex.setOutput(7, self.icuNum) 118 self.logger.critical('Ended up at wrong limit...') 119 self.logger.critical('setupLinear() failed.') 120 return 121 elif lstatus == 0: 122 self.cortex.setOutput(7, self.icuNum) 123 self.logger.critical('Failed to reach limit switch.') 124 self.logger.critical('setupLinear() failed.') 125 return 126 # Record the position of the lower limit switch. 127 lower = self.cortex.getPosition(self.icuNum) 128 129 # Now find the position of the upper limit switch. 130 self.logger.debug('Moving to upper limit.') 131 self.cortex.moveLimit(+1, self.icuNum) 132 while self.cortex.isActive(self.icuNum): 133 # Wait until the move is complete. 134 time.sleep(1) 135 self.position = self.cortex.getPosition(self.icuNum) 136 # Quick check we're at the limit we expect to be at... 137 lstatus = self.cortex.getLimitStatus(self.icuNum) 138 if lstatus == -1: 139 self.cortex.setOutput(7, self.icuNum) 140 self.logger.critical('Ended up at wrong limit...') 141 self.logger.critical('setupLinear() failed.') 142 return 143 elif lstatus == 0: 144 self.cortex.setOutput(7, self.icuNum) 145 self.logger.critical('Failed to reach limit switch.') 146 self.logger.critical('setupLinear() failed.') 147 return 148 # Record the position of the upper limit switch. 149 upper = self.cortex.getPosition(self.icuNum) 150 151 range = upper - lower 152 self.position = int(range / 2.0) 153 self.upperLimit = int(0.9 * range / 2.0) 154 self.lowerLimit = -self.upperLimit 155 156 self.logger.debug('Moving to central position.') 157 self.moveTo(0)
158
159 - def getUnits(self):
160 """ 161 Return the number of steps per unit of movement 162 """ 163 self.logger.debug('getUnits() called') 164 return self.units
165
166 - def getLimits(self):
167 """ 168 Returns the allowed range of movement of the mechanism as tuple of 169 (lowerLimit, upperLimit), in the units specified by setUnits. 170 """ 171 self.logger.debug('getLimits() called') 172 return (self.lowerLimit/self.units, self.upperLimit/self.units)
173
174 - def getMotorParams(self):
175 """ 176 Returns a tuple containing the four motor motion parameters, 177 baseSpeed, maxSpeed, acceleration, deceleration, in terms of 178 the units specified with setUnits. 179 """ 180 self.logger.debug('getMotorParams() called') 181 return tuple(\ 182 [item/self.units for item in mechanism.getMotorParams(self)])
183
184 - def getPosition(self):
185 """ 186 Returns the current mechanism position, in units defined by 187 setUnits(). 188 """ 189 self.logger.debug('getPosition() called') 190 return mechanism.getPosition(self) / self.units
191
192 - def moveBy(self, distance):
193 """ 194 Move the mechanism by a given distance. Units are defined by 195 setUnits() 196 """ 197 self.logger.debug('moveBy(%d) called' % distance) 198 # Calculate the new position 199 newPosition = self.position / self.units + distance 200 # Call moveTo 201 self.moveTo(newPosition)
202
203 - def moveTo(self, newPosition):
204 """ 205 Move the mechanism to the given position. Units are defined by 206 setUnits(). 207 """ 208 self.logger.debug('moveTo(%d) called' % newPosition) 209 # Convert the requested position to steps 210 newPosition = newPosition * self.units 211 # Check software limits 212 if newPosition >= self.lowerLimit and newPosition <= self.upperLimit: 213 mechanism.moveBy(self, (newPosition - self.position)) 214 elif newPosition < self.lowerLimit: 215 self.logger.critical(\ 216 'Attempt to move beyond lower limit in moveTo(%d), ignored' \ 217 % (newPosition / self.units)) 218 elif newPosition > self.upperLimit: 219 self.logger.critical(\ 220 'Attempt to move beyond upper limit in moveTo(%d), ignored' \ 221 % (newPosition / self.units))
222
223 - def setUnits(self, units):
224 """ 225 Sets the number of steps per unit of movement. 226 """ 227 self.logger.debug('setUnits(%d) called' % units) 228 if units > 0: 229 self.units = units 230 else: 231 self.loggger.warning("Negative argument in setUnits(%d), 'fixed'" \ 232 % units) 233 self.units = abs(units)
234
235 - def setLimits(self, lowerLimit, upperLimit):
236 """ 237 Set the allowed range of movement of the mechanism. Takes two 238 arguments, the lower and upper limits of the range. Units are 239 as defined by setUnits. 240 """ 241 self.logger.debug('setLimits(%d, %d) called' % \ 242 (lowerLimit, upperLimit)) 243 if lowerLimit < upperLimit: 244 self.lowerLimit, self.upperLimit = lowerLimit * self.units, \ 245 upperLimit * self.units 246 elif upperLimit < lowerLimit: 247 self.logger.warning(\ 248 "Limits wrong way round in setLimits(%d, %d), 'fixed'" \ 249 % (lowerLimit, upperLimit)) 250 self.lowerLimit, self.upperLimit = upperLimit * self.units, \ 251 lowerLimit * self.units 252 else: 253 self.logger.critical(\ 254 'Lower and upper limits equal in setLimits(%d, %d), ignored' \ 255 % (lowerLimit, upperLimit))
256
257 - def setMotorParams(self, baseSpeed, maxSpeed, acceleration, deceleration):
258 """ 259 Sets the four motor motion parameters, baseSpeed, maxSpeed, 260 acceleration and deceleration. Takes 4 integer arguments. 261 Units are as defined by setUnits. 262 """ 263 self.logger.debug('setMotorParams(%i, %i, %i, %i) called' % \ 264 (baseSpeed, maxSpeed, acceleration, deceleration)) 265 mechanism.setMotorParams(self, baseSpeed * self.units, \ 266 maxSpeed * self.units, \ 267 acceleration * self.units, \ 268 deceleration * self.units)
269
270 - def setPosition(self, new_position=0):
271 """ 272 Defines the current mechanism position to be equal to the single 273 integer argument. If no argument is given, the mechanism position 274 is zeroed. Units used are as defined in setUnits(). 275 """ 276 self.logger.debug('setPosition(%d) called' % new_position) 277 mechanism.setPosition(self, new_position * self.units)
278