Использование ML-агентов Unity и среды моделирования для обучения искусственного интеллекта для автономной парковки

Прошли те времена, когда мы видели беспилотные автомобили или автономные автомобили только в научной фантастике. Поскольку ведущие мировые производители автомобилей вкладывают большие средства в беспилотные автомобили, станет реальностью то, что беспилотные автомобили станут частью нашего повседневного трафика в течение следующего десятилетия.

Автомобили с автоматическим управлением должны решать широкий круг проблем, таких как обнаружение полосы движения, отслеживание полосы движения, обнаружение сигнала, обнаружение препятствий и многие другие. В этой статье мы собираемся решить одну из проблем - Автономную парковку с помощью среды моделирования Unity и пакета ML-агентов.

Если вы новичок в ML-агентах и ​​задаетесь вопросом, как их настроить, прочтите мою предыдущую статью о тренировке 6-осевой руки робота.



Почему моделирование?

Мы видели, как беспилотные автомобили проходят испытания на дороге. Но это последний этап. Обучение ИИ для автономных транспортных средств проходит примерно в 3 основных этапа

  1. Моделирование / обучение с учителем - с использованием компьютера или лаборатории
  2. Контролируемое обучение в реальной среде - встроено в кампусе
  3. Обучение в реальном мире - отправляйтесь в путь

В этой статье мы увидим первую фазу, т.е. обучение моделированию, когда ИИ будет обучаться с помощью симуляции физики в компьютерной модели. На этом этапе все существует в виде данных и программного обеспечения. Обученная модель AI будет выдавать только такие сигналы, как количество газа, тормоза и рулевого управления. Ничто не связано с аппаратным обеспечением физического автомобиля. Именно на втором этапе выходной сигнал ИИ будет передаваться на оборудование.

Настройка моделирования

Эта симуляция состоит из двух ключевых частей: одна - это «Автомобиль», которую мы будем называть агентом, идущим вперед, а вторая - это среда, в которой мы тренируем машину. В этом проекте автомобильный элемент создается как префаб и прикрепляется к физическому элементу Rigitbody. Автомобиль, который мы моделируем, имеет следующие значения:

  • Общая масса тела около 1500 кг.

  • Автомобильный контроллер с передним приводом
  • Тормоз на все 4 колеса
  • Крутящий момент двигателя 400
  • Тормозной момент 200 и
  • Максимум. угол поворота 30 градусов

  • Датчики Ray бросают во все четыре стороны автомобиля. Датчики лучей в реальном мире будут похожи на датчики изображения LIDAR.

Обучение с подкреплением

ML-агенты Unity используют обучение с подкреплением (Марковский процесс принятия решений) для обучения агентов. Итак, нам нужен механизм, чтобы сообщить агенту, когда он правильно занял место для парковки. Итак, стоянки настроены с помощью триггерного коллайдера.

Агент получит штраф, если он наткнется на препятствие.

Забавный AI

Во время разработки этого проекта я установил триггер-коллайдер при въезде на каждую парковку, чтобы стимулировать агента к успешному въезду на парковку. Но умный ИИ начал собирать все входные стимулы, линейно покрывая их, вместо того, чтобы входить в лот.

Агент переопределяет

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

public override void OnEpisodeBegin()
{
    _simulationManager.ResetSimulation();
    _simulationManager.InitializeSimulation();
    _nearestLot = null;
}

От ИИ получено 3 сигнала, первый - это количество рулевого управления. во-вторых, это количество дроссельной заслонки, а в-третьих, количество тормозов, применяемых для каждого шага моделирования.

public override void OnActionReceived(float[] vectorAction)
{
    _lastActions = vectorAction;
    _controller.CurrentSteeringAngle = vectorAction[0];
    _controller.CurrentAcceleration = vectorAction[1];
    _controller.CurrentBrakeTorque = vectorAction[2];
}

Состояние моделирования собирается в CollectObservations. Выравнивание скорости с ближайшей парковкой рассчитывается и дается в качестве награды. Следует отметить, что значения датчика луча будут автоматически добавляться в наблюдение на каждом шаге.

public override void CollectObservations(VectorSensor sensor)
{
    if (_lastActions != null && _simulationManager.InitComplete)
    {
        if(_nearestLot == null)
            _nearestLot = _simulationManager.GetRandomEmptyParkingSlot();
        Vector3 dirToTarget = (_nearestLot.transform.position - transform.position).normalized;
        sensor.AddObservation(transform.position.normalized);
        sensor.AddObservation(
            this.transform.InverseTransformPoint(_nearestLot.transform.position));
        sensor.AddObservation(
            this.transform.InverseTransformVector(_rigitBody.velocity.normalized));
        sensor.AddObservation(
            this.transform.InverseTransformDirection(dirToTarget));
        sensor.AddObservation(transform.forward);
        sensor.AddObservation(transform.right);
        // sensor.AddObservation(StepCount / MaxStep);
        float velocityAlignment = Vector3.Dot(dirToTarget, _rigitBody.velocity);
        AddReward(0.001f * velocityAlignment);
    }
    else
    {
        sensor.AddObservation(new float[18]);
    }
}

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

