2017-02-21 8 views
2

Я работаю над автономным управляющим решением для Euro Truck Simulator 2 с OpenCV на C++.Как предотвратить чрезмерное исправление в моем автономном решении вождения?

Вот где мы определяем кривые дороги:

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

Текущая проблема заключается в том, что рулевое управление не центрируется достаточно быстро, заставляя его постоянно перевернуться, пока оно не отступит от l ана. Я попытался увеличить чувствительность рулевого управления в игре, чтобы обеспечить более быструю или медленную токарную обработку, но это либо приводит к тому, что грузовик выйдет из-под контроля, либо не станет достаточно поворачиваться при движении по большой кривой.

Мой текущий метод просто делит небольшие движения (от -20px до 20px) на 10, а большие движения - на 20. Я также попытался обратить вспять это, но не исправил проблему с чрезмерной коррекцией.

Есть два возможных решения, которые я нашел до сих пор:

  1. я мог бы постепенно увеличить делитель, для которого применим к move_mouse_pixel, тем самым уменьшая силу рулевого управления делается между небольшими движениями.

  2. Или, я мог бы как-то сделать центр программы рулевого колеса быстрее. Я не знаю, как это реализовать.

Что вы, ребята, думаете?

+2

Я думаю, что [ПИД-регулятор] (https://en.wikipedia.org/wiki/PID_controller) может оказаться полезным. – user2079303

+0

@BrianLittlefield Связанные: [Стэнли: Робот, который выиграл грандиозный вызов DARPA] (http://isl.ecst.csuchico.edu/DOCS/darpa2005/DARPA%202005%20Stanley.pdf). Существует раздел '9.2. Управление рулем ", которое может быть полезно. – Catree

ответ

4

Я считаю, что ПИД-регулятор был бы подходящим для этой задачи. https://en.wikipedia.org/wiki/PID_controller В вашей ситуации это будет выглядеть примерно так:

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

Не следует использовать, если заявление в этом контроллере. Вам нужно держать рулевое управление, даже если нет ошибки для его устранения. Я бы предложил пропустить интегральную часть, потому что ваш объект интегрируется (когда вы не едете прямо, вы интегрируете ошибку). Вам необходимо экспериментально выбрать значения параметров Kp и Kd, например, методом Циглера-Николса https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method.

+0

Хорошо, спасибо за информацию! Я рассмотрю это. –