如何在自动驾驶解决方案中防止过度校正?

3

我正在使用C++和OpenCV开发Euro Truck Simulator 2自动驾驶解决方案。

这里是我们检测道路曲线的地方:

    int bottom_center = 160;
    int sum_centerline = 0;
    int count_centerline = 0;
    int first_centerline = 0;
    int last_centerline = 0;
    double avr_center_to_left = 0;
    double avr_center_to_right = 0;

    //#pragma omp parallel for
    for (int i = 240; i > 30; i--){
        double center_to_right = -1;
        double center_to_left = -1;

        for (int j = 0; j < 150; j++) {
            if (contours.at<uchar>(i, bottom_center + j) == 112 && center_to_right == -1) {
                center_to_right = j;
            }
            if (contours.at<uchar>(i, bottom_center - j) == 112 && center_to_left == -1) {
                center_to_left = j;
            }
        }
        if (center_to_left != -1 && center_to_right != -1){
            int centerline = (center_to_right - center_to_left + 2 * bottom_center) / 2;
            if (first_centerline == 0) {
                first_centerline = centerline;
            }
            cv::circle(outputImg, Point(centerline, i), 1, Scalar(30, 255, 30), 3);
            cv::circle(outputImg, Point(centerline + center_to_right+20, i), 1, Scalar(255, 30, 30) , 3);
            cv::circle(outputImg, Point(centerline - center_to_left+10, i), 1, Scalar(255, 30, 30) , 3);
            sum_centerline += centerline;
            avr_center_to_left = (avr_center_to_left * count_centerline + center_to_left) / count_centerline + 1;
            avr_center_to_right = (avr_center_to_right * count_centerline + center_to_right) / count_centerline + 1;
            last_centerline = centerline;
            count_centerline++;
        }
        else {}
    }

以下是我目前的转向解决方案:

int diff = 0;
    if (count_centerline != 0) {
        diff = sum_centerline / count_centerline - bottom_center;
        int degree = atan2(last_centerline - first_centerline, count_centerline) * 180 / PI;
        //diff = (90 - degree);

        int move_mouse_pixel = diff;
        cout << "Steer: " << move_mouse_pixel << "px ";
        if (diff <= 20 || diff >= -20){
            SetCursorPos(pt.x + (move_mouse_pixel / 10), height / 2);
        }
        else{
            SetCursorPos(pt.x + (move_mouse_pixel / 25), height / 2);
        }
    }

最后,这是我程序目前的功能视频:https://www.youtube.com/watch?v=rqyvoFuGKKk&feature=youtu.be 我目前遇到的问题是方向盘不能快速居中,导致它不断地过度修正,最终偏离车道。我尝试在游戏中增加方向灵敏度,以允许更快或更慢的转弯,但这要么使卡车失控,要么在行驶大曲线时无法转弯。
我的当前方法只是将微小移动(在-20px和20px之间)除以10,而将大移动除以20。我也尝试过反过来做,但没有解决过度纠正的问题。
到目前为止,我找到了两种可能的解决方案:
  1. 我可以逐步增加应用于move_mouse_pixel的分隔器,从而减少在小移动之间进行的转向力量。
  2. 或者,我可以想办法让程序更快地居中转向盘。我不确定我该如何实现这一点。
你们觉得呢?

2
我认为 PID 控制器 可能会很有用。 - eerorika
@BrianLittlefield 相关:Stanley:赢得DARPA大挑战的机器人。有一个9.2.转向控制部分可能会有用。 - Catree
1个回答

5

我认为PID控制器适合这项任务。 https://zh.wikipedia.org/wiki/PID控制器 在您的情况下,它将类似于以下内容:

            diffOld = diff;
            diff = sum_centerline / count_centerline - bottom_center;
            SetCursorPos(width/2 + Kp* diff + Kd*(diff - diffOld) , height / 2);

请勿在此控制器中使用if语句。即使没有错误需要纠正,您也需要保持控制。建议跳过积分部分,因为对象在集成时(当您不直行时)集成误差。您需要使用Ziegler-Nichols方法通过实验选择Kp和Kd参数值。具体信息请参见https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method

好的,谢谢您提供的信息!我会调查一下。 - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接