- Home /

# Measure rotation as a gyroscope does (without a real gyroscope)

I decided to edit my question to be less abstract.

I want to emulate the readings of a gyroscope in unity using C# and the engine.

The following code works for most cases:

```
public float rollAngle;
public float rollRate;
void AngleRoll(Quaternion rotationOne, Quaternion rotationTwo){
var rotationA = rotationOne * Vector3.left;
var rotationB = rotationTwo * Vector3.left;
var angleA = Mathf.Atan2(rotationA.x, rotationA.y) * Mathf.Rad2Deg;
var angleB = Mathf.Atan2(rotationB.x, rotationB.y) * Mathf.Rad2Deg;
float prevRollAngle = rollAngle;
rollAngle = Mathf.DeltaAngle(angleA,angleB);
RollRate(rollAngle,prevRollAngle);
}
void RollRate(float newValue,float prevValue){
rollRate = ((newValue - prevValue) / Time.deltaTime);
}
```

There is one of these for each axis X,Y,Z.

One issue that I am facing with this current model is that as the rotation around Y changes the readings for X and Z angles start to change rapidly and the changes become huge when the rotation around Y goes past +90 or -90.

To correct this I have tried to isolate the X,Y,Z parts of the rotation by creating three quaternions that represent the three axis rotations.

```
Quaternion theRot = this.transform.rotation; // Object's rotation
Quaternion xPart = Quaternion.Euler(theRot.eulerAngles.x,0.0f,0.0f); // X part
Quaternion yPart = Quaternion.Euler(0.0f,theRot.eulerAngles.y,0.0f); // Y part
Quaternion zPart = Quaternion.Euler(0.0f,0.0f,theRot.eulerAngles.z); // Z part
Quaternion yBase = Quaternion.identity * yPart; // Quaternion representing current Y rot
AnglePitch(xPart,yBase); //Calc gyro values for x (pitch) using the x/y plane
AngleRoll(zPart,yBase); //Calc gyro values for z (roll) using the z/y plane
AngleYaw(yPart,Quaternion.identity); //Calc values for y (yaw) using the z/x plane
```

This doesn't seem to be working and I am not sure where to go from here. I have tried a couple other ways to get the desired results but this is the closest I have come.

Any insight is welcome

Edit:

They way this is used:

```
private GyroScope gyro;
private Rigidbody physBody;
void Start(){
gyro = new GyroScope(); // Create a new gyroscope
physBody = gameObject.GetComponent<Rigidbody>(); // Get the rigidbody
}
// This maps a value with range (inMin <-> inMax) to the equivalent value in range (outMin <-> outMax)
float Map(float value, float inMin, float inMax, float outMin, float outMax){
return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
void FixedUpdate(){
float rollTar = Map(Input.GetAxis("Horizontal"),-1.0f,1.0f,maxRoll,minRoll); //Get user input for desired roll value
float rollError = rollTar - gyro.rollAngle; // Calc the error between the roll value we want and the gyro rollAngle value
// A PID is a mathematical operation that combines the Proportional/Integral/Derivative of the value into a smooth balanced change
stabiliyRollValue = PID.Compute(rollError); //Compute the value needed to balance our current value combined with our new value
rollRateError = stabiliyRollValue - gyro.rollRate; //Get the error between our desired stability and our actual stability rate
rollOutputCorrection = PID.Compute(rollRateError); //Compute the correction value needed to balance out desired rate and teh actual gyro rate
physBody.AddForceAtPosition(Vector3.up * rollOutputCorrection,thrustPoint[0].position,ForceMode.Force);
}
```

Do everything as a Quaternion, and then just read the Quaternion.eulerAngles to get the actual readings if you need them. Maybe I have misunderstood what you are trying to do, but keeping everything as a Quaternion will be less likely to fail.

The reason I am not using Quaternion.eulerAngles is because the value returned doesn't contain a positive or negative value. For the system that will be using this gyroscope I need to know the direction of the rotation around each axis.

For example if the object's rotation starts falling to the left(-z rotation or negRoll) I apply posRoll torque to correct the rotation.

I feel I am still misunderstanding something, perhaps you have a link for how gyro measurments act, as so far I have found very little, this describes what I was trying to get at:

```
public class gyroScope : MonoBehaviour {
void Start () {
InvokeRepeating("dBug", 1, 1);
}
void dBug(){
Vector3 rot = transform.rotation.eulerAngles;
Debug.Log(string.Format("gyro rotation is ({0}, {1}, {2})", AngleTransform(rot.x), AngleTransform(rot.y), AngleTransform(rot.z)));
}
float AngleTransform(float f){
if(f > 90 && f <= 270){
f = (180-f);
}else{
f = f > 180 ? (f-360) : f;
}
return f;
}
}
```

I just attached that to a cube which i was rotating manually in the scene view whilst playing.

Just read again the second bit, so that you can correct the rotation, you should definitely do as Tanoshimi suggested and look at Angle Axis

The correction forces are on a rigid body and come from an external system to the gyroscope class. All the gyroscope class does is return the angle of rotation from center or zero. This angle comes as a positive or negative angle. The other part of the gyro returns the angular velocity which is the derivative of the angle position over time.

Unless I misread Quaternion.angleaxis it generates a Quaternion representing the provided angle on the provided axis. This doesn't get a Quaternion from an existing rotation.

**Answer** by tanoshimi
·
Aug 10, 2015 at 06:30 AM

Quaternions are vector4s of complex numbers. The components don't represent rotations about axes, so the following lines are incorrect:

```
rollAngle = difference in A.z and B.z;
pitchAngle = difference in A.x and B.x;
```

It sounds like you want ToAngleAxis() instead - http://docs.unity3d.com/ScriptReference/Quaternion.ToAngleAxis.html

The code supplied by my post is pseudo-code. I have updated my post with the actual code I am using.

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.