Resolving gimbal lock without quaternions

Hi there. I am currently trying to rotate a part, a plane or ship for example, without experiencing gimbal lock.

Let’s say I have a part and I want to set it’s X rotation to 90.

part.CFrame = CFrame.Angles(math.rad(90), 0, 0);

does the trick. But now, let’s say that I want to set the Y axis to 90.

Now, let’s set X to 45. What happens is this makes the part rotate 45 degrees on the Z axis. Not what I want.

Let me visualize this:

In the first few seconds, I show how the part can rotate fine on the X axis whilst the Y and Z axis are both 0. Then, I set the Y axis to -90 and try to rotate the X axis again, except now it rotates on the Z axis. This is gimbal lock.

So you may ask, why not just do the 'ol

part.CFrame = part.CFrame * CFrame.Angles(speedX, speedY, speedZ)

Well, the reason is that I do not want to apply a constant rotational speed, I want to set the rotation. I’ve tried to subtract the current rotation from the target angle to find the difference but this produces an odd jittering effect (as in, the arrow shown here has a full out seizure) when it hits certain angles, so I am not certain if that solution would work.

Are there any ways to fully resolve gimbal lock, without using quaternions or applying rotational speed in real-time? I feel like there would be, given that I’ve seen other people do what I’m attempting to achieve without quaternions, but I’m not sure.

When you do this, you reset the quaternion. I would multiply the Angles by a position to resolve the gimbal lock.

1 Like

Mind elaborating? What position? I am setting the object’s position, I just did not include that for the sake of example.

Oh, I see.

I’m not sure the quaternion way of doing it, but my method is rather… hacky.

When rotating, instead of doing pi/2 radians (or 90 degrees), I might do pi/2.001. In some cases, this can solve a lock.

How would that resolve a lock? Could you provide your method in code?

part.CFrame = part.CFrame * CFrame.fromEulerAngles(0, math.pi/2.01, 0)

That does not solve my problem.

Interesting. Could you print the CFrame every frame of the transition to show what’s happening?

There is no transition. I am just trying to set the rotation of the object without gimbal lock.

I meant for the video example.

When I start adjusting the Cframe (after I snap it back to default position), I start at 0,0,0 and then adjust the CFrame to 0,-90,0, then I adjust it to 80,-90,0

since I haven’t thought up a better way of doing it, the way I can think of would be to:
make a function that takes into account the other rotational angles, then uses math to divide up the angle you want to set it to among the axis. That way it accounts for gimbal lock.
There’s probably some much better way, but this’d only be using some basic math.

2 Likes

You might be on to something, but wouldn’t that use trig?

1 Like

Nah it shouldn’t, if my idea works, then all you’d have to do is division, some multiplication then addition.
or do you mean something else by trig (I thought you meant trigonometry)

Meant trigonometry. Honestly, I am not sure what kind of math you would need to do to counteract based on what you mentioned. That’s not my strong suit. Mind demonstrating your idea in code?

yeah, lemme finish writing something I’m working on rn then I’ll come back and give you an example of what I mean.

1 Like

We’re you able to get it to work? I tried compensating by subtracting the difference between the current location rotation and target rotation and It sort of worked but spazzed out at certain rotations.

1 Like

Oh this topic is a bit old, but don’t it works if you simply apply the y rotation after the x rotation ? For me it works and it doesn’t require any true maths.

  • List item
    part.CFrame = CFrame.Angles(your x angle, 0, 0)*CFrame.Angles(0, -math.pi/2, 0)
1 Like