Rotation issues, Gimbal Lock and quaternions in flight mechanics (C++)

Hi!

I am using UE 5.4.3 and C++.

I am working on a small spaceship project and while working on the flight mechanics I ran into some issues with making the spaceship rotate properly.

My spaceship is a pawn with FloatingMovement component (btw I am not sure if this is the proper way to do it, just felt kinda straight forward). I set up the Enhanced Input system with a steer action that is a Vector2D.
I have a very simple plan for the start: with the WSAD keys held down, the spaceship’s pitch and yaw should update and the spaceship should rotate up / down and to the sides accordingly.

At first I’ve done it with Rotators but very soon I ran into the Gimbal Lock issue when attempting to make a full 360 steer and figured out I should switch to quaternions.
This is how the function that handles input from the user look like:

void APlayerSpaceship::handleSteerInput(const FInputActionValue& value)
{
	const auto input = value.Get<FVector2D>();
 	const auto deltaRot = FRotator(input.Y, input.X, 0).Quaternion();
 	AddActorLocalRotation(deltaRot);
}

I’m curerntly having the following issue:
If I steer at one direction only, everything worksfine. However if I combine sidewise and upwise steering at the same time, instead of just having the pitch and yaw updated, the roll is being changed too.

I attached a video for reference, you can see the rotation values at the top left.

Any idea what makes this happen?

Thanks!

The first issue is not a gimbal lock problem; it’s possible that the rotation of other components in your pawn is causing this phenomenon. I wasn’t able to reproduce this issue.

If you want to replicate the gimbal lock problem, you can write the following code:

void APlayerSpaceship::handleSteerInput(const FInputActionValue& value)
{
    const auto input = value.Get<FVector2D>();
    const auto deltaRot = FRotator(input.Y, input.X, 0) + GetActorRotation();
    SetActorRotation(deltaRot);
}

As for the second issue, the change in roll is normal. Due to the gimbal lock problem, Euler angles cannot be simply added together; instead, transformations should be applied using matrices to ensure the rotation matches the visual effect. If you want to learn more, you can look up information related to Euler angles.

Actually the code snippet that you posted is what I had initially.
The thing is that now I switched to using quaternions instead of Euler angles which did solve the gimbal lock issue. I just don’t understand what causes the roll problem.

Finally found the solution here:

This code now fixed my issues:

void APlayerSpaceship::handleSteerInput(const FInputActionValue& value)
{
	const auto input = value.Get<FVector2D>();
	
	const auto currentQuat = GetActorQuat();
	const auto currentRotation = GetActorRotation();
	const auto newQuat =
		FRotator(0, input.X * steeringSpeed, 0).Quaternion() *
		currentQuat *
		FRotator(input.Y * steeringSpeed, 0, 0).Quaternion();

	SetActorRotation(newQuat);
}```

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.