using UnityEngine;
namespace NanoBrain.Unity.Braitenberg {
///
/// A powered wheel collider, controlled by a NanoBrain::Neuron
///
[RequireComponent(typeof(WheelCollider))]
[HelpURL("https://passer.life/documentation/nanobrain/Documentation/html/class_nano_brain_1_1_unity_1_1_braitenberg_1_1_motor.html")]
public class Motor : MonoBehaviour {
///
/// The name of the NanoBrain::Neuron to control this wheel
///
/// This is used to connect the motor to the right output neuron of the Vehicle::brain
[Tooltip("The name of the Nanobrain Neuron to control this wheel")]
public string outputNeuronName;
///
/// The speed of the motor in rotations per second
///
[Tooltip("The speed of the motor in rotations per second")]
public float speed { get; protected set; }
///
/// The maximum torque used to drive the wheel collider
///
[Tooltip("The maximum torque used to drive the wheel collider")]
public float maxTorque = 1;
///
/// The wheel collider used to drive the car
///
/// \see [Unity WheelCollider](https://docs.unity3d.com/ScriptReference/WheelCollider.html)
[Tooltip("The wheel collider used to drive the car")]
public WheelCollider wheelCollider;
///
/// The NanoBrain::Neuron to control this wheel
///
[Tooltip("The NanoBrain Neuron to control this wheel")]
public Neuron motorNeuron;
///
/// Unity calls Awake when loading an instance of a script component.
///
protected virtual void Awake() {
wheelCollider = GetComponent();
GetMotorNeuron();
}
///
/// Retrieve the motor neuron from the outputNeuronName;
///
private void GetMotorNeuron() {
if (motorNeuron != null)
return;
Vehicle vehicle = GetComponentInParent();
if (vehicle == null)
return;
Cluster brain = vehicle.brain;
if (brain != null)
motorNeuron = brain.GetNeuron(outputNeuronName);
}
///
/// Update called at regular, fixed intervals as part of Unity's physics update loop.
///
void FixedUpdate() {
if (motorNeuron == null)
return;
this.speed = motorNeuron.outputValue.z;
Debug.DrawRay(this.transform.position, this.transform.forward * this.speed, Color.blue);
float desiredRpm = speed * 60; // target wheel RPM
float currentRpm = wheelCollider.rpm;
float rpmError = desiredRpm - currentRpm;
float kP = 0.02f; // proportional gain
float torque = wheelCollider.motorTorque + kP * rpmError;
wheelCollider.motorTorque = Mathf.Clamp(torque, -maxTorque, maxTorque);
}
}
}