1
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
23 Thread.__init__(self)
24 self.gear = gear
25 self.isRunning = False
26
44
54
56 ''' Class that represents the combination of two motors on an axis
57 to perform a car-like movement.
58 '''
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
71 self._arcRadius = 0
72
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
85 '''
86 Returns the current speed (arbitrary units).
87 '''
88 return self.speed
89
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
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
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)
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)
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)
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)
246 gearState = GearState.RIGHTARC
247 self._arcRadius = radius
248 if duration > 0:
249 Tools.delay(duration)
250 self._startBrakeThread()
251
253 '''
254 Returns the reference of motor 1 (left motor).
255 '''
256 return self.mot1
257
259 '''
260 Returns the reference of motor 2 (right motor).
261 '''
262 return self.mot2
263
264
266 self._bt = BrakeThread(self)
267 self._bt.start()
268
269 while not self._bt.isRunning:
270 time.sleep(0.001)
271
273 if self._bt != None:
274 self._bt.isRunning = False
275
276 while not self._bt.isFinished:
277 time.sleep(0.001)
278 self._bt = None
279