带油箱踏板的PID Line从动装置

时间:2019-02-15 21:45:00

标签: c

我做了一个(非常糟糕的)线路追随者。

这里是一个草图,可以大致了解机器人的形状以及踏板和传感器的位置

[-] 0  0 [-] // 0 = color sensor
[-]------[-] // - = robot body
[-]------[-] // [-] = tank tread
[-]      [-] 

这是它的作用:

  • 获取红色,绿色和蓝色,取传感器1读数的平均值,对2进行相同的操作

  • 减去以获得价值

  • 此值将通过PID部分

  • 具有计算得出的转向的转向

  • 重复(所有这些都是循环的)

我使用RGB而不是反射强度(通常使用这种强度),因为有时我需要检测传感器下方是否有绿色(如果有,请转弯)。

真正的问题出在转向部分。不幸的是,它只会使电动机加速,这意味着在非常狭窄的转弯中,我们只会失去动力。

最佳地,它应该与另一台电动机(可能是朝另一个方向行驶)进行一些补偿,但是我不确定如何计算电动机的速度,也不确定如何执行此非常严格的线路遵循策略。 / p>

这是代码(我也非常感谢任何有关清理代码的技巧!这是我在C:D中的第一个项目)。我不是要全部阅读(篇幅很长),您也可以只看一下转向功能,然后回到rawFollowLine,这样可以缩短代码。

void rawFollowLine(int speed, float Kp, float Ki, float Kd){

    _checkInit();

    set_sensor_mode(sn_lx_color, "RGB-RAW");
    set_sensor_mode(sn_rx_color, "RGB-RAW");
    //printAllSensors();

    int wasBlackCounter = 0;
    int wasBlack = 0;
    int lastBlack = 0;

    for (int i = 0; i < 2000; i++)
    {

        if (isTerminating == 1)
        {
            killMotors(0);
            break;
        }

        int greenCheck = rawGreenCheck(&wasBlack, &wasBlackCounter, &lastBlack);


        if (wasBlack == 1){
            wasBlackCounter++;
            if (wasBlackCounter > 50){
                wasBlackCounter = 0;
                wasBlack = 0;
            }
        }
        if (greenCheck == 1)
        {
            // lx is green
            killMotors(1);
            usleep(400 * 1000);
            drive(200, 70);
            waitIfMotorIsRunning();
            killMotors(1);
            pivotTurn(-90);
        } 
        else if (greenCheck == 2)
        {
            // rx is green
            killMotors(1);
            usleep(400 * 1000);
            drive(200, 70);
            waitIfMotorIsRunning();
            killMotors(1);
            pivotTurn(90);
        }
        else if (greenCheck == 3)
        {
            // both rx and lx are green
            killMotors(1);
            turn(180);
        }
        else if (greenCheck == 5) 
        {
            if(lastBlack == 2)
            {
                lastBlack = 0;
                drive(100, -200);
                //pivotTurn(50);
            }
            else if (lastBlack == 1)
            {
                lastBlack = 0;
                drive(100, -200);
                //pivotTurn(-50);
            } else {
                pidLineRaw(speed, Kp, Ki, Kd, &lastBlack);  
            }
        }
        else
        {
            pidLineRaw(speed, Kp, Ki, Kd, &lastBlack);  
        }

    }
    killMotors(1);

}


