How to write code to accelerate and decelerate drive train code for autonomous

I recently have been having problems to figure out how to accelerate and decelerate the drive train during autonomous for v5 pro text. I want to slowly ramp up or ramp down the speed to make sure that it is consistent. I have tried to split the distance I want the go and redeclare the velocity but then there is a pause in-between the lines of code when I redeclare. Can someone show me a template of how to accelerate or decelerate a motor. I am a brand new programmer that knows barely nothing.

Thanks

You should try using a PID controller for this. Here is a document that will get you started:
http://georgegillard.com/documents/2-introduction-to-pid-controllers

2 Likes

I will look into that but is there any other simpler way. I wrote something using only the P in PID

P should be all you need for this. It’s pretty simple too. The I and D components are only needed if you are having issues with drift or friction.

1 Like

I actually do have issues with slight drift. I tried using only P but it didn’t work for me because I probably did it wrong.

P loops will help with the deceleration of your drivetrain, but they won’t do much for your acceleration.

You may want to look into slew rate control with a P (or PID) loop

7 Likes

Since you are new, start simple. Get the motor to work the way you want it to without worrying about how elegant the code looks.

In pseudocode, probably you want something like:

setMotorSpeed(10);
wait(20, msec);
setMotorSpeed(15);
wait(20,msec);
setMotorSpeed(20);
wait(20,msec);
// ... etc.

Recall from math/physics that “acceleration” is change in velocity over some period of time. The pseudocode above does precisely that, it changes the motor speed over some period of time.

6 Likes

It’s weird I tried that in my program but after every time I redeclare the velocity it stops the robot for half a second so its not smooth

If you want something really simple, here is an example of how to do a pseudo-trapezoidal motion profile. It’s definitely not written very well, but hopefully it can get the idea across. It’s basically just two P controllers with a limit. A slew controller for acceleration and a P controller for deceleration would also work well as @trontech569 mentioned.

6 Likes

Perhaps post your code.

While @Bob132 and @trontech569 provide correct answers for longer-term solutions, you probably need to get your feet wet keeping things very simple to start before researching more involved techniques.

6 Likes

Great Thanks for everyones help I have one last question. Is there a way to run through motor commands without the code stopping? For example

FrontLeft.setVelocity(100,pct);
BackLeft.setVelocity(100,pct);
FrontRight.setVelocity(100,pct);
BackRight.setVelocity(100,pct);

FrontLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
FrontRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);

FrontLeft.setVelocity(50,pct);
BackLeft.setVelocity(50,pct);
FrontRight.setVelocity(50,pct);
BackRight.setVelocity(50,pct);

FrontLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
FrontRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);

So when I redeclare the Velocity for the four motors of the drive train that it runs smoothly and won’t have a stop when I redeclare it?

Assuming you are using VexCode, there are a lot of choices to make when commanding a motor to move. For this exercise, you’ll probably want to focus on the method signature vex::motor::spin(directionType dir, double velocity, percentUnits units)

So your code would look something like:

motor m = motor(PORT1, vex::ratio18_1, false); // Or whatever your motor settings are
m.spin(directionType::fwd, 10, velocityUnits::pct);
wait(250, msec); 
m.spin(directionType::fwd, 15, velocityUnits::pct);
wait(250, msec); 
m.spin(directionType::fwd, 20, velocityUnits::pct);
wait(250, msec); 
m.spin(directionType::fwd, 25, velocityUnits::pct);
wait(250, msec); 
m.spin(directionType::fwd, 30, velocityUnits::pct);
// etc.
5 Likes

My guess is that you only observe the motor spin at 50 percent power for 100 degrees. You’d need to provide some way for time to pass between setting the velocity to 100 and then changing it to 50 percent.

The startRotateFor that you use is what is called “non-blocking”. As soon as that line of code is hit, it goes onto the next line. This is useful in your drivetrain for making all 4 motors move the same distance at the same time. Unfortunately, when that last one is reached, the brain will immediately run the next setVelocity, without the motors running the full 100 degrees.

5 Likes

Preserving as much of your code as possible, one first-pass solution would be:

FrontLeft.setVelocity(100,pct);
BackLeft.setVelocity(100,pct);
FrontRight.setVelocity(100,pct);
BackRight.setVelocity(100,pct);

FrontLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
FrontRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);

while(FrontLeft.isSpinning() || BackLeft.isSpinning() || FrontRight.isSpinning() || BackRight.isSpinning()) {
wait(20,msec);
}

FrontLeft.setVelocity(50,pct);
BackLeft.setVelocity(50,pct);
FrontRight.setVelocity(50,pct);
BackRight.setVelocity(50,pct);

FrontLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackLeft.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
FrontRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);
BackRight.startRotateFor(vex::directionType::rev, 100, vex::rotationUnits::deg);

The while loop I inserted checks if any of the 4 motors is still spinning before moving onto the setVelocity(50, pct) lines of code.

5 Likes

PID is an extremely simple way to do this. There are many resources online for how to implement this form of control loop.

Another way is with motion profiling. One very effective way to do this is with BĂ©zier curves- but this can get a tad mathematically complex. You can approximate a simpler solution with a trapezoidal profile.

1 Like

I just implemented this into my code and there is still a pause when I redeclare the velocity and when I run the code and after it reaches the point of after the redeclare the velocity

These are fantastic solutions to the OP’s likely real problem, which is “How do I get my robot to move accurately”.

What is not apparent (and with no disrespect intended to the OP) is whether the OP is at a stage in their programming development where concepts such as “Control Loops”, PID, Motion Profiling, etc. are relevant. Lets try to help the OP move from crawling to walking before introducing running…

2 Likes

If PID is the most easy and efficient way to do this could someone show me an example of how to do this with PID? I don’t really understand this because I’m a newer programmer

Simple P loop can be done like this:

//this is a constant that you will need to tune
double kP = 0.1; 
//error is just the difference between target and current pos
//here I am just getting it from the front left motor, but it doesn't really matter which one you use
double error = targetPos - FrontLeft.position(deg); 
//accuracy is how close you want the robot to get to the target; if it is too small it will take too much time to reach the target, but if it's too large it won't be accurate
//this is needed because the robot will pretty much never be exactly at the target position
double accuracy = 5; 
//run the loop while the robot is not at target position
while (abs(error) > accuracy){
  //update error
  error = targetPos - FrontLeft.position(deg);
  //calculate output power by multiplying error by kP
  double pow = error * kP;
  //assign the power to the motors
  FrontLeft.setVelocity(pow, pct);
  FrontRight.setVelocity(pow, pct);
  BackLeft.setVelocity(pow, pct);
  BackRight.setVelocity(pow, pct);

  FrontLeft.spin();
  FrontRight.spin();
  BackLeft.spin();
  BackRight.spin();
}
//stop when done
FrontLeft.stop();
FrontRight.stop();
BackLeft.stop();
BackRight.stop();
2 Likes

Would I put this before the auton code? Then do the steps of what the robot should do where the void for autonomies starts?