Robot veering when programmed to go straight

We have programmed our drive base to drive forward autonomously for 5 seconds. When the program starts the robot is supposed to drive strait but some how the robot veers off to the right. There is no extra weight on the right side of the robot and the axles are not bent. I see no reason for this veering to occur. Can someone please give ideas of why this is happening.

Thanks for taking time to read my post.

~Cason

No two motors are the same. If you set 127 to all of your motors, because motors are all slightly different, you will get slightly different RPM’s. There are multiple ways this can be accounted for.

PID. How PID works, is it would get both sides to the same distance (using sensors), meaning that your robot would go straight. PID is strange to wrap your head around, so I would do some research into it if you don’t know it already. It is one of the greatest / useful things.

PID would be the more accurate way to go. Another way to go about doing this would to just mess around with the speeds of both sides of the chassis until it goes mostly straight. I say “mostly” because it wont be perfect, but it will be better than nothing.

I would also make sure that there isn’t any extra friction anywhere. One side of your chassis might have more friction on spacers / collars / other things, causing your robot to turn when you drive. You really don’t want extra friction if you don’t need it, stalling motors isn’t fun at all.

If you have any questions about PID, or anything really, just shoot me a message and I’ll gladly help :smiley:

So for driver control if I go forward with the joysticks would the robot still veer? I checked for friction in the spacers collars and stuff like that and there is no extra friction.

Technically, yes.

If you are going to just mess around with the speeds until it goes straight, this is how I would fix it during driver control:

Lets say the robot veers to the left. Meaning you would need the left side faster than the right to go straight. Lets say that if the left side goes 127, and the right goes 100, the robot goes straight.

I would set the left side of my chassis to the raw joystick value, and set the right side to the raw value - 27, because there is a 27 speed difference between both sides to get the robot going straight.

If you are doing PID, you can just implement some fancy code to make the robot go straight when both joysticks are equal to some value.

Check to make sure all of the motors are running? If you have a 4 motor chassis, maybe only 1 motor is running on the side it is veering to. This will sound stupid, but it seriously happens. Check to make sure everything is actually plugged in. That happened to me a couple times…

All the motors are running and everything is plugged in. I guess we will just use PID. Thanks for the help! :smiley:

~Cason

No problem!

And if you need any help, just shoot me a message

This will probably sound very dumb, but also make sure that none of your motors are the wrong gear configuration. Make sure that they are all high speed or all torque or whichever drive you are using. We accidentally put on a high speed motor with 3 high torque motors and we spent forever trying to figure out why the robot wouldn’t go straight.

With respect, do not do this. When driving backwards at full tilt you would be feeding a value of -154 to the motors. They would just error out and nothing would work. Also, when driving backwards you would really veer because now the right side is way overpowered. Finally, when the bot is at rest, it may turn to the left because the right motor is set to -27 when the joysticks are neutral.

I recommend a simple proportion function. Set the slower side to the raw value, and the faster side to X times the raw value. X, in this case, would be 100/127, because 100 is the calibrated power and 127 is the max power.

Now, the function works perfectly. When at rest, all drive motors are off. When moving forwards, everything works. When moving backwards, everything works. And because physics, the intermediary values are far closer to working.

To sum up, here’s some code. It’s not formatted properly because I don’t code in RobotC, but you should get the idea:


set.motor(DriveLeft , JoyLeft);
set.motor(DriveRight , JoyRight * 100 / 127;)

I agree, I wouldn’t do this. But, if you don’t know PID, it would work well enough with some more logic behind it. Just a general concept if you don’t know PID.

And if you are using PID, using PD would be the best imo. Just to smooth it out a bit more when driving so it doesn’t jitter as much. I seems unneeded for what this is doing.

Do you have quad encoders attached to the wheels if so you could do something like
If sensor value encoder1 > sensor value encoder2
motor[right] = speed *.7;
motor[left] = speed;

Something like this would work for driving straight for a given number of encoder ticks.


int dSide, pMod, initialLeft, initialRight;

    initialLeft = SensorValue[enc_baseLeft];
    initialRight = SensorValue[enc_baseRight];

     while (SensorValue[enc_baseLeft] < initialLeft + ticks) {

        dSide = (SensorValue[enc_baseLeft] - initialLeft) - (SensorValue[enc_baseRight] - initialRight);
        pMod = sign(dSide) * power * 0.1;

        setDriveLeft(power);
        setDriveRight(power + pMod);

        delay(20);
    }

