Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • 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 /
  • Help Room /
avatar image
0
Question by ghosttie · Apr 18, 2021 at 01:12 AM · physicsangularvelocitygimbal-lock

cancelling out angularVelocity with forces

I'm creating a space ship game with Newtonian forces. Rather than rotating and translating the ship directly, when the user presses a direction the code fires thrusters in the opposite direction to move or rotate the ship in the right direction - this all works fine.

I'm now trying to add an "auto stop" button so that when the user gets into a spin they can hold down the button and the code will fire the appropriate thrusters to reverse the spin and bring them to a stop.

This works fine for translation and it works fine for rotations in a single axis, but when it's spinning in more than one axis it gets into a situation where it only makes the problem worse - the numbers seem to get flipped so it fires the wrong thrusters.

This sounds like gimbal lock to me, but I've spent all day googling and trying suggestions without success.

Usually the solution to gimbal lock is either separate the axes so each gameobject is only rotated in one axis (which is not possible because a ship floating in space is free to rotate in all axes) or to use quaterions instead of Euler angles (which is not possible because all I have to work with is Rigidbody.angularVelocity which is a Vector3).

What I'm doing is:

  • get Rigidbody.angularVelocity

  • if it's positive in the X axis then fire the pitch down thrusters, if negative pitch up etc.

That's basically it. When it's doing this if I get it to log the angularVelocity and it shows positive X, it'll correctly fire the pitch down thrusters. But this makes it worse and I find that if I manually fire the pitch up thrusters it fixes the spin. So the problem was that it's showing positive X, which must be wrong.

Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Edy · Apr 19, 2021 at 04:17 PM

Note that in Unity / PhysX freely rotating objects rotate around a single static axis defined by the center of mass and the angular velocity. Contrarily to reality, this axis of rotation and the angular velocity never change unless there's some force or torque applied on the object.

A possible solution might be considering the angular velocity as an axis of rotation instead of a set of 3 angular velocities. Then you could figure out the positions of the thrusters with respect to this axis of rotation, and fire them at the appropriate times in order to align this axis of rotation with one of the local axes of the ship (i.e. the one that is closer).

When the axis of rotation is aligned with a local ship axis then the local angular velocity vector should have a single non-zero value. You could then cancel out that velocity using the proper pair of trusters.

I wouldn't try implementing realistic algorithms here because most probably they will require considering the momentum of inertia of the ship. This aspect is severely simplified in PhysX, so such algoritms won't likely work.

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 ghosttie · Apr 20, 2021 at 12:22 AM 0
Share

Thanks for the advice, I'm not really sure how to write code to make it happen though.

I can use Vector3.Dot to compare the angularVelocity to each local axis to find the one it's closest to.

Then I use Vector3.Cross to get an axis I can rotate in to move toward that axis?

I don't understand the math, I'm just failing...

avatar image
0

Answer by SpaceManDan · Apr 20, 2021 at 04:01 AM

Here you go, this has everything you need in it to stabilize torque. You have a little work to do to tailor it to your project but this is how you do it.

 public class TorqueStabilizer : MonoBehaviour {
 
 public float stability = 0.3f;
 public float speed = 2.0f;
 
 // Update is called once per frame
 void FixedUpdate () {
     Vector3 predictedUp = Quaternion.AngleAxis(
         rigidbody.angularVelocity.magnitude * Mathf.Rad2Deg * stability / speed,
         rigidbody.angularVelocity
     ) * transform.up;
 
     Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.up);
     // Uncomment the next line to stabilize on only 1 axis.
     //torqueVector = Vector3.Project(torqueVector, transform.forward);
     rigidbody.AddTorque(torqueVector * speed);
 }
 }
Comment
Add comment · Show 4 · 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 ghosttie · Apr 22, 2021 at 12:56 AM 0
Share

Thanks! I don't suppose you could explain how it works? I'd rather understand so I can improve

