End of Vex Change up 2020-21 season

Hello, This was my first year in VRC and since my Change up season is practically over since we didn’t make it to states, I was wondering what I should be practicing that would be useful and beneficial to understand/practice. I don’t have much practice building DR4B’s and I have only built and driven Tank drive configured drive trains so should I practice building different lift types, different drive trains, different mechanisms, programming, etc.? If so, what should I practice? This season, my teams robot had a “pooper” mechanism that worked really well and took me about a week to perfect the build so are there other great mechanisms that work great. Thanks
-Team929

3 Likes

You may want to check this thread out

In addition. Learning how to make DR4Bs is a good idea. Other useful things include ratchets, X-Drives, and PID coding.

3 Likes

Judging by your post in another thread, you seem to already know some CAD. I would recommend using that to design other things like lifts, some different drives, and just how to learn to improve build quality in general.

3 Likes

Programming depends on your situation. If you have someone dedicated to programming who will be on your team next year, then it would be a good idea to merely learn the basics. If you don’t know who will be programming next year, you may want to get into different programming concepts like PID.

2 Likes

Yeah I was thinking PID but I don’t even know where to begin with that. I barely know what it stands for so could someone help me understand and possibly give me links to helpful videos? I would appreciate it. Thanks!

1 Like

There are a LOT of threads about PID, so use the search bar.

This is one of the best resources though:

4 Likes

So PID is used with sensors (such as distance sensors, potentiometers, motor encoders, etc.) to calculate and change the speed of the motors so that it can stop at the exact spot you need it to? What sensors can you use with it? Can I use normal sensors such as limit switches, bumper switches?

1 Like

I use PID with motor encoders. To be even more accurate, you can use external wheel encoders or tracking wheels.

1 Like

Anything analog. Analog means anything that returns a range of numbers, not just 0 or 1. So no, you can’t use limit switches or bumper switches.

2 Likes

I don’t suggest trying to make an X drive or spending time in CAD like others have suggested, at least if you main goal is to improve your competitiveness. CAD is a very useful tool but I truly believe that it is not useful unless you have already vigorously tested things in real life before moving into cad to made a final version.

For improving building, I suggest somewhat “studying” past robots that did well and looking at how their structure of their robot is composed. Great examples are 169’s ITZ robot and 62’a Skyrise robot. Remembering bits and pieces of the best parts of some of the best robots made will often help you be super flexible while building while having a very clean and tested solution. Examples of this would be mounting towers stiffly, bracing arms, drivetrain layouts, manipulators, ratchets, chain tensioning, proper joints, etc. While doing this don’t be afraid to grab some parts and try things out for yourself, I know that I was really amazed at how strong the X bracing 62 used on their skyrise lift was when I built a test for it. Other great videos are Skyline (4411S) Turning point robot explanation, 2587Z’s Skyrise and Nothing but net reveals, and any team 44 or team 5225A robot.

Programming is always something that needs improved as well, if you want to have higher level programming I suggest you start with learning what PID is, once you learn that learn either slew rate or trapezoidal motion profiling for more accurate movements (Slew rate is much simpler if you haven’t taken a basic physics class with kinematics). If you want to go even more advanced look at the resources QUEEN (Formally Pilons memebers) made about odometry: https://youtu.be/_T6KHywSP58

If you want to get even more advanced you can look at the pure pursuit algorithm.

Or you could not do any of that and just use Okapi which is built into PROS. :slight_smile:

Other then that, I suggest at the beginning of the season you follow what karthik suggest in his strategic game analysis presentation: https://youtu.be/sJOfH-lomEQ

During the season make sure to emphasize driving a lot. It’s often overlooked by even some of the best mechanical skilled teams which leads them to getting beat by a simpler robot that was better driven. Try recording yourself while driving and watching it back, it lets you understand what you are messing up in a way that isn’t possible while you are actually driving.

Good luck next season, Hope you do well!

10 Likes

I’d recommend understanding the algorithms before the season starts. It’s not crunch time for next season yet so no need to take the easy road. Try and get odometry working in pros or vexcode pro without okapilib or copying someone else’s code.

I found designing & building a base during off season to be pretty useful for me. First, I was able to get familiar and fast with CAD, and I get to experiment with how to build with high build quality. For example, I found out how to make my drive free spin for 30 seconds without stopping, and make tracking wheels robust without needing lots of extra structure. Designing bases is also good since its possible that you can use it for future seasons.

Another thing I found to be extremely useful is programming. I’ll suggest getting familiar with PID first since it is effective in autonomous and can be used in almost every subsystem. You can also try out stuff like odometry and pairing PID with it for absolute movements. Another thing which you should learn about is general c++ knowledge. For example, I found classes to be one of the most useful things in c++ for vex programming, but not a lot of teams use them.

