- Home /
How to Display Degrees Per Second of each Rotation Axis or 'Local' Angular Velocity
I have a space based lunar module game and I want to display the rotation rate of each axis in the HUD.
I'm not very good with vector math and I tried using the rigidbody.angular velocity but that is aligned with the world axis I quickly found out.
So I tried using the localEulerAngles and testing the difference between them every second.
Like this:
void FixedUpdate() { if (Time.time >= nextSample) { pitchDiff = Mathf.Abs(Lunar.transform.localEulerAngles.x - lastPitchAngle); yawDiff = Mathf.Abs(Lunar.transform.localEulerAngles.y - lastYawAngle); rollDiff = Mathf.Abs(Lunar.transform.localEulerAngles.z - lastRollAngle);
lastPitchAngle = Lunar.transform.localEulerAngles.x;
lastYawAngle = Lunar.transform.localEulerAngles.y;
lastRollAngle = Lunar.transform.localEulerAngles.z;
nextSample = Time.time + sampleRate;
}
}
This 'sort of' works but I get bad results when the angle passes to and from 360 to 1 within a second.
I also noticed that it gets less accurate the faster the object spins.
This does seem like a rather crappy approach or I just need to find a better way to derive the angle difference every second.
I essentially want they 'local' angular velocity of each axis.
Answer by hellcats · May 03, 2011 at 04:37 AM
Try using DeltaAngle. This gives you the minimum difference between two angles
pitchDiff = Mathf.DeltaAngle(Lunar.transform.localEulerAngles.x, lastPitchAngle);
Answer by sh0v0r · May 03, 2011 at 05:33 AM
I ended up using the Angle class on the Unify Wiki which has a Difference function.
void FixedUpdate() { // This code relys on the Angle class which is a Boo script in the standard assets/scripts folder Angle cx = new Angle(Lunar.transform.localEulerAngles.x, AngleMode.Degree); Angle cy = new Angle(Lunar.transform.localEulerAngles.y, AngleMode.Degree); Angle cz = new Angle(Lunar.transform.localEulerAngles.z, AngleMode.Degree);
if (Time.time >= nextSample)
{
Angle lx = new Angle(lastPitchAngle, AngleMode.Degree); // Pitch
pitchRate = (float)(cx.Difference(lx)).Deg;
Angle ly = new Angle(lastYawAngle, AngleMode.Degree); // Yaw
yawRate = (float)(cy.Difference(ly)).Deg;
Angle lz = new Angle(lastRollAngle, AngleMode.Degree); //Roll
rollRate = (float)(cz.Difference(lz)).Deg;
// update last angle values for next sample
lastPitchAngle = Lunar.transform.localEulerAngles.x;
lastYawAngle = Lunar.transform.localEulerAngles.y;
lastRollAngle = Lunar.transform.localEulerAngles.z;
nextSample = Time.time + sampleRate;
}
}
I need to improve this so the values are updated every frame ins$$anonymous$$d of every second. That should just require some time division of the difference.
Answer by sh0v0r · May 03, 2011 at 12:40 PM
So here's the current 'realtime' solution, I ended up making my own Angle Difference function and got rid of the Angle class as it was written in Boo and was introducing some weird floating point error.
float AngleDifference(float angA, float angB) { float diff = Mathf.Abs(angA - angB);
if (diff > 180) diff = 360 - diff;
return diff;
}
void FixedUpdate() // used to calculate roll rates and add rotation stabilisation when rotation rate is very low. { float frameDivider = 1 / Time.deltaTime;
pitchRate = AngleDifference(Lunar.transform.localEulerAngles.x, lastPitchAngle) * frameDivider;
yawRate = AngleDifference(Lunar.transform.localEulerAngles.y, lastYawAngle) * frameDivider;
rollRate = AngleDifference(Lunar.transform.localEulerAngles.z, lastRollAngle) * frameDivider;
// update last angle values for next sample
lastPitchAngle = Lunar.transform.localEulerAngles.x;
lastYawAngle = Lunar.transform.localEulerAngles.y;
lastRollAngle = Lunar.transform.localEulerAngles.z;
}
There is a problem still though, Yaw and Roll work perfectly when rotating on a single axis but if I rotate only around the X axis (Pitch) as the angle approaches 90 degrees forward or backward, Yaw and Roll start to show a change in their value, this is because the Euler angles are also World Axis aligned. I tested this by rolling 90 degrees to the side then applying a pitch rotation which caused the Yaw value to change.
So it looks like I am going to have to use some sort of more complex vector derived solution...
Answer by Klaus-Eiperle · May 21, 2014 at 11:34 AM
Hi,
just found your question. Maybe my reply helps others.
Transform _transform;
Rigidbody _rigidbody;
float degreePerSecondY;
Vector3 cachedAngularVelocity;
void Awake() {
_transform = transform; // Transform into cache
_rigidbody = rigidbody; // Rigidbody into cache
}
void FixedUpdate() {
cachedAngularVelocity = _transform.InverseTransformDirection(_rigidbody.angularVelocity);
degreePerSecondY = cachedAngularVelocity.y/Time.fixedDeltaTime;
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613131025im_/https://answers.unity.com/themes/thub/images/avi.jpg)