avatar image SpaceManDan ghosttie · Apr 22, 2021 at 02:42 AM 0
Share

Sure, lets go through it. I added some stuff so you can play with it. Ok step by step now, here we set up our variables

 public class TorqueStabilizer : MonoBehaviour
 {
 public Rigidbody rb;
 public float stability = 0.3f;
 public float speed = 2.0f;
 public Vector3 wantedUp = new Vector3(0f, 1f, 0f);

 private void Start()
 {
     rb = GetComponent<Rigidbody>();
 }
 private void FixedUpdate()
 {
     if (Input.GetKey(KeyCode.Z))
     {

Here we get a vector of rotation and a torque power to apply based on how fast it's going. The faster it's rotating, the higher the torque will be. We make sure to convert it from a radian so that we can use a Vector 3.

         Vector3 predictedUp = Quaternion.AngleAxis(
         rb.angularVelocity.magnitude * Mathf.Rad2Deg * stability / speed,
         rb.angularVelocity
         ) * transform.up;


Here we get our torqueVector cross product of our prediction verses the EulerAngle we want to orient too "wantedUp". Change wantedUp to the EulerAngle you want to stabilize too. Say for example an input vector from a controller.

         Vector3 torqueVector = Vector3.Cross(predictedUp, wantedUp);

If you don't want to stabilize all the rotation but only the rotation on 1 axis you'd uncomment the next line. Say for example you want to keep y rotation but want to cancel out z rotation. Play with it on and off to see how it behaves.

         // Uncomment the next line to stabilize on only 1 axis.
         //torqueVector = Vector3.Project(torqueVector, transform.forward);

Apply our math to a torque force...

         rb.AddTorque(torqueVector * speed);
     }

I added this so you can get some random spin to try to stabilize.

     if (Input.GetKey(KeyCode.L))
     {
         rb.AddTorque(new Vector3(30f, 30f, 30f));
     }
 }

}

So put a cube in your scene with no parent. Add a rigidbody, set angular velocity to 1 (so it doesn't spinn too much) and turn off gravity. Add this script. press play and then hold L. It will start to spin. Hold Z to activate the stabilizer. Change wantedUp in the inspector to see how it behaves.

As far as your game goes, all you need now is a EulerAngle to call up and assign it to wantedUp.

Have fun!

avatar image SpaceManDan ghosttie · Apr 22, 2021 at 02:57 AM 0
Share

Sorry forgot to say,

I know you wanted to do this with ship thrusters so what you do is read the final torqueVector.

Figure out which thruster is firing on the x axis and feed torqueVector.x to it, y thruster torquevector.y, z thruster torqueVector.z.

Obviously you'll need to write some code to make this work but thats the logic and you should be able to follow it on your own. And it will be good practice since your getting into Newtonian stuff, this is like 101. You can do it though!

avatar image ghosttie SpaceManDan · Apr 29, 2021 at 12:17 AM 0
Share

So Quaternion.AngleAxis gives me a rotation in the direction of the angular velocity, multiplying it by transform.up gives me a vector rotation in local space?

And then Vector3.Cross gives me the right angle to that rotation in world space?

I don't think I understand what Vector3.Project does at all.

I tried feeding torqueVector directly to the appropriate thrusters:

  • It works for roll and pitch, except that it overcorrects and goes back and forth past stationary - I can fix that by adjusting it to give less thrust as it approaches zero.

  • If the ship's up is pointing at world up and I give it a yaw, then torqueVector is zero and it never fires the thrusters. If ship's up is not pointing at world up then when it tries to fix the yaw it ends up rotating in all axes, and never corrects it.

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.

Follow this Question

Answers Answers and Comments

233 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 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 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 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 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 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 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 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 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Control accurate velocity and angular velocity 0 Answers

how to calculate rotation 0 Answers

i wanna set max velocity, max angular velocity to joint 0 Answers

Angular Velocity not correctly rotating objects 1 Answer

Ball slows down too fast.. why? 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