実行したいこと
現在、Unityで,マップ内の建物をよけながら車を運転するBotをML-Agentsで実装しているのですが、自分が作ったBotの車がうまく進んでもらえず、ずっとその場でくるくる回っているだけです。
報酬内容
- 前進、後退をするごとに報酬(0.001)を与える
- くるくる回るのを防ぐため、 ハンドルを動かすと罰(-0.001)を与える
- スポーンから300秒すると強制的にリスポーン
- 死亡または壁にぶつかると罰(-10)を与える
毎回100万回ほど学習させていました。
コード
C#(Bot_ML.cs)
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.MLAgents; using Unity.MLAgents.Sensors; using Unity.MLAgents.Actuators; public class Bot_ML : Agent //Agentクラスを継承する { public Bot bot_script; public BotCar botcar_script; public GameObject guns; private void Awake() { } //インスタンス生成時に呼ばれるメソッド public override void Initialize() { } public override void OnEpisodeBegin() { } // 観察の収集 public override void CollectObservations(VectorSensor sensor) { } public override void OnActionReceived(ActionBuffers vectorAction){ //操縦 int move_action = (int)vectorAction.ContinuousActions[0]; if(move_action == 1){ //前進 botcar_script.moveint = 1; AddReward(0.001f); } if(move_action == 2){ //後退 botcar_script.moveint = 2; //AddReward(0.001f); } int turn_action = (int)vectorAction.ContinuousActions[1]; if(turn_action == 1){ botcar_script.turn_int = 1; //左折 AddReward(-0.001f); } if(turn_action == 2){ botcar_script.turn_int = 2; //右折 AddReward(-0.001f); } } public void dead(){ AddReward(-10f); //エピソード終了 EndEpisode(); return; } }
C#(BotCar.cs)
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using Random = UnityEngine.Random; [System.Serializable] public class AxleInfo { public WheelCollider leftWheel; public WheelCollider rightWheel; public bool motor; public bool steering; } public class BotCar : MonoBehaviour { public List<AxleInfo> axleInfos; public float maxMotorTorque; public float maxSteeringAngle; private float NomalMotorTorque; private float ADSMotorTorque; private float BoostMotorTorque; public sys sys_script; //===settings=========================// public int moveint = 1; public int turn_int = 0; //=================================// //Bot_ML public Bot_ML ml_script; void Start() { NomalMotorTorque = maxMotorTorque; } // 対応する視覚的なホイールを見つけます // Transform を正しく適用します public void ApplyLocalPositionToVisuals(WheelCollider collider){ if (collider.transform.childCount == 0) { return; } Transform visualWheel = collider.transform.GetChild(0); Vector3 position; Quaternion rotation; collider.GetWorldPose(out position, out rotation); visualWheel.transform.position = position; visualWheel.transform.rotation = rotation; } private float motor; private float steering; public void FixedUpdate(){ foreach (AxleInfo axleInfo in axleInfos) { if (axleInfo.steering) { axleInfo.leftWheel.steerAngle = steering; axleInfo.rightWheel.steerAngle = steering; } if (axleInfo.motor) { axleInfo.leftWheel.motorTorque = motor; axleInfo.rightWheel.motorTorque = motor; } ApplyLocalPositionToVisuals(axleInfo.leftWheel); ApplyLocalPositionToVisuals(axleInfo.rightWheel); } } void Update(){ switch(moveint){ //移動 case 1: //前進 motor += maxMotorTorque * Time.deltaTime; //StartCoroutine("RandomMoveint"); break; case 2: //後退 motor -= maxMotorTorque * Time.deltaTime; //StartCoroutine("RandomMoveint"); break; } switch(turn_int){ case 1: //左折 if(steering <= -maxSteeringAngle){ steering -= maxSteeringAngle * Time.deltaTime; //StartCoroutine("RandomMoveint"); } if(steering <= maxSteeringAngle){ steering = -maxSteeringAngle; } break; case 2: //右折 if(steering <= maxSteeringAngle){ steering += maxSteeringAngle * Time.deltaTime; //StartCoroutine("RandomMoveint"); } if(steering <= maxSteeringAngle){ steering = maxSteeringAngle; } break; } } }
C#(Bot.cs(一部のみ抜粋))
private IEnumerator autoRespawn(){ yield return new WaitForSeconds(300f); StartCoroutine("dead"); //死亡処理 } public void atDead(){ StartCoroutine("dead"); //死亡処理 }
試したこと
こちらのサイトを参考にして上記の報酬を設定したのですが、うまく動作しませんでした。
説明の不足などがあれば追記します。
まだ回答がついていません
会員登録して回答してみよう