Skip to content

Commit da0dc7d

Browse files
committed
Edited missions.py to prevent double-instantiation of the robot object. Added comments to DriveLibraries.py
1 parent 716eddc commit da0dc7d

File tree

4 files changed

+141
-34
lines changed

4 files changed

+141
-34
lines changed

FLLMaster/DriveLibraries.py

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from ev3dev2.motor import *
22
from ev3dev2.sensor.lego import *
33
from ev3dev2.sensor import *
4+
reflHighVal = 100
5+
reflLowVal = 0
6+
reflRate = 1
47

58
class Robot:
69
from ev3dev2.motor import MoveTank, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, LargeMotor
@@ -12,6 +15,7 @@ class Robot:
1215
from ev3dev2.display import Display
1316
import ev3dev2.fonts as fonts
1417
import math
18+
1519

1620
def __init__(self, filename):
1721
from configparser import SafeConfigParser
@@ -83,32 +87,68 @@ def __init__(self, filename):
8387
self.spkr.beep()
8488

8589
def reflectCal(self):
90+
"""
91+
"Calibrate" the color sensor using high and low setpoints, and a simple linear mapping.
92+
The adjusted value can then be accessed using robot.correctedRLI, and the raw value can be acessed using
93+
robot.cs.reflected_light_intensity.
94+
95+
Use: When called, the robot will emit a high-pitched beep. This is a signal to place the robot on a white surface
96+
and press the center button. The robot then emits a low-pitched beep. This is a signal to repeat the procedure with a
97+
black surface.
98+
"""
99+
# These variables need to be accessed by the correctedRLI function, and thus need to be global.
86100
global reflHighVal
87101
global reflLowVal
88102
global reflRate
103+
# Signal for white
89104
self.spkr.beep('-f 880')
105+
# Wait for user conformation of a white surface
90106
self.btn.wait_for_bump('enter')
107+
# Set High fixpoint
91108
reflHighVal = (self.cs.reflected_light_intensity)
109+
# Conformation of completion
92110
self.spkr.beep()
111+
# Signal for black
93112
self.spkr.beep('-f 220')
113+
# Wait for user conformation of a black surface
94114
self.btn.wait_for_bump('enter')
115+
# Set Low fixpoint
95116
reflLowVal = self.cs.reflected_light_intensity
117+
# Conformation of completion
96118
self.spkr.beep()
119+
# Calculate the slope of the linear function that maps the fixpoints to 0 - 100
97120
reflRate = 100 / (reflHighVal - reflLowVal)
98121

99122
@property
100123
def correctedRLI(self):
124+
"""
125+
Returns the reflected light intensity from the color sensor, scaled based on the high and low values created by reflectCal
126+
127+
This means LineFollow can use 50 as the target, even though the actual reading for black might be 20, and white 75, as it
128+
will be scaled to 0 - 100.
129+
"""
130+
# Calculates adjusted value with a linear mapping. To see how this works go here: https://www.desmos.com/calculator/d4mudhrdng
101131
value = min([100, max([0, (self.cs.reflected_light_intensity * reflRate) + (-reflLowVal * reflRate)])])
102132
return(value)
103133

104134
@property
105135
def correctedAngle(self):
136+
"""
137+
Retuns the gyro value corrected for the orientation of the gyro in the robot; turning right will always increase the value,
138+
and turning left will always decrease the value. The raw value can be accessed with robot.gs.angle_and_rate[0]
139+
140+
Angle and rate is used to prevent switching modes and resetting the angle.
141+
"""
142+
106143
# Multiply the gyro angle by -1 if the gyro is mounted upside-down relative to the motors in the robot.
107144
# GyroInvertedNum is set up in __init__()
108145
return(self.gs.angle_and_rate[0] * self.GyroInvertedNum)
109146

110147
def zeroGyro(self):
111-
# Reset the gyro angle to zero by switching modes. gyro.reset would have been used instead of this function, but it does not work
148+
"""
149+
Reset the gyro angle to zero by switching modes. gyro.reset would have been used instead of this function,
150+
but it does not work
151+
"""
112152
self.gs._ensure_mode(self.gs.MODE_GYRO_RATE)
113153
self.gs._ensure_mode(self.gs.MODE_GYRO_G_A)
114154

