1 from mechanism import mechanism
2 import ConfigParserRT
3 import cortex
4 import logging
5 import time
6
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
38 self.units = float(units)
39
40 self.lowerLimit = int(float(lower_limit) * self.units)
41 self.upperLimit = int(float(upper_limit) * self.units)
42
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
49 mechanism.__init__(self, cortex, icu_num, axis_num, \
50 base_speed, max_speed, acceleration, deceleration, \
51 position, name)
52
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
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
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
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
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
112 time.sleep(1)
113 self.position = self.cortex.getPosition(self.icuNum)
114
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
127 lower = self.cortex.getPosition(self.icuNum)
128
129
130 self.logger.debug('Moving to upper limit.')
131 self.cortex.moveLimit(+1, self.icuNum)
132 while self.cortex.isActive(self.icuNum):
133
134 time.sleep(1)
135 self.position = self.cortex.getPosition(self.icuNum)
136
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
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
160 """
161 Return the number of steps per unit of movement
162 """
163 self.logger.debug('getUnits() called')
164 return self.units
165
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
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
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
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
199 newPosition = self.position / self.units + distance
200
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
210 newPosition = newPosition * self.units
211
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
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
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