Использование ML-агентов Unity и среды моделирования для обучения искусственного интеллекта для автономной парковки
Прошли те времена, когда мы видели беспилотные автомобили или автономные автомобили только в научной фантастике. Поскольку ведущие мировые производители автомобилей вкладывают большие средства в беспилотные автомобили, станет реальностью то, что беспилотные автомобили станут частью нашего повседневного трафика в течение следующего десятилетия.
Автомобили с автоматическим управлением должны решать широкий круг проблем, таких как обнаружение полосы движения, отслеживание полосы движения, обнаружение сигнала, обнаружение препятствий и многие другие. В этой статье мы собираемся решить одну из проблем - Автономную парковку с помощью среды моделирования Unity и пакета ML-агентов.
Если вы новичок в ML-агентах и задаетесь вопросом, как их настроить, прочтите мою предыдущую статью о тренировке 6-осевой руки робота.
Почему моделирование?
Мы видели, как беспилотные автомобили проходят испытания на дороге. Но это последний этап. Обучение ИИ для автономных транспортных средств проходит примерно в 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. Возможно, вам потребуется импортировать этот пакет с помощью диспетчера пакетов.