@@ -126,6 +166,7 @@ def DriveAtHeading(self, Heading, Distance, Speed, Stop):
126166
print("Distance must be greater than zero. Use negative speed to drive backwards.")
127167
return
128168
elif Distance > 265:
169+
# The longest distance on an FLL table (diagonal) is about 265cm.
129170
if self.ForFLL:
130171
print("Please don't use silly distances (max = 265cm)")
131172
return
@@ -181,7 +222,7 @@ def DriveAtHeading(self, Heading, Distance, Speed, Stop):
181222
# Calculate the pecrentage of the distance left to travel
182223
targDist = 1 - (avg / target)
183224
# Calculate speedMult based on pecentage; linear function was designed to bring the robot to a
184-
# smooth stop while still reaching the target.
225+
# smooth stop while still reaching the target, resulting in 20% of the intial speed at end.
185226
speedMult = ((8 / 3) * targDist) + 0.2
186227
else:
187228
speedMult = 1
@@ -201,25 +242,48 @@ def DriveAtHeading(self, Heading, Distance, Speed, Stop):
201242
self.steer.stop()
202243

203244
def degrees2power(self, currentDifference):
245+
"""
246+
Returns a power value based on the degrees left to turn, using a linear function that allows the robot
247+
to reach the desired angle, while slowing down as to not overshoot. Used only in GyroTurn.
248+
"""
204249
if currentDifference == 0:
250+
# Minimum power value is 5
205251
return(5)
252+
# Using and returning absolute values, for simplicity. GyroTurn fixes the sign.
206253
currentDifference = abs(currentDifference)
254+
# Return calculated value
207255
return(min([50, max([5, ((0.125 * currentDifference) + 4.875)])]))
208256

209257
def GyroTurn(self, Heading):
258+
"""
259+
Turns the robot to ``Heading``, slowing down as it approaches. Will unwind any full circles
260+
(if the gyro reads 540, and the value given is 90, the robot will spin until reaching 90, not 450).
261+
"""
262+
263+
# Initalize the sign variable (used to correct overshoot)
210264
sign = 1
211265

266+
# If the current heading is equal to the desired heading, no turning is needed.
212267
if Heading - self.correctedAngle == 0:
213268
return
214269

270+
# Read the gyro, and store in currentHeading
215271
currentHeading = self.correctedAngle
272+
# Continue turning until the robot is within 1 degree of the target (can be reduced if necessary)
216273
while (currentHeading > 0.5 + Heading) or (currentHeading < Heading - 0.5):
274+
# Calculate the difference between where the robot should be and where it is
217275
currentDifference = Heading - currentHeading
276+
# The sign variable defines the direction in which to turn. It should have the same sign as the currentDifference variable.
277+
# If not, multiply by -1 to fix it.
218278
if ((sign > 0) and (currentDifference < 0)) or ((sign < 0) and (currentDifference > 0)):
219279
sign *= -1
280+
# Set the power variable to the absolute power (calculated by degrees2power) multiplied by the sign variable
220281
power = sign * self.degrees2power(currentDifference)
282+
# Start turning
221283
self.tank.on(power, -1 * power)
284+
# Update currentHeading
222285
currentHeading = self.correctedAngle
286+
# When the loop finishes, stop the motors.
223287
self.tank.stop()
224288

225289
def ArcTurn(self, Degrees, Radius, Speed):

FLLMaster/Main.py

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,67 @@
11
#!/usr/bin/env python3
2-
from MenuLib import init
3-
import MenuLib
2+
from MenuLib import init, initthread, runCurrentMission
43
from time import sleep
5-
# Write Code Here ----------------------------------------
4+
loopIndex = 0
65

7-
init()
6+
init('robot.cfg')
7+
initthread()
88
from MenuLib import *
9-
MenuLib.robot.reflectCal()
9+
calibrate()
10+
robot.reflectCal()
1011