Where setDriveLeft() and setDriveRight() are functions for setting the respective sides of the drivetrain.

Wrapped up nicely in a function would be something like this (for autonomous use):

void driveQuad(const int power, const int ticks) {
    int dSide, pMod, initialLeft, initialRight;

    initialLeft = SensorValue[enc_baseLeft];
    initialRight = SensorValue[enc_baseRight];

    // Drive at full power for 80% of ticks
    while (SensorValue[enc_baseLeft] < initialLeft + (ticks * 0.8)) {

        dSide = (SensorValue[enc_baseLeft] - initialLeft) - (SensorValue[enc_baseRight] - initialRight);
        pMod = sign(dSide) * power * 0.1;

        setDriveLeft(power);
        setDriveRight(power + pMod);

        delay(20);
    }

    // Drive at 1/3 Power for remaining 20% of ticks
    while (SensorValue[enc_baseLeft] < initialLeft + (ticks * 0.2)) {

        dSide = (SensorValue[enc_baseLeft] - initialLeft) - (SensorValue[enc_baseRight] - initialRight);
        pMod = sign(dSide) * power * 0.1;

        setDriveLeft((power / 3));
        setDriveRight((power + pMod) / 3);

        delay(20);
    }

    // Stop
    driveTime(-0.5 * power, -0.5 * power, 100);
    setDriveLeft(0);
    setDriveRight(0);
}

Where driveTime() is a function that sets motor values for a specific time:


void driveTime(const int l_power, const int r_power, const int timeMs) {
    int startingTime = nSysTime;

    while (startingTime + timeMs > nSysTime) {
        setDriveLeft(l_power);
        setDriveRight(r_power);
    }

    setDriveLeft(0);
    setDriveRight(0);

}

@NattyMan0007 @2501B RoboJackets @Unionjackjz1 @Mr_L_on_Yoshi @The Electrobotz Thanks for the help, we have fixed the issue.

Guyz…There is no such thing as a stupid question…

Thanks for helping!

~Cason

I’m sorry about interrupting the main question, but I am getting more and more into advanced ROBOTC coding, and there’s a word I don’t seem to understand in the code. Could you tell me what “sign” means?
Thank you so much in advance :slight_smile: .

Oh sorry I didn’t realise that was still in there. the sign() function in there is actually just a function that returns the sign value of an integer. If the value is positive it returns a ‘1’, negative it returns a ‘-1’ and zero returns 0. It’s a way of providing direction. Basically splitting up something like ‘-978’ into ‘-1 * 978’ so in terms of power that tells me which way to turn the wheels to correct for error. If that makes sense

RobotC has a standard function for this called sgn() however I wrote a #define statement for my own that is non-branching and therefore faster to execute. Not that it matters much but saves on computing power when doing this every 20ms.

If you are interested my sign function can be used by adding


#define sign(x) (x > 0) - (x < 0)

to the start of your main code file. Sorry for any confusion :slight_smile: if you want to you can just replace the sign with sgn and it will still work the same.

For those wondering for proof of that being non branching the machine code if written as a function is this:

_sign:
    xorl    %eax, %eax
    testl   %edi, %edi
    setg    %al
    shrl    $31, %edi
    subl    %edi, %eax
    ret

@Vex Dudes 8558B always happy to help.

I’m curious to know how this would work; because “initialLeft” is the same thing as “SensorValue[enc_baseLeft]” and so both of those are technically variables. But, both of them are the same variable so when one of them changes the other will change the same amount(let me know if I’m wrong on one of these). So, the part I’m confused about is if you’re adding something to one of those variables then how would that while statement ever become false??? Thanks to anyone who takes the time to answer :slight_smile:
I’m probably reading it wrong somewhere :stuck_out_tongue:


initialLeft

is only equal to


SensorValue[enc_baseLeft]

at the very beginning of the method, after which it reads in new values from the sensor during the loop.

1 Like

Including this year, I’ve been doing Vex for 3 years.

This has killed me for 3 years in a row.

In RobotC, SensorValue[sensor] is an array value set every cycle to the number of encoder ticks.

As the program executes it only stores it once so


initialLeft

is just a single, unchanging variable referring to the initial position that the shaft started in.
All that is happening is the code is moving a certain number of ticks onwards from where it started where


SensorValue[enc_baseLeft]

is the changing variable in that inequality.