How do I apply a constant angular velocity to an orientation over time?

Perhaps this is more of a physics/mathematics question than one for Unreal Engine. Let’s say I have an actor with a location and rotation, plus a constant linear and angular velocity. I know how to apply a constant linear velocity to a location over time:

float DeltaSeconds;
FVector Location;
FVector LinearVelocity;
Location += LinearVelocity * DeltaSeconds;

But how would I apply a constant angular velocity to an orientation (rotation stored as a unit quaternion) over time?

float DeltaSeconds;
FQuat Rotation;
FVector AngularVelocity;
Rotation = ???

Specifically I’m interested in using this code with FBodyInstance and the underlying physics system. Happy to convert between other representations (eg. FRotationMatrix) if it’s easiest.

There are two components to how the Angular Velocity is stored: The direction of the FVector is the axis of the rotation. The length of the FVector is the angle of the rotation (in radians, I believe).

FVector AngularChangeThisFrame = AngularVelocity * DeltaSeconds;
FVector RotAxis = AngularChangeThisFrame.GetSafeNormal();
float RotAngle = AngularChangeThisFrame.Size();
Rotation = FQuat(RotAxis, RotAngle) * Rotation;

Edit: To account

i’m not convinced this is correct. I implemented it and the rotation is basically random

Maybe your angular velocity is nearly zero resulting in inaccuracies. If that’s not it could you test this in a clean project or show your implementation?

I’ve just been doing something similar to this, and you need to be aware of UE4’s annoying inconsistency when it comes to angular units.
For example, the FQuat constructor requires radians, but if you are getting your AngularVelocity vector from GetPhysicsAngularVelocity(), then the length of the vector is the angle in degrees…

Hey, the Angular Rotation needs an Up and Forward Direction to not spin through.
It also needs to calculated in Delta Rotations between the Current and Wanted Rotation.

My Code looks like the following which works perfect, NOTE: I wouldn’t use it on Physics Animations or anything which requires consistent 100% Accurate results every frame, but it’s good enough for everything else.

/**
 * @brief Applies Angular Rotation to an Physics Object
 * @param PhysicsComponent The Shape Component, can be any Physics Object
 * @param WantedRotation The Wanted World Space Rotation
 * @param RotationSpeed The Force we apply to the angular spin
 * @param bIsBouncing true -> It acts like a wobbling object | false -> The Motion act like a object without physics
 */
static FORCEINLINE void ApplyPhysicsAngularRotation(const TObjectPtr<UShapeComponent> PhysicsComponent, const FQuat& WantedRotation, const float& RotationSpeed, const bool& bIsBouncing)
{
	// We calculating here the difference between current forward and up to the wanted forward and up
	// which has the purpose to define the angular delta rotations which we use to create the WantedTorque
	const FVector& CurrentUpVector = PhysicsComponent->GetUpVector();
	const FVector& WantedUpVector = WantedRotation.GetUpVector();
	const FQuat WantedFacing = FQuat::FindBetween(PhysicsComponent->GetForwardVector(), WantedRotation.GetForwardVector());
	const FQuat WantedUp = FQuat::FindBetween(CurrentUpVector, WantedUpVector);
    
	// Here we adding force to the angular rotation
	// the calculation takes the pure quaternion rotations 0 - 1 without quaternion.w
	// because this is usually the spin.
	// So we just calculating 2 FVectors forward and up and multiply it by RotationSpeed
	const FVector& WantedTorque = FVector(WantedFacing.X + WantedUp.X, WantedFacing.Y + WantedUp.Y, WantedFacing.Z + WantedUp.Z) * RotationSpeed * 4;
     
	// Add angular velocity with bAddToCurrent = true which makes it wobble around the origin,
	// set it to false and it wont wobble
	PhysicsComponent->SetAllPhysicsAngularVelocityInDegrees(WantedTorque, bIsBouncing);
}
1 Like