private void OnCollisionEnter(Collision other)
{
    if (other.gameObject.CompareTag("barrier") || other.gameObject.CompareTag("car") ||
        other.gameObject.CompareTag("tree"))
    {
        AddReward(-0.01f);
        EndEpisode();
    }
}

Когда агент успешно въезжает на парковку, вызывается этот триггерный коллайдер, и агенту выдается джекпот. Размер бонуса рассчитывается в зависимости от того, насколько агент привязан к парковке. Минимальный бонус, если машина припаркована лицом к стене, максимальный бонус, если она припаркована лицом к дороге.

private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("agent"))
    {
        if (fullEndCollider.bounds.Intersects(other.bounds))
        {
            if (!IsOccupied)
            {
                float bonusfactor = 0.2f;
                float alignment = Vector3.Dot(gameObject.transform.right,
                    other.gameObject.transform.up);
                if (alignment > 0)
                    bonusfactor = 0.8f;
                float bonus = bonusfactor * Mathf.Abs(alignment);
                other.gameObject.transform.parent.GetComponent<AutoParkAgent>().JackpotReward(bonus);
            }
        }
    }
}

Конфигурация обучения yml настроена так, что у нас есть 4 скрытых слоя с 512 узлами на слой. И мы проводим тренировку из 10 миллионов циклов.

behaviors:
    default:
        trainer_type: ppo
        hyperparameters:
            batch_size: 512 
            buffer_size: 5120
            learning_rate_schedule: linear
            learning_rate: 3.0e-4
        network_settings:
            hidden_units: 512
            normalize: false
            num_layers: 4
            vis_encode_type: simple
            memory:
                memory_size: 512
                sequence_length: 512
        max_steps: 10.0e5
        time_horizon: 64    
        summary_freq: 10000
        reward_signals:
            extrinsic:
                strength: 1.0
                gamma: 0.99
    Autopark:
        trainer_type: ppo
        hyperparameters:
            batch_size: 512
            buffer_size: 5120
        network_settings:
            hidden_units: 512
            num_layers: 4
        max_steps: 10.0e6
        time_horizon: 128

Во время обучения обнаруживается, что агент не обучается должным образом даже после 5 миллионов циклов, если мы всегда помещаем его у въезда на парковку. Таким образом, случайное размещение агента рядом с пустой парковкой увеличивало его шансы на получение награды и, следовательно, увеличивало разброс в обучении. Менеджер симуляции изменен таким образом, чтобы эта рандомизация выполнялась в 50% случаев. В остальное время агент находится у въезда на парковку.

public void PositionAtSafePlace(GameObject nearestLotGameObject)
{
   float[] ang = new float[] {-90f, 90f, 180f, -180f,0f};
   
   if (agent != null)
   {
      agent.GetComponent<Rigidbody>().velocity = Vector3.zero;
         agent.GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
         agent.GetComponent<CarController>().CurrentSteeringAngle = 0f;
         agent.GetComponent<CarController>().CurrentAcceleration = 0f;
         agent.GetComponent<CarController>().CurrentBrakeTorque = 0f;
         Vector3 newPosition = nearestLotGameObject.transform.position +
                               nearestLotGameObject.transform.right * Random.Range(-3f, -7f) +
                               nearestLotGameObject.transform.forward * Random.Range(-1f, 1f);
         agent.transform.position = newPosition;
         agent.transform.Rotate(agent.transform.up,ang[Random.Range(0,4)]);
   }
}

Тензорный график после 5 миллионов циклов выглядел так

Агент не только увеличил вознаграждение, но и оптимизировал количество шагов для достижения оптимального решения (правый график). В среднем потребовалось 40 сигналов (например, разгон, рулевое управление, тормоз), чтобы принять его от въезда на пустую парковку.

В знак признательности за то, что вы прочитали эту статью до сих пор, пожалуйста, найдите весь исходный код этого проекта в https://github.com/xrpractice/AutonomousParkingMLUnity. В этой статье мы использовали фреймворки ML-Agents версии 1.0.3. Возможно, вам потребуется импортировать этот пакет с помощью диспетчера пакетов.

Интересные обучающие материалы