currently working on training an Agent to park a car. Before using the ray perception sensor component this was my CollectObservations() method:
Debug.Log("collect observations called");
sensor.AddObservation(transform.localPosition);
sensor.AddObservation(transform.rotation);
sensor.AddObservation(carController.GetVelocity());
Vector3 toTarget = targetParkingSpot.localPosition - transform.localPosition;
Vector3 normalizedToTarget = toTarget.normalized;
sensor.AddObservation(toTarget.magnitude);
sensor.AddObservation(normalizedToTarget);
sensor.AddObservation(rb.velocity.magnitude / maxSpeed);
sensor.AddObservation(rb.angularVelocity.magnitude / maxAngularVelocity);
sensor.AddObservation(targetParkingSpot.localPosition);
sensor.AddObservation(targetParkingSpot.rotation);
Vector3[] raycastDirections = { transform.forward, transform.right, -transform.right, transform.forward + transform.right, transform.forward - transform.right };
foreach (Vector3 direction in raycastDirections)
{
if (Physics.Raycast(transform.localPosition, direction, out RaycastHit hit, maxRaycastDistance))
{
float normalizedDistance = hit.distance / maxRaycastDistance;
sensor.AddObservation(normalizedDistance);
}
else
{
sensor.AddObservation(-1f);
}
}
then when my agent wasn’t responding or doing anything I figured CollectObservations() is at fault so I switched to ray perception sensors. However it the agent is still not moving and at seemingly random i get the “Fewer observations (0) made than vector observation size (21). The observations will be padded.” warning. Here is how my scene is currently set up:
and this is my current script:
using System.Collections;
using System.Collections.Generic;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using UnityEngine;
using Unity.MLAgents.Actuators;
public class CarParkingAgent : Agent
{
public Transform targetParkingSpot;
public CarController carController;
public float maxRaycastDistance = 10f;
private Rigidbody rb;
public float maxSpeed = 10f;
public float maxAngularVelocity = 10f;
private bool isCarParked = false;
public Vector3 tensor;
private bool lastFrameParkedStatus = false;
private int currentStep = 0;
private bool useHeuristic = true; // after ur done with BC just delete this whole logic
//private float totalReward = 0f;
private RayPerceptionSensorComponent3D RayPerceptionSensorComponent;
private int observationCount = 0;
void Awake()
{
RayPerceptionSensorComponent = GetComponent<RayPerceptionSensorComponent3D>();
Debug.Log("Awake called");
rb = GetComponent<Rigidbody>();
rb.inertiaTensor = tensor;
rb.inertiaTensor = new Vector3(1829.532f, 1974.514f, 391.8728f);
useHeuristic = true;
}
private void FixedUpdate()
{
if (!isCarParked)
{
Debug.Log("car aint parked");
isCarParked = IsCarOnParkingSpot();
}
//idk what this does but if i remove it my entire IsCarOnParkingSpot() stops working
if (!lastFrameParkedStatus)
{
isCarParked = IsCarOnParkingSpot();
}
lastFrameParkedStatus = isCarParked;
}
private void Heuristic()
{
if (!useHeuristic)
{
return;
}
else
{
Debug.Log("using heuristics");
}
// Calculate target direction (normalized)
Vector3 toTarget = targetParkingSpot.localPosition - transform.localPosition;
Vector3 normalizedToTarget = toTarget.normalized;
// Apply heuristic actions based on target direction
float steering = Vector3.Dot(normalizedToTarget, transform.right);
float accelerate = Mathf.Clamp01(Vector3.Dot(rb.velocity, transform.forward));
float brake = 0f;
// Apply actions
carController.HandleMotor(accelerate, brake);
carController.HandleSteering(steering);
}
public override void CollectObservations(VectorSensor sensor)
{
Debug.Log("collect observations called");
// Observations related to the agent's position and orientation
sensor.AddObservation(transform.localPosition);
sensor.AddObservation(transform.rotation);
sensor.AddObservation(carController.GetVelocity());
// Observations related to the distance and direction to the target parking spot
Vector3 toTarget = targetParkingSpot.localPosition - transform.localPosition;
Vector3 normalizedToTarget = toTarget.normalized;
sensor.AddObservation(toTarget.magnitude);
sensor.AddObservation(normalizedToTarget);
// Observations related to the agent's speed and angular velocity
sensor.AddObservation(rb.velocity.magnitude / maxSpeed);
sensor.AddObservation(rb.angularVelocity.magnitude / maxAngularVelocity);
// Observations related to the target parking spot's position and rotation
sensor.AddObservation(targetParkingSpot.localPosition);
sensor.AddObservation(targetParkingSpot.rotation);
observationCount += 9;
Debug.Log("Observations made: " + observationCount);
}
public override void OnActionReceived(ActionBuffers actions)
{
Debug.Log("OnActionReceived called");
currentStep++;
float accelerate = Mathf.Clamp(actions.ContinuousActions[0], -1f, 1f);
//Debug.Log("Accelerate: " + accelerate);
float steering = Mathf.Clamp(actions.ContinuousActions[1], -1f, 1f);
//Debug.Log("Steering: " + steering);
float brake = Mathf.Clamp(actions.ContinuousActions[2], 0f, 1f);
//Debug.Log("Brake: " + brake);
carController.HandleMotor(accelerate, brake);
carController.HandleSteering(steering);
}
public override void Heuristic(in ActionBuffers actionsOut)
{
var continuousActionsOut = actionsOut.ContinuousActions;
continuousActionsOut[0] = Input.GetAxis("Vertical"); // Acceleration
continuousActionsOut[1] = Input.GetAxis("Horizontal"); // Steering
continuousActionsOut[2] = Input.GetKey(KeyCode.Space) ? 1.0f : 0.0f; // Brake
}
public override void OnEpisodeBegin()
{
observationCount = 0;
//totalReward = 0f;
currentStep = 0;
Debug.Log("new episode begun");
ResetCarPosition();
isCarParked = false;
lastFrameParkedStatus = false;
}
public void OnTriggerEnter(Collider collision)
{
if (collision.gameObject.CompareTag("Obstacle"))
{
AddReward(-1.0f);
ResetCarPosition();
EndEpisode();
isCarParked = false;
}
else if (collision.gameObject.CompareTag("ParkingSpot") && !isCarParked)
{
IsCarOnParkingSpot();
}
}
public bool IsCarOnParkingSpot()
{
Vector3 toParkingSpot = targetParkingSpot.position - transform.position;
//Debug.Log("Distance from parking spot: " + toParkingSpot.magnitude);
if (toParkingSpot.magnitude < 1f)
{
AddReward(1.0f);
isCarParked = true;
ResetCarPosition();
EndEpisode();
return true;
}
isCarParked = false;
return false;
}
private void ResetCarPosition()
{
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
Vector3 localPosition = new Vector3(
UnityEngine.Random.Range(-7f, -4f),
0.1f,
UnityEngine.Random.Range(-7f, 2f));
//Debug.Log("Calculated Local Position: " + localPosition);
transform.localPosition = localPosition;
transform.localRotation = Quaternion.Euler(Vector3.zero);
}
}
any help is greatly appreciated thankyou in advance.