3 Likes

Ok so I think I understand PID now. it is used to get the exact distance on a robot either when driving, lifting an arm, etc. Usually PI controls will do the job but what applications would PID be better than PI? Like would I use PID when lifting a tower takeover intakes so that I can get it to the exact location even if the weight of the intakes weigh it down?
Also, Do I need a sensor for PID or can I use the built in motor encoders that are built in to Vex V5 motors? It would be a lot easier to use the built in encoders to make a basic drive train with motor PID.

1 Like

There isn’t really a definite guide to that (I think). Just try different things and see what works. Many people do a PD controller instead of PID as well.

That is a good example of what you can use P or PI or PD or PID for.

The built-in motor encoders are technically sensors, so yes you can use them. External sensors can be more accurate depending on how you build with them though.

yes, maintaining lift height is a very good example of where PID can be useful. This also means that you can store which height you want in controller buttons and toggle between them (By changing the target of your PID controller)

Some other applications include controlling the velocity of a flywheel so it’s accurate, turning and driving to an exact spot. The idea of a p loop slowing down as it reaches target also made it useful for trays in TT since it’s able to go fast at the start and slow down as the cube is getting scored.

Yes, as PID is a “feedback” / closed loop controller, it needs sensor feedback (getting error) in order to calculate the output. For example it can be motor encoders for drive, a potentiometer for lift etc.

Conversely, there’s also such things called feedforward / open loop control. It responds to control signals in a predefined way. Examples can be setting motor to a certain power based on the user input, following a pre-generated motion profile etc.

I think doing PID with V5 motor encoders seems to be a pretty common choice for teams. iirc 574C used motor encoder PID + slew for their 25pt skills run in turning point. Another way which I’ve tried is using tracking wheels. Instead of doing odom with them, I just tracked how much distance the wheels have travelled to get my input for PID. It worked pretty well.

Have fun programming!

3 Likes

Thank you all so much! It has helped me a lot! This coming weekend I will tear apart my robot and practice PID, building, driving etc.! Also, would PID in driver control be useful? I know that it would probably give us an advantage over other teams but how would I use it to drive to an exact location like for example, using it to drive straight to a goal and line up with it for change up?

PID in driver control can be used to maintain a set flywheel velocity or a specific lift height. I guess we’ll see if we need to use any of those applications when the new game gets released…

It definitely is possible to use drive pid in code, just code a macro like such:
if(button A is pressed)
drivePID(48_in)

Note that you won’t be able to control the robot during that time thoigh

Technically you could if you run it in a separate task

I am trying to convert the PID degrees into inches. Would this work
//Autonomous Settings

int inches;

inches/12.9525 *360 = degrees; //the 12.9525 is 3.14 * 4.125" (the 4" omni wheels are actually 4.125" diameter)

int desiredValue = inches;//this is the amount of degrees that you desire – change if needed

desiredValue = 10; //this number is the number of inches the wheels will move

This obviously isnt the whole code but the desiredValue =10; would be in the autonomous code and the rest would be before that. This is my whole code:

