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