100 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| #if UNITY_5_3_OR_NEWER
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace RoboidControl.Unity {
 | |
|     public class DifferentialDrive : Thing {
 | |
| 
 | |
|         public Wheel leftWheel;
 | |
|         public Wheel rightWheel;
 | |
|         public SphereCollider casterWheel;
 | |
| 
 | |
|         protected RoboidControl.DifferentialDrive coreDrive => core as RoboidControl.DifferentialDrive;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Create the Unity representation
 | |
|         /// </summary>
 | |
|         /// <param name="core">The core touch sensor</param>
 | |
|         /// <returns>The Unity representation of the touch sensor</returns>
 | |
|         public static DifferentialDrive Create(RoboidControl.DifferentialDrive core) {
 | |
|             DifferentialDrive component = null;
 | |
|             Rigidbody rb = null;
 | |
|             GameObject prefab = (GameObject)Resources.Load("DifferentialDrive");
 | |
|             if (prefab != null) {
 | |
|                 // Use resource prefab when available
 | |
|                 GameObject gameObj = Instantiate(prefab);
 | |
|                 component = gameObj.GetComponent<DifferentialDrive>();
 | |
|                 if (component != null)
 | |
|                     component.core = core;
 | |
| 
 | |
|                 rb = component.GetComponent<Rigidbody>();
 | |
|             }
 | |
|             else {
 | |
|                 // Fallback implementation
 | |
|                 GameObject gameObj = new(core.name);
 | |
|                 component = gameObj.AddComponent<DifferentialDrive>();
 | |
|                 component.Init(core);
 | |
| 
 | |
|                 rb = gameObj.AddComponent<Rigidbody>();
 | |
|                 rb.isKinematic = false;
 | |
|                 rb.mass = 0.1f;
 | |
|             }
 | |
|             return component;
 | |
|         }
 | |
| 
 | |
|         private Rigidbody rb = null;
 | |
| 
 | |
|         protected virtual void Start() {
 | |
|             rb = GetComponent<Rigidbody>();
 | |
|         }
 | |
| 
 | |
|         protected override void HandleBinary() {
 | |
|             Debug.Log("Diff drive handle Binary");
 | |
|             if (coreDrive.wheelRadius <= 0 || coreDrive.wheelSeparation <= 0)
 | |
|                 return;
 | |
| 
 | |
|             if (leftWheel == null)
 | |
|                 leftWheel = Wheel.Create(this.transform, coreDrive.leftWheel.id);
 | |
| 
 | |
|             leftWheel.core ??= coreDrive.leftWheel;
 | |
|             SphereCollider leftWheelCollider = leftWheel.GetComponent<SphereCollider>();
 | |
|             leftWheelCollider.radius = coreDrive.wheelRadius;
 | |
|             // leftWheelCollider.center = new Vector3(-coreDrive.wheelSeparation / 2, 0, 0);
 | |
| 
 | |
|             if (rightWheel == null)
 | |
|                 rightWheel = Wheel.Create(this.transform, coreDrive.rightWheel.id);
 | |
| 
 | |
|             rightWheel.core ??= coreDrive.rightWheel;
 | |
|             SphereCollider rightWheelCollider = rightWheel.GetComponent<SphereCollider>();
 | |
|             rightWheelCollider.radius = coreDrive.wheelRadius;
 | |
|             // rightWheelCollider.center = new Vector3(coreDrive.wheelSeparation / 2, 0, 0);
 | |
| 
 | |
|             if (casterWheel == null) {
 | |
|                 GameObject gameObj = new("Caster wheel");
 | |
|                 gameObj.transform.parent = this.transform;
 | |
|                 casterWheel = gameObj.AddComponent<SphereCollider>();
 | |
|                 casterWheel.material = Wheel.slidingWheel;
 | |
|             }
 | |
|             casterWheel.radius = coreDrive.wheelRadius;
 | |
|             // Put it in the middle of the back
 | |
|             casterWheel.center = new Vector3(0, 0, -coreDrive.wheelSeparation);
 | |
|         }
 | |
| 
 | |
|         protected override void FixedUpdate() {
 | |
|             base.FixedUpdate();
 | |
| 
 | |
|             if (rb != null && leftWheel != null && rightWheel != null) {
 | |
|                 float leftWheelVelocity = leftWheel.rotationSpeed * (2 * Mathf.PI) * coreDrive.wheelRadius;
 | |
|                 float rightWheelVelocity = rightWheel.rotationSpeed * (2 * Mathf.PI) * coreDrive.wheelRadius;
 | |
| 
 | |
|                 float forwardSpeed = (leftWheelVelocity + rightWheelVelocity) / 2f;
 | |
|                 float turningSpeed = (leftWheelVelocity - rightWheelVelocity) / coreDrive.wheelSeparation;
 | |
| 
 | |
|                 // Use smoothing to emulate motor inertia
 | |
|                 rb.velocity = 0.9f * rb.velocity + 0.1f * forwardSpeed * transform.forward;
 | |
|                 rb.angularVelocity = 0.9f * rb.angularVelocity + 0.1f * turningSpeed * Vector3.up;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| #endif |