Skip to content

Commit cb3b9c2

Browse files
committed
Linefollow working, tuning PID.
1 parent eb67647 commit cb3b9c2

File tree

3 files changed

+122
-9
lines changed

3 files changed

+122
-9
lines changed

FLLMaster/DriveLibraries.py

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ def __init__(self, filename):
3838
self.InfraredPort = eval(conf.get('Sensors', 'InfraredPort'))
3939
self.TouchPort = eval(conf.get('Sensors', 'TouchPort'))
4040
self.UltrasonicPort = eval(conf.get('Sensors', 'UltrasonicPort'))
41+
self.kpLine = float(conf.get('Sensors', 'kpLine'))
42+
self.kiLine = float(conf.get('Sensors', 'kiLine'))
43+
self.kdLine = float(conf.get('Sensors', 'kdLine'))
4144

4245
self.AuxMotor1 = eval(conf.get('AuxMotors', 'AuxMotor1'))
4346
self.AuxMotor2 = eval(conf.get('AuxMotors', 'AuxMotor2'))
@@ -80,11 +83,11 @@ def reflectCal(self):
8083
global reflHighVal
8184
global reflLowVal
8285
global reflRate
83-
self.spkr.speak("Show me white")
86+
self.spkr.beep('-f 880')
8487
self.btn.wait_for_bump('enter')
8588
reflHighVal = (self.cs.reflected_light_intensity)
8689
self.spkr.beep()
87-
self.spkr.speak("Show me black")
90+
self.spkr.beep('-f 220')
8891
self.btn.wait_for_bump('enter')
8992
reflLowVal = self.cs.reflected_light_intensity
9093
self.spkr.beep()
@@ -423,4 +426,82 @@ def LineStop(self, Heading, Speed, Stop):
423426
# Set the brick light back to green flashing
424427
#EVS.SetLEDColor("GREEN", "PULSE")
425428

426-
def LineFollow(self, Speed, Stop):
429+
def LineFollow(self, Distance, Speed, Stop):
430+
"""
431+
Follows the edge of a line for a specific distance at a specific speed.
432+
433+
``Distance``: The distance to drive, in centimeters (positive only).
434+
``Speed``: The speed at which to drive, in motor percentage (same speed units as EV3-G). (Positive only; there's no going back)
435+
``Stop``: Stop motors after completion. If ``FALSE``, motors will continue running after ``Distance`` has been traveled. Otherwise, motors will stop after ``Distance`` cm.
436+
"""
437+
# Ensure values are within reasonable limits, and change them if necessary (Idiotproofing).
438+
if Speed > 50:
439+
Speed = 50
440+
print("Speed must be between -50 and 50 (inclusive).")
441+
elif Speed < -50:
442+
Speed = -50
443+
print("Speed must be between -50 and 50 (inclusive).")
444+
445+
# "Reset" motor encoders by subtracting start values
446+
left_motor_start = self.lm.degrees
447+
right_motor_start = self.rm.degrees
448+
left_motor_now = self.lm.degrees
449+
right_motor_now = self.rm.degrees
450+
left_motor_change = left_motor_now - left_motor_start
451+
right_motor_change = right_motor_now - right_motor_start
452+
453+
# Determine the sign of the speed, for PID correction
454+
sign = Speed / abs(Speed)
455+
456+
# Find number of degrees that motors need to rotate to reach the desired number of cm.
457+
target = (Distance * 360) / self.WheelCircumference
458+
459+
# Find the average of the left and right encoders, as they could be different from PID correction
460+
avg = abs((left_motor_change + right_motor_change) / 2)
461+
462+
# Initialize variables for PID control
463+
integral = 0.0
464+
last_error = 0.0
465+
derivative = 0.0
466+
467+
# Check if the motors have gone far enough
468+
while avg < target:
469+
# Read the gyro
470+
current_RLI = self.correctedRLI
471+
472+
# Calculate the PID components
473+
error = 50 - current_RLI
474+
integral = integral + error
475+
derivative = error - last_error
476+
last_error = error
477+
478+
# Calculate Steering value based on PID components and kp, ki, and kd
479+
turn_native_units = sign * max([min([(self.kpLine * error) + (self.kiLine * integral) + (self.kdLine * derivative), 100]), -100])
480+
481+
# Check if the motors will stop at the end. If not, the speed will be adjusted to come to a smooth stop.
482+
if Stop == False:
483+
speedMult = 1
484+
else:
485+
# Check if the robot has gone 70% or more of the distance. If so, start slowing down
486+
if (target - avg) <= (0.3 * target):
487+
# Calculate the pecrentage of the distance left to travel
488+
targDist = 1 - (avg / target)
489+
# Calculate speedMult based on pecentage; linear function was designed to bring the robot to a
490+
# smooth stop while still reaching the target.
491+
speedMult = ((8 / 3) * targDist) + 0.2
492+
else:
493+
speedMult = 1
494+
495+
# Start the motors, using the steering value calculated by the PID control, and the input speed multiplied by speedMult (0 - 1, see above).
496+
self.steer.on(-turn_native_units, (Speed * speedMult))
497+
498+
# Update corrected encoder values
499+
left_motor_now = self.lm.degrees
500+
right_motor_now = self.rm.degrees
501+
left_motor_change = left_motor_now - left_motor_start
502+
right_motor_change = right_motor_now - right_motor_start
503+
avg = abs((left_motor_change + right_motor_change) / 2)
504+
505+
# If the robot is to stop, stop the motors. Otherwise, leave the motors on and return.
506+
if not Stop == False:
507+
self.steer.stop()

FLLMaster/Main.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
11
#!/usr/bin/env python3
22
from DriveLibraries import *
33
from time import sleep
4+
from ev3dev2.display import *
5+
disp = Display()
46

57
R1 = Robot('robot.cfg')
68
R1.gs.calibrate()
79
sleep(1)
810
R1.spkr.beep()
9-
R1.btn.wait_for_bump('enter')
10-
R1.cs.calibrate_white()
11+
R1.reflectCal()
1112
R1.btn.wait_for_bump('enter')
1213
# Write Code Here ----------------------------------------
13-
while True:
14-
R1.zeroGyro()
15-
R1.LineStop(0, 75, True)
16-
R1.btn.wait_for_bump('enter')
14+
15+
def left(state):
16+
if state:
17+
R1.kpLine = R1.kpLine - 0.01
18+
print(R1.kpLine)
19+
20+
def right(state):
21+
if state:
22+
R1.kpLine = R1.kpLine + 0.01
23+
print(R1.kpLine)
24+
25+
def up(state):
26+
pass
27+
def down(state):
28+
pass
29+
def enter(state):
30+
if state:
31+
R1.LineFollow(50, 20, True)
32+
def backspace(state):
33+
pass
34+
35+
R1.btn.on_left = left
36+
R1.btn.on_right = right
37+
R1.btn.on_up = up
38+
R1.btn.on_down = down
39+
R1.btn.on_enter = enter
40+
R1.btn.on_backspace = backspace
41+
42+
43+
while True:
44+
R1.btn.process()
45+
1746

FLLMaster/robot.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ GyroPort=INPUT_2
1616
InfraredPort=INPUT_4
1717
TouchPort= 0
1818
UltrasonicPort=INPUT_3
19+
kpLine = 0.5
20+
kiLine = 0.01
21+
kdLine = 0.5
1922

2023
[AuxMotors]
2124
AuxMotor1 = 0

0 commit comments

Comments
 (0)