# Objective

I want to achieve the following rotations in Unity:

Pitch (local coordinate system)**: Follow controller input.

• Yaw (global coordinate system): Follow controller input.
• Roll (local coordinate system): Prevent this.
• I want to achieve these rotations using only `AddTorque` or `AddRelativeTorque` (I don’t want to use `Slerp` due to potential issues with passing through walls).

# Problems and Uncertainties

The following issue is occurring:

• When rotating pitch and yaw simultaneously, there is an unnatural behavior (it seems to jitter?). If it weren’t for this, the behavior would be ideal.

## Relevant Source Code

``````void ApplyTorque()
{
rigidBody.AddTorque(0, torqueInput.y * Mathf.PI * coefficient, 0);
rigidBody.AddRelativeTorque(new Vector3(torqueInput.x * Mathf.PI * coefficient, 0, 0));

ApplyTorqueToZeroZRotation();
}

[SerializeField] private float ratio = 20f;
void ApplyTorqueToZeroZRotation()
{
Quaternion q = rigidBody.rotation;

float curPitch = Mathf.Atan2(2 * q.x * q.y + 2 * q.w * q.z, q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z);
float curYaw = Mathf.Asin(-2 * q.x * q.z + 2 * q.w * q.y);
float curRoll = Mathf.Atan2(2 * q.y * q.z + 2 * q.w * q.x, q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z);

Quaternion targetRotation = SetQuaternionForZeroRoll(q);

Quaternion rotationDifference = targetRotation * Quaternion.Inverse(q);

if (rotationDifference.w < 0)
{
rotationDifference = new Quaternion(-rotationDifference.x, -rotationDifference.y, -rotationDifference.z, -rotationDifference.w);
}

Vector3 rot = new Vector3(rotationDifference.x, rotationDifference.y, rotationDifference.z);
}

Quaternion SetQuaternionForZeroRoll(Quaternion q)
{
// Calculate q.z
q.z = -q.x * q.y / q.w;

// Normalize the quaternion
float magnitude = Mathf.Sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z);
q.w /= magnitude;
q.x /= magnitude;
q.y /= magnitude;
q.z /= magnitude;

return q;
}
``````

### Attempts and Research

• Modified the source code on my own.
• Tried other methods.

Results of the above:

I tried applying `Slerp` before assigning to `targetRotation`, but if the `Slerp` speed is too slow, the effect of suppressing roll rotation diminishes, and if the speed is too fast, this issue occurs, so I gave up as it doesn’t seem to be a fundamental solution.

Also, I tried the following code, but when the pitch angle reaches 90 degrees or -90 degrees, attempting to rotate beyond that causes endless roll rotation (in the local coordinate system) instead of continuing the pitch rotation.

``````Quaternion currentRotation = rigidBody.rotation;
Quaternion targetRotation = Quaternion.Euler(new Vector3(currentRotation.eulerAngles.x, currentRotation.eulerAngles.y, 0));

Quaternion rotationDifference = targetRotation * Quaternion.Inverse(currentRotation);

if(rotationDifference.w < 0){
rotationDifference = new Quaternion(-rotationDifference.x, -rotationDifference.y, -rotationDifference.z, rotationDifference.w);
}

var rot = new Vector3(rotationDifference.x, rotationDifference.y, rotationDifference.z) * 20f;
``````

thank you.

At first, I was using the ToAngleAxis() function, but it didn’t work well.

Even after rewriting the code to use quaternion functions, the following issue persists:

## Issue

• When attempting to change the pitch angle beyond 90 degrees or -90 degrees, the pitch angle does not change, and the roll rotation continues instead.

## Code

``````    void ApplyTorqueToZeroZRotation()
{
Quaternion q = droneRigidbody.rotation;

Quaternion targetRotation = SetQuaternionForZeroRoll(q);

Quaternion rotationDifference = targetRotation * Quaternion.Inverse(q);

if (rotationDifference.w < 0)
{
rotationDifference = new Quaternion(-rotationDifference.x, -rotationDifference.y, -rotationDifference.z, -rotationDifference.w);
}

Vector3 rot = new Vector3(rotationDifference.x, rotationDifference.y, rotationDifference.z);