/----------------------------------------------------------------------------/
/* /
/
PID Control Test code /
/
/
/
----------------------------------------------------------------------------/
// ---- START VEXCODE CONFIGURED DEVICES ----
// Robot Configuration:
// [Name] [Type] [Port(s)]
// LeftDriveSide motor_group 1, 2
// RightDriveSide motor_group 3, 4
// Controller1 controller
// ---- END VEXCODE CONFIGURED DEVICES ----
#include “vex.h”
using namespace vex;
// A global instance of competition
competition Competition;
// define your global instances of motors and other devices here
/
---------------------------------------------------------------------------/
/
Pre-Autonomous Functions /
/
/
/
You may want to perform some actions before the competition starts. /
/
Do them in the following function. You must return from this function /
/
or the autonomous and usercontrol tasks will not be started. This /
/
function is only called once after the V5 has been powered on and /
/
not every time that the robot is disabled. /
/
---------------------------------------------------------------------------*/
void pre_auton(void) {
// Initializing Robot Configuration. DO NOT REMOVE!
vexcodeInit();

LeftDriveSide.setPosition(0,degrees);
RightDriveSide.setPosition(0,degrees);
// All activities that occur before the competition starts
// Example: clearing encoders, setting servo positions, …
}
//settings
double kP = 0.0;
double kI = 0.0;//these are constants that never change
double kD = 0.0;//modify these numbers if needed
double turnkP = 0.0;
double turnkI = 0.0;//these are constants that never change
double turnkD = 0.0;//modify these numbers if needed
//Autonomous Settings
int inches;
inches/12.9525 *360 = degrees;
int desiredValue = inches;//this is the amount of degrees that you desire – change if needed
int desiredTurnValue = 0;
int error;// currentSensorValue - desiredValue, positional value -> speed -> acceleration ->jerk
int prevError = 0; //position 20 miliseconds ago
int derivative; //error - prevError = speed, calculates the speed needed to reach the end value/target without overshooting -
//if it is going too fast, the derivative will have a negative effect and slow it down and if too slow, it will speed it up (positive effect)
int totalError = 0; //totalError = totalError + error
int turnError;// currentSensorValue - desiredValue, positional value -> speed -> acceleration ->jerk
int turnPrevError = 0; //position 20 miliseconds ago
int turnDerivative; //error - prevError = speed, calculates the speed needed to reach the end value/target without overshooting -
//if it is going too fast, the derivative will have a negative effect and slow it down and if too slow, it will speed it up (positive effect)
int turnTotalError = 0; //totalError = totalError + error
bool resetDriveSensors = false;
//variables modified for use
bool enableDrivePID = true;//currently when it is true, that means it is enabled
int drivePID(){
while (enableDrivePID){

if (resetDriveSensors){
  resetDriveSensors = false;
  LeftDriveSide.setPosition(0,degrees);
  RightDriveSide.setPosition(0,degrees);
}

//get the position of both sides
int LeftDriveSidePosition = LeftDriveSide.position(degrees);
int RightDriveSidePosition = RightDriveSide.position(degrees);

//////////////////////////////////////////////////////////////////
//drive PID control
///////////////////////////////////////////////////////////////////
//get average of these 2 drive sides(motors)

int averagePosition = (LeftDriveSidePosition + RightDriveSidePosition)/2;
//Potential
error = averagePosition - desiredValue;
//Derivative
derivative = error - prevError;

 //integral
 //velocity -> position -> absement(postion * time) -- if pos doesnt change, then we need the absement to increase
 //totalError += error;
 double DriveMotorPower = error * kP + derivative * kD; // + totalError * kI     /12.0  you dont have to have it be divided by 12.0
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////
 //turn PID control
 ////////////////////////////////////////////////////////////////////////////////
 //get average of these 2 drive sides(motors)

int turnDifference = LeftDriveSidePosition - RightDriveSidePosition;

//Potential 
turnError = turnDifference - desiredTurnValue;
//Derivative
turnDerivative = turnError - turnPrevError; 

 //integral
 //velocity -> position -> absement(postion * time) -- if pos doesnt change, then we need the absement to increase
 //turnTotalError += turnError;
 double TurnMotorPower = turnError * turnkP + turnDerivative * turnkD; // + turnTotalError * turnkI    /12.0  you dont have to have it be divided by 12.0
 ///////////////////////////////////////////////////////////////////////////////////
LeftDriveSide.spin(forward, DriveMotorPower + TurnMotorPower, voltageUnits::volt);
RightDriveSide.spin(forward, DriveMotorPower + TurnMotorPower, voltageUnits::volt);

prevError = error;
turnPrevError = turnError;
vex::task::sleep(20);
}
return 1;
}
/---------------------------------------------------------------------------/
/* /
/
Autonomous Task /
/
/
/
This task is used to control your robot during the autonomous phase of /
/
a VEX Competition. /
/
/
/
You must modify the code to add your own robot specific commands here. /
/
---------------------------------------------------------------------------*/
void autonomous(void) {
vex::task DrivePIDTask(drivePID);
resetDriveSensors = true;

desiredValue = 10;//this number is the number of inches the wheels will move
desiredTurnValue = 360;//the desired turn value to turn the robot – try negative turn values and see if it will turn the other direction
vex::task::sleep(1000);
resetDriveSensors = true;
desiredValue = 720;
desiredTurnValue = -360;
vex::task::sleep(1000);

}
/---------------------------------------------------------------------------/
/* /
/
User Control Task /
/
/
/
This task is used to control your robot during the user control phase of /
/
a VEX Competition. /
/
/
/
You must modify the code to add your own robot specific commands here. /
/
---------------------------------------------------------------------------*/
void usercontrol(void) {
enableDrivePID = false;
// User control code here, inside the loop
while (1) {

wait(20, msec); // Sleep the task for a short amount of time to
                // prevent wasted resources.

}
}
//
// Main will set up the competition functions and callbacks.
//
int main() {
// Set up callbacks for autonomous and driver control periods.
Competition.autonomous(autonomous);
Competition.drivercontrol(usercontrol);
// Run the pre-autonomous function.
pre_auton();
// Prevent main from exiting with an infinite loop.
while (true) {
wait(100, msec);
}
}