1112
def left(state):
1213
if state:
13-
minusCount()
14-
display()
14+
if not mission.is_alive():
15+
minusCount()
16+
display()
17+
else:
18+
abort()
19+
minusCount()
20+
display()
1521
def right(state):
1622
if state:
17-
addCount()
18-
display()
23+
if not mission.is_alive():
24+
addCount()
25+
display()
26+
else:
27+
abort()
28+
minusCount()
29+
display()
1930
def down(state):
2031
if state:
21-
calibrate()
32+
if not mission.is_alive():
33+
calibrate()
34+
else:
35+
abort()
36+
minusCount()
37+
display()
2238
def up(state):
2339
if state:
24-
abort()
25-
minusCount()
26-
display()
40+
if not mission.is_alive():
41+
robot.reflectCal()
42+
else:
43+
abort()
44+
minusCount()
45+
display()
2746
def enter(state):
2847
if state:
29-
run()
30-
addCount()
31-
display()
48+
if not mission.is_alive():
49+
run()
50+
addCount()
51+
display()
52+
else:
53+
abort()
54+
minusCount()
55+
display()
3256
def backspace(state):
33-
if state:
34-
abort()
57+
pass
3558

3659
robot.btn.on_left = left
3760
robot.btn.on_right = right
3861
robot.btn.on_up = up
3962
robot.btn.on_down = down
4063
robot.btn.on_enter = enter
41-
robot.btn.on_backspace = backspace
42-
64+
robot.btn.on_backspace = backspace
4365

4466
while True:
4567
robot.btn.process()

FLLMaster/MenuLib.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
from DriveLibraries import *
22
import multiprocessing
3-
import Missions
43
from time import sleep
4+
Missions = None
55
mission = None
66
robot = None
77
programs = []
88
numPrograms = 0
99
count = 1
1010
loopIndex = 0
1111

12-
def init():
12+
def init(confFile):
1313
global programs
1414
global numPrograms
1515
global robot
16-
robot = Robot('robot.cfg')
16+
global Missions
17+
robot = Robot(confFile)
18+
import Missions
1719
programs = dir(Missions)
1820
i = 0
1921
index = -1
@@ -29,17 +31,19 @@ def init():
2931

3032
robot.disp.clear()
3133
robot.disp.text_grid(programs[0][3:], font=robot.fonts.load('timR24'))
32-
34+
3335
def runCurrentMission():
3436
method_to_call = getattr(Missions, programs[count - 1])
3537
method_to_call()
3638
robot.rm.off(brake=False)
3739
robot.lm.off(brake=False)
3840

39-
def run():
40-
robot.zeroGyro()
41+
def initthread():
4142
global mission
4243
mission = multiprocessing.Process(target=runCurrentMission)
44+
45+
def run():
46+
robot.zeroGyro()
4347
mission.start()
4448

4549
def display():

FLLMaster/Missions.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
1-
from DriveLibraries import *
2-
robot = Robot('robot.cfg')
1+
if __name__ == "__main__":
2+
from DriveLibraries import *
3+
robot = Robot('robot.cfg')
4+
else:
5+
from MenuLib import robot
36
# Write Mission Programs Here ----------------------
47

8+
# Mission Names should be prefaced with a##, where ## is two numbers. These
9+
# numbers will not show up on the display, and tell the program what order the
10+
# missions should be in; a00 is first, followed by a01, and so on. It is
11+
# reccomended that spaces are left between the numbers (a00, a05, a10...), to
12+
# allow for future missions.
13+
514
def a00Star():
15+
# Drives a simple 4-pointed star, with arced sides
616
robot.ArcTurn(-90, 30, 30)
717
robot.ArcTurn(-90, 30, -30)
818
robot.ArcTurn(-90, 30, 30)
919
robot.ArcTurn(-90, 30, -30)
20+
1021
def a05LineFollow():
22+
# Follows a line for 50 cm, at 50% speed, stopping at end
1123
robot.LineFollow(50, 50, True)
24+
1225
def a10Command_Key():
26+
# Drives in a pattern similar to the Apple command key
27+
# o_o
28+
# | |
29+
# o‾o
1330
robot.DriveAtHeading(0, 50, 30, False)
14-
robot.ArcTurn(270, 30, 30)
31+
robot.ArcTurn(270, 10, 30)
1532
robot.DriveAtHeading(270, 50, 30, False)
16-
robot.ArcTurn(270, 30, 30)
33+
robot.ArcTurn(270, 10, 30)
1734
robot.DriveAtHeading(270 * 2, 50, 30, False)
18-
robot.ArcTurn(270, 30, 30)
35+
robot.ArcTurn(270, 10, 30)
1936
robot.DriveAtHeading(270 * 3, 50, 30, True)
20-
robot.GyroTurn(0)
37+
robot.GyroTurn(0)

0 commit comments

Comments
 (0)