int rawGreenCheck(int *wasBlack, int *wasBlackCounter, int *lastBlack)
{
    // Some documentation
    // return nums:
    // 3 = double green
    // 2 = right green
    // 1 = left green
    // 0 = no green 
    int lx_red;
    int lx_green;
    int lx_blue;

    int rx_red;
    int rx_green;
    int rx_blue;

    get_sensor_value(0, sn_lx_color, &lx_red);
    get_sensor_value(0, sn_rx_color, &rx_red);

    get_sensor_value(1, sn_lx_color, &lx_green);
    get_sensor_value(1, sn_rx_color, &rx_green);

    get_sensor_value(2, sn_lx_color, &lx_blue);
    get_sensor_value(2, sn_rx_color, &rx_blue);

    //printf("rx_red %d\n", rx_red);
    rx_red = (rx_red * rx_ratio_r);
    rx_green = (rx_green * rx_ratio_g);
    rx_blue = (rx_blue * rx_ratio_b);
    //printf("rx_red (again) %d\n", rx_red);

    if(
        lx_red < 55 && 
        lx_green > 90 && 
        lx_blue < 55 && 

        rx_red < 55 && 
        rx_green > 90 && 
        rx_blue < 55
        )
    {
        // rx and lx see green
        if (*wasBlack == 1)
        {
            // Apparently we crossed an intersection!
            printf("Apparently we crossed an intersection!\n");
            // We need to go straight.
            *wasBlack = 0;
            *wasBlackCounter = 0;
            return 0;
        } 
        else
        {
            return 3;
        }
    }
    else if(lx_red < 55 && lx_green > 90 && lx_blue < 55)
    {
        // lx sees green
        return 1;
    }
    else if(rx_red < 55 && rx_green > 90 && rx_blue < 55)
    {
        // rx sees green
        return 2;
    }
    else if(rx_red < 50 && rx_green < 50 && rx_blue < 50 && lx_red < 50 && lx_green < 50 && lx_blue < 50)
    {
        // rx and lx see black
        // this is needed if the intersection has the green tiles after the black line
        printf("We are on the line? Is this an intersection?\n");
        *wasBlack = 1;
        return 0;
    }
    else if(lx_red < 55 && lx_green < 55 && lx_blue < 55)
    {
        // lx = right sees black
        // this is needed if the intersection has the green tiles after the black line
        //printf("We are on the line? Is this an intersection?\n");
        killMotor(1, motor[R]);
        rotateTillBlack(motor[L], sn_rx_color);
        //printf("ASS2\n");
        return 0;
    }
    else if(rx_red < 55 && rx_green < 55 && rx_blue < 55)
    {
        // rx = left sees black
        killMotor(1, motor[L]);
        rotateTillBlack(motor[R], sn_lx_color);
        //printf("ASS1\n");
        return 0;
    }

    //*lx_color_status = 0;
    //*rx_color_status = 0;
    *lastBlack = 0;
    return 0;
}

void pidLineRaw(int speed, float Kp, float Ki, float Kd, int *lastBlack)
{

    int red_lx_color;
    int red_rx_color;

    int green_lx_color;
    int green_rx_color;

    int blue_lx_color;
    int blue_rx_color;

    int lx_color;
    int rx_color;

    int last_error = 0;

    int integral = 0;
    int derivative = 0;

    //float Kp = 0.1;
    //float Ki = 0;
    //float Kd = 0;

    //set_sensor_mode(sn_lx_color, "COL-REFLECT");
    //set_sensor_mode(sn_rx_color, "COL-REFLECT");

    get_sensor_value(0, sn_lx_color, &red_lx_color);
    get_sensor_value(0, sn_rx_color, &red_rx_color);

    get_sensor_value(1, sn_lx_color, &green_lx_color);
    get_sensor_value(1, sn_rx_color, &green_rx_color);

    get_sensor_value(2, sn_lx_color, &blue_lx_color);
    get_sensor_value(2, sn_rx_color, &blue_rx_color);

    lx_color = (red_lx_color + green_lx_color+ blue_lx_color)/3;
    rx_color = ( (red_rx_color*rx_ratio_r) + (green_rx_color*rx_ratio_g) + (blue_rx_color*rx_ratio_b))/3;

    if(*lastBlack == 0)
    {
        int error = lx_color - rx_color;
        integral = integral + error;
        derivative = error - last_error;
        last_error = error;

        int steering_val = (error * Kp) + (integral * Ki) + (derivative * Kd);
        // printf("error: %d\nsteering: %d\n",error, steering_val);
        move_steering(-steering_val, speed, 1, 0);
    } else if (*lastBlack == 1)
    {
        printf("lx_color_status\n");
        move_steering(35, speed, 1, 0);
        move_steering(-2, speed, 1, 0);
    } 
    else if (*lastBlack == 2)
    {
        printf("rx_color_status\n");
        move_steering(-35, speed, 1, 0);
        move_steering(2, speed, 1, 0);
    }
    else
    {
        printf("HMMM: %d\n", *lastBlack);
        exit(666);
    }
}
static void _getSteeringSpeed(int speed, int *lx_speed, int *rx_speed, int steering)
{
    if(steering > 100 || steering < -100)
    {
        printf("Yo wtf steering is %d\n", steering);
    } 
    else 
    {
        int speed_factor = (50 - abs(steering)) / 50;
        *lx_speed = speed;
        *rx_speed = speed;

        if(steering >= 0)
        {
            *rx_speed = *rx_speed * speed_factor;
        } 
        else 
        {
            *lx_speed = *lx_speed * speed_factor;
        }
    }
}

省略了某些部分,是的,不需要它们来解决问题。

我也非常抱歉,因为可能存在未使用的变量等。我正在重构项目,完成后我将更新帖子。

因此,总括来说,我需要确保转向部件正确地转动并沿直线行驶。我怎么做?我编写的代码是否合适?我猜测转向本身可能需要某种反馈回路,以检查其是否在线?

0 个答案:

没有答案