How to make P Loop (V5 C++)

I swear I’ve looked everywhere for this. I understand the concept, but I don’t understand the implementation. I’ve looked at a bunch of posts here, and things like the George Gillard docs, but still don’t know the implementation. For example, what values would I connect to my variables? Like inertial rotation to my desired or something?

int desired = Inertia.rotation(degrees);
int error = desired - Inertia.rotation(degrees);

With Inertia being my inertial sensor, what would I change/add to make this work? How do I figure out and make my proportional constant?

P is how much the robot tries to get to the 0-error location, so as you get closer it doesn’t try as hard. I haven’t implemented a PID yet (or a P), but from what I know, you would multiply error by P then move your motors by that new value. You can tune a PID using math (I don’t know the math). Another, easier way is to follow the steps in this post.

1 Like

Here’s a p loop in c++:

void turn(float angle, float kP){
     while(1){
          Drive.spin(fwd, kP*(angle-Inertia.rotation(degrees)));
     }
}
6 Likes

I have to determine what kP is, right? What does the angle part refer to and do I need to put in a specific number?

Yes, you have to input kP. angle is the angle the robot turns to.

4 Likes

That function takes two parameters: angle (desired angle of the robot) and kP (constant of proportionality). Angle is the desired angle of the robot in absolute degrees (not heading) that you want the robot to face. In PID/P-loop docs, this is usually called the target.

Yes, you’ll have to tune kP for each subsystem you use a P-loop for. The higher kP is, the more responsive to error the robot will be. That might sound like a good thing, but it gets to a point where your robot will run at full power for a 0.01 degree error. I think I usually start drivetrains off at 0.05 kP, but it depends on the application.

1 Like

Would I have to implement numbers to fit the angle or does it already know the desired angle?
Also @2775Josh how would I change your loop to fit a smart-drive (.spin and fwd wont work- would need some kind of turn and either left or right)

Dont use a smart drive. Make two motor groups, one left and one right. (We’ll call them DriveL and DriveR.) Spin them with voltage, not rpm.

The drive function will be

DriveL.spin(fwd, kP*error, volt);
DriveR.spin(reverse, kP*error, volt);
3 Likes

Yes, it’s a user-defined variable, so you need to specify the desired angle. The robot knows nothing except for the sensor data and the information you give it.

Agreed with Josh, using discrete motor groups will give you much more headroom when you get to more advanced programming.

1 Like

I meant does it know the intended angle based on where I code the inertial sensor to turn?
Like, if I tell the inertial sensor to turnToRotation 90 degrees, would it count 90 degrees as the angle for the “angle” variable?

Heads up, I use V5’s C++, not V5 Pro’s C++.

Will you just code the function and test it out? You can answer almost all of your questions on your own.

4 Likes

No, I think you’re misunderstanding the purpose of the code Josh provided. Functions are pieces of code that can be called whereever you need them. His code is a better alternative to the built in function. I recommend brushing up on functions and the opportunities they provide if you intend to move past the built-in ones. Trying the code on an actual robot and learning from there will always be more valueable than discussing it. Best of luck!

2 Likes

I did. I asked these questions after trying these things, editing them, and still getting errors.

I’ve been trying everything I can think of for forever, but with this

motor_group   leftDrive( lb, lm, lf );
motor_group   rightDrive( rb, rm, rf );

float kP = 1;

int error = angle - Inertia.rotation(degrees);

void Drive(int direction) {
leftDrive.spinFor(forward, error, volt);
rightDrive.spinFor(reverse, error, volt);
}

void turn(float angle, float kP){
     while(true){
          Drive.spin(forward, (angle-Inertia.rotation(degrees)));
     }
}

I still get these 2 errors:
use of undeclared identifier ‘angle’ (I tried making a function for it, but it didn’t work)
member reference base type ‘void (int)’ is not a structure or union (I tried a bunch of different things and looked it up here and elsewhere but I have no clue how to fix it)

This article should help.

5 Likes

It is useful and I may use it in the future, but it doesn’t really help for the current issue. Thanks.

When you first define error, angle hasn’t been defined yet, so it doesn’t have a value.

I also don’t know the scope of your code, but I don’t think you can do calculations and variable assignments like that outside of the main functin.

I believe Josh was trying to educate you about how to avoid issues like this in the future.

Through no fault of your own, it seems you have a few holes in your knowledge of how variables work in C++ (That’s normal, we all had to start somewhere).

Josh's suggestion is, in fact, directly applicable to the bug you have been getting.

Good luck, and happy coding.

6 Likes

Your first error is because you have two variables called angle. It might seem like you only have one, but the first time you define angle, you’re creating a global variable (it’s outside of a function). The second time, your turn function is creating a local variable with the same name, causing an error.

When you have variables in functions (like your direction variable in your Drive function), you need to specify them every time you call the function. For example, in your code, you have to type Drive(50) instead of Drive(). The same is true for your turn function, and any function with these variables (called parameters).

You don’t need to define error outside of your function. Every time you call the function, the error will be different (because your robot will be in a different place with a different target), so it should be a local variable defined and used inside your function.

I don’t understand the purpose of your drive function, some clarification would be appreciated. Why are you using spinFor? if it’s supposed to make the robot drive straight, why is your error being calculated based off the angle and inertial variables? Also, you need to be conscious of the units of your variables. You’re assigning motor power with the error variable, which theoretically should go from -12 to 12 because you’re controlling the motor with voltage, but the possible range of error is much larger than that.

Your turn function is also flawed:

  • Angle is double-defined, as mentioned
  • There is no exit condition for the while loop, so your drive will never stop moving even if it was coded correctly (and thus the function will never end)
  • You can’t use Drive.spin because the .spin only applies to motors and motor groups. You need to control the left and right sides separately.
  • kP is defined as a parameter for the function but never used. Your error calculation is correct but you need to multiply it by kP to get the final power.
2 Likes