1
\$\begingroup\$

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.

\$\endgroup\$

You must log in to answer this question.

Browse other questions tagged .