VEX Robotics 2020-21
It was no secret that the 2020-21 VEX game was one of the worst games produced while I was competing. Rather than dwell on the losses, our team decided to use the opportunity to learn new things and play around with sensors.
Below is a collection of things I did this season that I thought were pretty cool.
Ratcheting Intake Mechanism
In order to meet the sizing requirements for VEX, a lot of teams employed some sort of expansion mechanism to allow them to take full advantage of the expansion rules with their robot design. One design that we another team use was a ratcheting mechanism that would deploy the intake when run in reverse and intake normally when driven forwards. This design was very cool, however it came with many downsides including being large, hard to implement, and poor consistency. Our team really liked the idea behind this design, so we decided to look into similar ways to achieve the same functionality. I eventually came up with the following design that utilizes a slip gear, pinion and an elastic. When the intake is retracted, the motor can run in forwards to deploy the intake. Once the intake reaches the deployed position, the pinion slips on the slip gear while intaking game objects. The elastic holds the pinion to the slip gear, allowing the motor to spin in reverse and retract the intake.
The elastic was eventually replaced by a standoff held on by a cut bushing.
Lidar Alignment
One of the other things I did this year was write a PID algorithm to use two lidar sensors to line the robot up with the corner goals during the autonomous period. Below is a few videos of the robot and the code. The first video shows the robot with an untuned PID. The other two show the robot with a tuned PID. In the third video, the reaction of the robot to being pushed is shown.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
void Chassis::twrAlign(int timeout, int leftTarg, int rightTarg){
int diffErrR, diffErrL;
int startMillis = pros::millis();
float KP = 0.8;
float KD = 1.2;
int errL = 0; //error value init
int derrL = 0;//error difference
int err_lastL = 0; //last error
int err_sumL = 0; //sum of errors
float pL; //p value normally 0.8
float dL; //d value normally 0.7
int errR = 0; //error value init
int derrR = 0;//error difference
int err_lastR = 0; //last error
int err_sumR = 0; //sum of errors
float pR; //p value normally 0.8
float dR; //d value normally 0.7
int dPowL, dPowR;
while((pros::millis()-startMillis) < timeout){
errL = lLDR.get() - leftTarg;
err_lastL = errL;
derrL = (errL - err_lastL);
pL = (KP * errL);
err_sumL += errL;
dL = KD * derrL;
errR = rLDR.get() - rightTarg;
err_lastR = errR;
derrR = (errR - err_lastR);
pR = (KP * errR);
err_sumL += errR;
dR = KD * derrR;
dPowL = (pL+dL);
dPowR = (pR+dR);
diffErrR = (errL/errR)/2;
diffErrL = (errR/errL)/2;
if(dPowL > 80){dPowL=80;};
if(dPowL < -80){dPowL=-80;};
if(dPowR > 80){dPowR=80;};
if(dPowR < -80){dPowR=-80;};
driveRF.move(dPowR);
driveLB.move(dPowL);
driveRB.move(dPowR);
driveLF.move(dPowL);
}
}
void Chassis::fenceAlign(int timeout){
int startMillis = pros::millis();
float KP = 0.7;
float KD = 1.2;
int err = 0; //error value init
int derr = 0;//error difference
int err_last = 0; //last error
int err_sum = 0; //sum of errors
float p; //p value normally 0.8
float d; //d value normally 0.7
int dPow;
while((pros::millis()-startMillis) < timeout){
err = rbLDR.get() - lbLDR.get();
err_last = err;
derr = (err - err_last);
p = (KP * err);
err_sum += err;
d = KD * derr;
dPow = (p+d);
if(dPow > 127){dPow=127;};
if(dPow < -127){dPow=-127;};
driveRF.move(dPow);
driveLB.move(-dPow);
driveRB.move(dPow);
driveLF.move(-dPow);
}
}