• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by StewVanB · Aug 10, 2015 at 04:23 AM · rotationquaternionangle

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);
     
 }
Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Scribe · Aug 13, 2015 at 02:31 PM 0
Share

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

avatar image StewVanB · Aug 13, 2015 at 02:39 PM 0
Share

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.

avatar image Scribe · Aug 13, 2015 at 03:07 PM 0
Share

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 : $$anonymous$$onoBehaviour {
     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.

avatar image Scribe · Aug 13, 2015 at 03:29 PM 0
Share

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

avatar image StewVanB · Aug 13, 2015 at 03:45 PM 0
Share

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.

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image
1

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

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image StewVanB · Aug 10, 2015 at 03:48 PM 0
Share

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

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

25 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

90 Degree stopping rotation on y-axis issue 0 Answers

How to get angular difference? 2 Answers

Align GameObject to Terrain angle 2 Answers

Creating a multiple part turret what locks onto certain axis. 4 Answers

Why is my Quaternion rotation going crazy? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges