11from ev3dev2 .motor import *
22from ev3dev2 .sensor .lego import *
33from ev3dev2 .sensor import *
4+ reflHighVal = 100
5+ reflLowVal = 0
6+ reflRate = 1
47
58class 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 ):
0 commit comments