Monday, April 17, 2017

unity - How to align angular velocity wit target rotation in 3D?


I'm making a space crew sim (controlling a ship) and have recently posted a question about how to calculate ETA between two rotations. I how now a new question more well defined.


Background: I have Qtarget and Qcurrent(the ships rotation) and can find Qdelta using Qdelta = Qcurrent ^-1*Qtarget. And I have the angular velocity in rotation speed around the world axis from the Unity.



I want to control the ship only using delta angular velocity around ships axis.


I want to get the angular velocity aligned with Qdelta so i can just use that angular velocities e.g. x part and the angel to solve for if I should accelerate or decelerate and just decelerate along the y and z axis. After that I want to rotate that data back to ship rotation.


I have this test code:


using UnityEngine;
using System.Collections;

public class RoationTest : MonoBehaviour {
public Vector3 startAngularVelocity = new Vector3();
public Vector3 targetRoation = new Vector3();
public Vector3 maxShipDeltaAngularVelocity = new Vector3();



// Use this for initialization
void Start (){
rigidbody.angularVelocity = startAngularVelocity*Mathf.Deg2Rad;
rigidbody.WakeUp();
}

// Update is called once per frame
void Update () {

Vector3 currentAngularVelocity = rigidbody.angularVelocity*Mathf.Rad2Deg; //This seams to work
Quaternion deltaRoationQuat = Quaternion.Inverse(rigidbody.rotation) * Quaternion.Euler(targetRoation); //This seams to work

float deltaAngel = Quaternion.Angle(rigidbody.rotation,Quaternion.Euler(targetRoation)); //This seams to work

Vector3 xAxis = new Vector3(1,0,0);
Vector3 deltaRotationAxis = deltaRoationQuat.eulerAngles;
Vector3 deltaRotationAxisClampedToShortestDist = ClampEulerAngelsToClosest(deltaRotationAxis);
Quaternion AlignQuat = Quaternion.FromToRotation(deltaRotationAxisClampedToShortestDist, xAxis);


Vector3 angularVelocityAligend = AlignQuat*currentAngularVelocity; //This should be Quaternion.Inverse(AlignQuat)*currentAngularVelocity; But that does not work as I think I should but this do.
Vector3 maxDeltaAngularVelocityGlobalRotaion = rigidbody.rotation*maxShipDeltaAngularVelocity; //Transform max delta angular velocity from ship rotation to global space. The same as maxShipDeltaAngularVelocity*Quaternion.Inverse(rigidbody.rotation) but Unity do not suport that.
Vector3 maxAlignedDeltaAngularVelocity = AlignQuat*maxShipDeltaAngularVelocity;
}

private Vector3 ClampEulerAngelsToClosest(Vector3 rotation){
if(rotation.x>180){
rotation.x = rotation.x-360;
}
if(rotation.y>180){

rotation.y = rotation.y-360;
}
if(rotation.z>180){
rotation.z = rotation.z-360;
}
return rotation;
}
}

Questions: Why do this Vector3 angularVelocityAligend = AlignQuat*currentAngularVelocity; align y axis with x axis? It should be Vector3 angularVelocityAligend = Quaternion.Inverse(AlignQuat)*currentAngularVelocity; in my understanding.



Also how can Vector3 maxDeltaAngularVelocityGlobalRotaion = rigidbody.rotation*maxShipDeltaAngularVelocity; be right?


General thoughts: Is this clear enough or am I taking the wrong approach? I general words I want to find the optimal solution in every frame on how to reach target rotation only using delta angular velocity limited by a max value (the ships engines effect) and also receive and ETA. I understand this is an approximation I state above since i assumes no rotation perpendicular to Qdelta but this solution will do for a start.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...