# Rotate around the roll axis or pitch axis, but the object rotates around the pitch axis

### The issue is as follows:

I send the roll, pitch, and yaw of a real camera in world coordinates to Unity. In Unity, I receive these values and make a virtual object move in the same way.

This works well when the yaw value is `0`. However, when the yaw value rotates to approximately `90` degrees or `-90` degrees, whether I rotate around the roll axis or the pitch axis, the object moves along the pitch axis.

### update data

``````void Update()
{
if (positionUpdated)
{
if (Mathf.Abs(bRoll_ - Roll_) > 150 && flag == 2)
{
print("flag = 1 and bRoll_ - Roll_ : " + (bRoll_ - Roll_));
flag = 1;//바꾸기
}
else if (Mathf.Abs(bRoll_ - Roll_) > 150 && flag == 1)
{
print("flag = 2 and bRoll_ - Roll_ : " + (bRoll_ - Roll_));
flag = 2;//그대로
}

if (flag == 1)
{
Roll_2 = Roll_ + 180;
//bPitch_ 150
//Pitch_ 30
if (Pitch_ > 0)
{
Pitch_ = 180 - Pitch_;
}
else if (Pitch_ < 0)
{
Pitch_ = -180 - Pitch_;
}
//bYaw_: 150                           bYaw : -30
//Yaw: 151 + 180 --> -29               Yaw : - 31 + 180  -> 149
//Yaw_ = Yaw_ - 180;
if (Yaw_ > 0)
{
Yaw_ = Yaw_ - 180;
}
else if (Yaw_ < 0)
{
Yaw_ = Yaw_ + 180;
}

print("flag = 1 : Rotate");
print("Roll_2 : " + Roll_2);
transform.position = targetPosition;
//transform.eulerAngles = targetRotation;
transform.eulerAngles = new Vector3(0, 0, 0);
print(" Pitch_ : " + Pitch_ + " Yaw_ : " + Yaw_ + " Roll_2 : " + -Roll_2);
transform.Rotate(Pitch_, 0.0f, 0.0f, Space.World);
transform.Rotate(0.0f, Yaw_, 0.0f, Space.World);
transform.Rotate(0.0f, 0.0f, -Roll_2, Space.World);

bRoll_ = Roll_2 - 180;
bPitch_ = Pitch_;
bYaw_ = Yaw_;
positionUpdated = false;
}
else
{
print("flag = 2 : Rotate");
transform.position = targetPosition;
//transform.eulerAngles = targetRotation;
transform.eulerAngles = new Vector3(0, 0, 0);
print(" Pitch_ : " + Pitch_ + " Yaw_ : " + Yaw_ + " Roll_ : " + -Roll_);
transform.Rotate(Pitch_, 0.0f, 0.0f, Space.World);
transform.Rotate(0.0f, Yaw_, 0.0f, Space.World);
transform.Rotate(0.0f, 0.0f, -Roll_, Space.World);

bRoll_ = Roll_;
bPitch_ = Pitch_;
bYaw_ = Yaw_;
positionUpdated = false;
}
}
else
{
transform.Rotate(0.0f, 0.0f, 0.0f, Space.World);
transform.Rotate(0.0f, 0.0f, 0.0f, Space.World);
transform.Rotate(0.0f, 0.0f, 0.0f, Space.World);
}
}
``````

``````void ParseData(string data)
{
string[] values = data.Split(',');
Vector3 position = new Vector3(
-Convert.ToSingle(values) + 0,
Convert.ToSingle(values) + 0,
Convert.ToSingle(values) + 0);

//Vector3 rotation = new Vector3(
//    Convert.ToSingle(values),
//    -Convert.ToSingle(values),
//    -Convert.ToSingle(values));
Roll_ = Convert.ToSingle(values);
Pitch_ = Convert.ToSingle(values);
Yaw_ = -Convert.ToSingle(values);

targetPosition = position;
//targetRotation = rotation;

positionUpdated = true;
}
``````

Rotating by Roll ⇒ The x-coordinate is the pitch, but the pitch has a Roll value:

Rotating by Pitch ⇒The x-coordinate is the pitch, so the pitch has a Pitch value:

### What did I do wrong??? Is this a gimbal lock???

This is my issue page, and there are videos, and all codes.

thank you

You may have to flip the sign of some of these values because I don’t know if your device considers looking to the right as a positive change in yaw or a negative one. Same goes for pitch and roll.

``````// TODO: These values are currently hardcoded. Use the received data to populate the variables
float deviceYaw   = 90; // If 0 is North, then the device is pointing East
float devicePitch = 45; // Looking 45 deegrees down
float deviceRoll  = 20; // Tilting 20 degrees to the left

// The order of these is VERY IMPORTANT.
// Notice how only the first one rotates in WORLD space. The next two rotate in LOCAL space
Quaternion unityWorldRotation =
Quaternion.Euler(0,            deviceYaw,  0         ) *   // Yaw   in Unity World space
Quaternion.Euler(devicePitch,  0,          0         ) *   // Pitch in Unity Local space
Quaternion.Euler(0,            0,          deviceRoll);    // Roll  in Unity Local space

transform.rotation = unityWorldRotation;
``````

I do not recommend calling `transform.Rotate()` multiple times because it causes the hierarchy to update every time you call it, but if you insist on doing it, then at least remember what I wrote earlier:

1. The order is important: Yaw then Pitch then Roll
2. Only the Yaw is allowed to be performed in World space. Pitch and roll should be done in Local space.

Example:

``````transform.Rotate(0,       Yaw_,  0,      Space.World); // World space
transform.Rotate(Pitch_,  0,     0,      Space.Self);  // Local space
transform.Rotate(0,       0,     -Roll_, Space.Self);  // Local space
``````

For some reason, I cannot edit my first answer, so I had to post a new one.

Thank you very much for the new video. It was really nice to be able to see all the values as you move the camera.

As before, let Roll_, Pitch_, Yaw_ be the raw values received from the device.

``````void Update()
{
if (positionUpdated)
{
transform.rotation = DeviceWorldRotation_to_UnityWorldRotation_v2(Roll_, Pitch_, Yaw_);
positionUpdated = false;
}
}

public Quaternion DeviceWorldRotation_to_UnityWorldRotation_v2 (float roll, float pitch, float yaw)
{
return
Quaternion.Euler(0,      0,     -roll) *
Quaternion.Euler(pitch,  0,     0    ) *
Quaternion.Euler(0,      -yaw,  0    );
}``````