Line Tracking Code Help


I’m one of the programmers for team 2929 for Emerald Ridge. Recently our robot was bagged and tagged and I’ve been working on our code for the line tracking sensors, because when we worked on the line tracking in autonomous, the robot only went backwards only, and one time did the spin of death, violently turning left continuously. So I was hoping if anyone sees any bugs in the robot code I’m posting, it would be great if someone could help me find and fix them.

Thanks in advance!

Robot Code.txt (2.49 KB)

Robot Code.txt (2.49 KB)

If your robot is running backwards, then just take the opposite numbers of the motor values (-1 instead of 1) and continue.

Looking over your code, though, there’s a better way of doing it. First of all, I would advise against running a motor at full speed when trying to turn, because you should just be making gradual adjustments. Second, a more accurate autonomous can be achieved by just slightly increasing the speed of whichever side of the robot you want to turn and continuing on. That’s how we did it, and we were extremely consistent in our autonomous at Alamo.

Any chance you could post your autonomous code?



My raw autonomous code wouldn’t be much use to you, as its deeply integrated in our system and would be difficult to read if you don’t know what everything does. But here’s the basic idea:

if (leftSensorTripped) {
   robotDrive->TankDrive(0.7, 0.8);
} else if (rightSensorTripped) {
   robotDrive->TankDrive(0.8, 0.7);
} else {
   robotDrive->TankDrive(0.7, 0.7);

This will gradually get your robot back on the line without overcorrecting. Obviously this is oversimplified and you’ll need to adapt it to your bot, but this shows the basic idea. Note that this will not work well in the Y (middle autonomous) as you need a much sharper turn at the corner. For that you need to make a sharper turn.

Thanks for the info. We’ve gotten our line tracking code working and now we just need access to a real field for tuning!


Our line following algorithm uses PID control. Basically, we combined the readings of the three light sensors into a 3-bit value (0-7) and used it to index a table. If the line is right at the center, it maps to 0.0. If the line is slightly to the left, it maps to 1.0, more to the left maps to 2.0. If the line is slightly to the right, its maps to -1.0 and -2.0 if further right. 999.0 is just a number used to indicate no valid line is found. The number -2.0 to 2.0 is then used as the current input in PID control calculation and the setpoint is 0.0 (the center). The turning power is proportional on how far we are “off course”. The speed driving forward is inversely proportional to the turning power. So the harder we turn, the slower we go. Our algorithm is actually more complicated than that but a simplified version is shown below.

    UINT32 value = 0;
    value = m_leftLightSensor->Get() << 2;
    value |= m_centerLightSensor->Get() << 1;
    value |= m_rightLightSensor->Get();
    return value;
}   //GetRawValue
static float inputMap[8] =
    999.0, //000: n/a (No light)
    -2.0,   //001: Extreme right
    0.0,    //010: Center
    -1.0,   //011: Slight right
    2.0,    //100: Extreme left
    999.0, //101: n/a (At Y)
    1.0,    //110: Slight left
    999.0  //111: n/a (At T)
UINT32 sensorRawValue = GetRawValue();
if (sensorRawValue == 0)
    // deal with losing the line.
else if (sensorRawValue == 0x5)
    // deal with the Y fork.
else if (sensorRawValue == 0x7)
    // deal with the T-end.
    float sensorMappedValue = inputMap[sensorRawValue];
    float turnPower = CalcPIDOutput(sensorMappedValue);
    float drivePower = m_maxDrivePower*(1.0 - fabs(turnPower));
    ArcardeDrive(drivePower, turnPower);

my mentor and i did it in binary case statements and it worked well very confusing though