Module Gear
[frames] | no frames]

Source Code for Module Gear

  1  # Gear.java 
  2   
  3  ''' 
  4   This software is part of the EV3BrickPi library. 
  5   It is Open Source Free Software, so you may 
  6   - run the code for any purpose 
  7   - study how the code works and adapt it to your needs 
  8   - integrate all or parts of the code in your own programs 
  9   - redistribute copies of the code 
 10   - improve the code and release your improvements to the public 
 11   However the use of the code is entirely your responsibility. 
 12  ''' 
 13   
 14  from Motor import Motor, MotorPort 
 15  import SharedConstants 
 16  from Tools import * 
 17  from LegoRobot import LegoRobot 
 18  import time 
 19  from threading import Thread 
 20   
21 -class BrakeThread(Thread):
22 - def __init__(self, gear):
23 Thread.__init__(self) 24 self.gear = gear 25 self.isRunning = False
26
27 - def run(self):
28 Tools.debug("Break thread started") 29 self.isRunning = True 30 self.isFinished = False 31 t = 0 32 while self.isRunning: 33 Tools.delay(10) 34 t += 10 35 if t >= SharedConstants.GEAR_BREAK_DELAY: 36 Tools.debug("Break thread stops gear") 37 self.isRunning = False 38 self.gear.mot1.stop() 39 self.gear.mot2.stop() 40 self.gear.gearState = GearState.STOPPED 41 42 Tools.debug("Break thread finished") 43 self.isFinished = True
44
45 -class GearState():
46 FORWARD = "FORWARD" 47 BACKWARD = "BACKWARD" 48 STOPPED = "STOPPED" 49 LEFT = "LEFT" 50 RIGHT = "RIGHT" 51 LEFTARC = "LEFTARC" 52 RIGHTARC = "RIGHTARC" 53 UNDEFINED = "UNDEFINED"
54
55 -class Gear():
56 ''' Class that represents the combination of two motors on an axis 57 to perform a car-like movement. 58 '''
59 - def __init__(self, port1 = MotorPort.A, port2 = MotorPort.B):
60 ''' 61 Creates a gear instance with left motor plugged into port1, right motor plugged into port2 62 (defaults: port1 = MotorPort.A, port2 = MotorPort.B). 63 ''' 64 self.mot1 = Motor(port1) 65 self.mot2 = Motor(port2) 66 self.gearState = GearState.STOPPED 67 self.speed = SharedConstants.GEAR_DEFAULT_SPEED 68 self.mot1.setSpeed(self.speed) 69 self.mot2.setSpeed(self.speed) 70 self._bt = None # BreakThread 71 self._arcRadius = 0
72
73 - def setSpeed(self, speed):
74 ''' 75 Sets the speed to the given value (arbitrary units). 76 The speed will be changed to the new value at the next movement call only. 77 @param speed: the speed 0..100 78 ''' 79 self.speed = speed 80 self.mot1.setSpeed(speed) 81 self.mot2.setSpeed(speed) 82 self.gearState = GearState.UNDEFINED
83
84 - def getSpeed(self):
85 ''' 86 Returns the current speed (arbitrary units). 87 ''' 88 return self.speed
89
90 - def forward(self, duration = -1):
91 ''' 92 Starts the forward movement with current speed for the given duration (in ms). 93 For duration = -1 (default), the method returns, while the movement continues. 94 Otherwise the method returns at the end of the given duration, but the 95 movement continues for 200 ms. Then it stops unless another movement method 96 call (forward, backward, left, right, leftArc, rightArc) is 97 invoked within that time. In a consequence calling several movement methods 98 one after the other will result a seamless movement without intermediate stops. 99 (If motor is already rotating with same speed, returns immediately.) 100 ''' 101 Tools.debug("calling forward() with speed: " + str(self.speed) + " and duration: " + str(duration)) 102 self._joinBrakeThread() 103 if duration == 0 or (duration < 0 and self.gearState == GearState.FORWARD): 104 return 105 self.mot1.forward() 106 self.mot2.forward() 107 self.gearState = GearState.FORWARD 108 if duration > 0: 109 Tools.delay(duration) 110 self._startBrakeThread()
111
112 - def backward(self, duration = -1):
113 ''' 114 Same as forward(int duration), but moves in reverse direction. 115 ''' 116 Tools.debug("calling backward() with speed: " + str(self.speed) + " and duration: " + str(duration)) 117 self._joinBrakeThread() 118 if duration == 0 or (duration < 0 and self.gearState == GearState.BACKWARD): 119 return 120 self.mot1.backward() 121 self.mot2.backward() 122 self.gearState = GearState.BACKWARD 123 if duration > 0: 124 Tools.delay(duration) 125 self._startBrakeThread()
126
127 - def stop(self):
128 ''' 129 Stops the gear. 130 (If motor is already stopped, returns immediately.) 131 ''' 132 Tools.debug("calling stop()") 133 self._joinBrakeThread() 134 if self.gearState == GearState.STOPPED: 135 return 136 self.mot1.stop() 137 self.mot2.stop() 138 self.gearState = GearState.STOPPED
139
140 - def moveTo(self, count, blocking = True):
141 ''' 142 Sets the rotation counter of both motors to zero and rotate the motors until the given count is reached. 143 If count is negative, the motors turn backwards. 144 If blocking = True (default), the method returns blocks, until the count is reached; otherwise it returns 145 immediately 146 ''' 147 self.mot1.rotateTo(count, False) 148 self.mot2.rotateTo(count, blocking)
149
150 - def left(self, duration = -1):
151 ''' 152 Starts turning left with left motor rotating forward and 153 right motor rotating backward at current speed. 154 For duration = -1 (default), the method returns, while the movement continues. 155 Otherwise the method returns at the end of the given duration, but the 156 movement continues for 200 ms. Then it stops unless another movement method 157 call (forward, backward, left, right, leftArc, rightArc) is 158 invoked within that time. In a consequence calling several movement methods 159 one after the other will result a seamless movement without intermediate stops. 160 (If gear is already turning left, returns immediately.) 161 ''' 162 self._joinBrakeThread() 163 if duration == 0 or (duration < 0 and self.gearState == GearState.LEFT): 164 return 165 self.mot1.backward() 166 self.mot2.forward() 167 self.gearState = GearState.LEFT 168 if duration > 0: 169 Tools.delay(duration) 170 self._startBrakeThread()
171
172 - def right(self, duration = -1):
173 ''' 174 Same as left, but turns to the right. 175 ''' 176 self._joinBrakeThread() 177 if duration == 0 or (duration < 0 and self.gearState == GearState.RIGHT): 178 return 179 self.mot1.forward() 180 self.mot2.backward() 181 self.gearState = GearState.RIGHT 182 if duration > 0: 183 Tools.delay(duration) 184 self._startBrakeThread()
185
186 - def leftArc(self, radius, duration = -1):
187 ''' 188 Starts turning to the left on an arc with given radius (in arbitrary units). 189 If the radius is negative, turns left backwards. 190 For duration = -1 (default), the method returns, while the movement continues. 191 Otherwise the method returns at the end of the given duration, but the 192 movement continues for 200 ms. Then it stops unless another movement method 193 call (forward, backward, left, right, leftArc, rightArc) is 194 invoked within that time. In a consequence calling several movement methods 195 one after the other will result a seamless movement without intermediate stops. 196 (If gear is already turning on a left arc with same radius, returns immediately.) 197 ''' 198 Tools.debug("calling leftArc() with radius: " + str(radius) + " and duration: " + str(duration)) 199 self._joinBrakeThread() 200 if duration == 0 or (duration < 0 and self.gearState == GearState.LEFTARC and self._arcRadius == radius): 201 return 202 speed1 = int(self.speed * (abs(radius) - SharedConstants.GEAR_AXE_LENGTH) / (abs(radius) + SharedConstants.GEAR_AXE_LENGTH)) 203 self.mot1.setSpeed(speed1) # Reduce speed of mot1 204 Tools.debug("speed1: " + str(speed1)) 205 Tools.debug("speed2: " + str(self.speed)) 206 if radius > 0: 207 self.mot1.forward() 208 self.mot2.forward() 209 else: 210 self.mot1.backward() 211 self.mot2.backward() 212 self.mot1.setSpeed(self.speed) # Restore old speed 213 gearState = GearState.LEFTARC 214 self._arcRadius = radius 215 if duration > 0: 216 Tools.delay(duration) 217 self._startBrakeThread()
218
219 - def rightArc(self, radius, duration = -1):
220 ''' 221 Starts turning to the right on an arc with given radius (in arbitrary units). 222 If the radius is negative, turns left backwards. 223 For duration = -1 (default), the method returns, while the movement continues. 224 Otherwise the method returns at the end of the given duration, but the 225 movement continues for 200 ms. Then it stops unless another movement method 226 call (forward, backward, left, right, leftArc, rightArc) is 227 invoked within that time. In a consequence calling several movement methods 228 one after the other will result a seamless movement without intermediate stops. 229 (If gear is already turning on a left arc with same radius, returns immediately.) 230 ''' 231 Tools.debug("calling rightArc() with radius: " + str(radius) + " and duration: " + str(duration)) 232 self._joinBrakeThread() 233 if duration == 0 or (duration < 0 and self.gearState == GearState.RIGHTARC and self._arcRadius == radius): 234 return 235 speed2 = int(self.speed * (abs(radius) - SharedConstants.GEAR_AXE_LENGTH) / (abs(radius) + SharedConstants.GEAR_AXE_LENGTH)) 236 self.mot2.setSpeed(speed2) # Reduce speed of mot2 237 Tools.debug("speed1: " + str(self.speed)) 238 Tools.debug("speed2: " + str(speed2)) 239 if radius > 0: 240 self.mot1.forward() 241 self.mot2.forward() 242 else: 243 self.mot1.backward() 244 self.mot2.backward() 245 self.mot2.setSpeed(self.speed) # Restore old speed 246 gearState = GearState.RIGHTARC 247 self._arcRadius = radius 248 if duration > 0: 249 Tools.delay(duration) 250 self._startBrakeThread() 251
252 - def getLeftMotor(self):
253 ''' 254 Returns the reference of motor 1 (left motor). 255 ''' 256 return self.mot1
257
258 - def getRightMotor(self):
259 ''' 260 Returns the reference of motor 2 (right motor). 261 ''' 262 return self.mot2
263 264
265 - def _startBrakeThread(self):
266 self._bt = BrakeThread(self) 267 self._bt.start() 268 # Must wait until BrakeThread is up and running 269 while not self._bt.isRunning: 270 time.sleep(0.001)
271
272 - def _joinBrakeThread(self):
273 if self._bt != None: 274 self._bt.isRunning = False 275 # Must wait until BrakeThread is finished 276 while not self._bt.isFinished: 277 time.sleep(0.001) 278 self._bt = None
279