About v5 programming

Hey guys.
This is our first year participating in vrc. We have never programmed v5 robots before. We have started with vexcode blocks but then the programming wasn’t that consistent so we switched to pros. We programmed our pid loops for forward backward left and right motions. Now we’re programming the trajectory. But it’s only getting frustrating because every time we run the code something different happens. The programming is still not consistent and it’s maybe even worse than before. Whenever we find a solution to something a bigger problem appears. We’re really feeling down right now, nothing seems to work and the atmosphere is getting cold and very tense. We just wanted to know if you guys ever feel that way and also do you have any ideas as to how we can make our program more consistent.
Please if you’ve got any pieces of advice, I’m ready to hear them.
Anything would help right now.
Thank you.

1 Like

we need to see the code to fix the code

8 Likes

TBH the fact that you are even trying to do a PID loop in you 1st year with little to no programming experience is pretty remarkable. I have seen veteran teams not even trying to do that kind of thing. I know this sounds cliche, but if you keep trying eventually you guys will do great.

And as drew said, post code.

5 Likes

Like Drew said, post code. I would also recommend programming a backup program just in case the PID fails. It pretty cool that you are doing PID, though you might just have to tune your loop a little more.

Also, I wouldn’t recommend going straight to PROS. Rather, go through VEXcode Text, then VEXcode V5 Pro, then PROS. Often, V5 Pro has everything you need unless you need to use the okapi library.

5 Likes

Here’s my code:
//PID Constants
double kP = 0.14;
double kI = 0.0001;
double kD = 0.1;

double turn_kP = 0.7;
double turn_kI = 0.00;
double turn_kD = 0.00;

//PID Variables
int error;
int prevError;
int derivative;
int totalError;
int targetPosition = 0;

int turn_error;
int turn_prevError;
int turn_derivative;
int turn_totalError;
int turn_targetPosition = 0;

bool enablePID = true;
bool resetDriveSensors = false;

int drivePID(){
while(enablePID){

	if (resetDriveSensors) {
		resetDriveSensors = false;
		left.tare_position();
		right.tare_position();
	}

	int leftPosition = left.get_position();
int rightPosition = right.get_position();

	//AVERAGE_POSITION
	int averagePosition= (leftPosition + rightPosition)/2;

	//POTENTIAL
	error = targetPosition - averagePosition;

	//DERIVATIVE
	derivative= error - prevError;

	//INTEGRAL
	totalError += error;

	double lateralMotion = error * kP + derivative * kD + totalError * kI;

	left.move(lateralMotion);
	right.move(lateralMotion);



	prevError = error;


pros::delay(20);

}
return 1 ;
}
bool enable_turnPID = false;
       int turnPID(){
     while(enablePID){

	if (resetDriveSensors) {
		resetDriveSensors = false;
		left.tare_position();
		right.tare_position();
	}

	int leftPosition = left.get_position();
	int rightPosition = right.get_position();

	//TURN_DIFFERENCE
	int turnDifference= leftPosition - rightPosition;

	//TURN_POTENTIAL
	turn_error = turnDifference - turn_targetPosition;

	//TURN_DERIVATIVE
	turn_derivative= turn_error - turn_prevError;

	//INTEGRAL
	turn_totalError += turn_error;

	double turnMotion = turn_error * kP + turn_derivative * kD + turn_totalError * kI;

	right.move(turnMotion);
	left.move(-turnMotion);

  turn_prevError = turn_error;

	pros::delay(20);
}
return 1;
 }
void autonomous() {
  
 enablePID = true;
 enable_turnPID = false;
 pros::Task pidstraight(drivePID);
 resetDriveSensors = true;

 targetPosition = 1608;
 intake1.move_absolute(5000 , 200);
 intake2.move_absolute(5000 , 200);

 pros::delay(1000);

 outake1.move_relative(1200, 200);
 outake2.move_relative(1200, 200);

 enable_turnPID =true;
 pros::Task turntwo(turnPID);
 turn_targetPosition = 908;
 pros::delay(1000);

 enablePID = true;
 enable_turnPID = false;
 pros::Task pidtwo(drivePID);
 resetDriveSensors = true;

 targetPosition = 936;

 pros::delay(1000);


 intake1.move_relative(7000 , 200);
 intake2.move_relative(7000 , 200);
     pros::delay(1000);
 outake1.move_relative(7000 , 200);
 outake2.move_relative(7000 , 200);


     pros::delay(1000);

 enablePID = true;
 enable_turnPID = false;
 pros::Task pidfour(drivePID);
 resetDriveSensors = true;

 targetPosition = -1200;
 intake1.move_relative(-5000 , 200);
 intake2.move_relative(-5000 , 200);
 outake1.move_relative(-5000 , 200);
 outake2.move_relative(-5000 , 200);
 pros::delay(1000);

 enable_turnPID =true;
 pros::Task turnthree(turnPID);
 turn_targetPosition = -1587;
 pros::delay(1000);

 enablePID = true;
 enable_turnPID = false;
     pros::Task pidstra(drivePID);
 resetDriveSensors = true;

 targetPosition = 1524;
 intake1.move_absolute(9000 , 200);
 intake2.move_absolute(9000 , 200);

 pros::delay(1000);

}
1 Like

Thank you for your reply :smile:
I think that it actually is a tuning problem. Do you know how I could tune my pid loop so that my autonomous run is 100% consistent? I must admit that we didn’t spend much time tuning it because the process of trying every combination of constants was a bit tyring. Also how much does it take you to fully tune your pid loops and how accurate can it be?

There is definitely a method to tuning PID loops

The p term just directly multiplies a constant to the amount of error (distance from target point) is measured, the further away a robot is from the target the faster it goes, and it slows down as it gets closer.

The I term is multiplied by the total accumulation of error, the integral, so the longer you have stayed further away from the end point the faster the I term will make the robot go, in addition to the P term.

The D term is multiplied to the derivative of error (basically the rate of change of error) This settles the robot faster and keeps the error lower during acceleration, which in conjunction with the P term lowers oscillation around the target point.

5 Likes