Controller Axis Sensitivity


#1

Can someone post code on nonlinear scaling for a tank style drive? I’m looking to make turning less sensitive while still being able to reach max speed when the joysticks are fully displaced.


#2

Normally I wouldn’t answer a VCS tagged question, but this does not seem specific to VCS. Here are two methods of how to do this in Robot Mesh Studio: link. I have not gotten a chance to test these algorithms for bugs yet, but they should be the kind of thing you’re looking for.


#3

and a VC++ Text example - four motor using a cube function. Suggest by QCC2 Jason McKinney after testing a V5 robot. Works like a charm.

void usercontrol( void ) {

    int32_t leftstick = 0;
    int32_t leftside = 0;
    int32_t rightstick = 0;
    int32_t rightside = 0;
    // User control code here, inside the loop
    while(true) {

        leftstick = Controller1.Axis3.position( percentUnits::pct);
        leftside = leftstick * leftstick * leftstick / 10000;
        rightstick = Controller1.Axis2.position( percentUnits::pct);
        rightside = rightstick * rightstick * rightstick / 10000;
        Leftfront.spin(vex::directionType::rev, leftside, vex::velocityUnits::pct); 
        Leftback.spin(vex::directionType::rev, leftside, vex::velocityUnits::pct); 
        Rightfront.spin(vex::directionType::rev, rightside, vex::velocityUnits::pct);
        Rightback.spin(vex::directionType::rev, rightside, vex::velocityUnits::pct);     

fixed code error after post.


#5

Oops - that was the old code – it was fixed oopsie


#6

My students have found ^3 sometimes insufficient. So some of them have moved to ^5. Be careful when you do, though. Order of operations matters. If you raise to the 5th power before ever dividing, you can accidentally hit the cap for integers. So if you want to go to something like the 5th power, you want something like

leftside = leftstick * leftstick * leftstick / 10000 * leftstick * leftstick / 10000;

instead of

leftside = leftstick * leftstick * leftstick * leftstick * leftstick / 100000000;


#7

Assuming your saving the intermediate joystick value as an int like in the above example this would have integer division issues. Probably should use a .0 on that number just to avoid any potential issues. As it stands you are almost certainly going to have 0 always.(assuming joystick value saved as int)


#8

Probably best for everyone to read this post on the same topic. It can be very easy to make a mistake with the integer division so I save the intermediate values as floats.


#9

This is why my example just casts to doubles. The V5’s processor is fast enough.


#10

Fair enough point. I edited my above posts to correct for this mistake. It should be pointed out that @lacsap 's example would have had the issues I was describing.


#11

Yes, better to do it with a double or a float, divide by 100 before multiplying for the power, and then scale it back by multiplying by 100 in the end. And, yes, if I only wanted to deal with int’s, it could be handled better. This would work pretty well with int’s:

leftside = leftstick * leftstick * leftstick * leftstick / 100 * leftstick / 1000000;

The rounding off from that first /100 shouldn’t be so bad. When it makes a noticeable difference, you’re probably at values that are small enough they’re in the dead zone. A well-planned automatic dead zone using int’s is probably the only nice thing about using int’s, since you don’t have to do the extra check for your dead zone. For example

leftside = leftstick * leftstick / 100 * leftstick / 100;

results in a dead zone of -9 to 9. (Yes, you’ll get more zeros beyond 9, but this handles the sign issue for -9 to 9.)

Personally, ^5 is too extreme, but I wasn’t going to stop them from trying it out. I would probably choose a more complex piecewise-defined function myself. I’d rather increase slowly but more linearly from ±5ish to ±50ish on the joystick, and then ramp it up to 100% from the roughly 10-20% I would target with 50ish values from the joystick.