Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to manipluate angular velocity

Discussion in 'Physics for ECS' started by Bieger, Feb 21, 2020.

  1. Bieger


    Jul 29, 2018
    Hi there, since the current iteration of DOTS Physics does not support
    joint motors i wanted to improvise a temporary solution and got quite confused
    by the angular velocity.

    In PhysX it was determined in rad/s, and when manually set to about 6.2, the object
    would rotate 360° in one second (or there about), as expected.

    Now in DOTS with either Havok or UnityPhysics I can't get the hang of angular
    velocity: rad/s does not work, and neither does deg/s. In both cases, the object spins
    at a seemingly arbitrary speed, although the Entity displays the correct angular velocity
    in its debugger. Disabling angular damping did not help either.
    So all I have managed thus far is to get an object to rotate around the desired axis, at some speed.

    I am very sure I got it completely wrong in concept here. Sadly the documentation
    did not shed any light on this and I failed to get any insight from the Physics Samples.

    TL;DR How does angular velocity work in DOTS and how can I set and read it in such a way
    that I get consistent results.
  2. steveeHavok


    Mar 19, 2019
    Angular Velocities in DOTS Physics are based on rad/s but the confusion is probably because they need set in the 'Motion Space' of the dynamic body, where you may be trying to apply things in 'World Space'.

    Here is the code for the Component Extension that applies an impulse at a specific point:

    Code (CSharp):
    1.         public static void ApplyImpulse(ref this PhysicsVelocity pv, PhysicsMass pm, Translation t, Rotation r, float3 impulse, float3 point)
    2.         {
    3.             // Linear
    4.             pv.ApplyLinearImpulse(pm, impulse);
    6.             // Angular
    7.             {
    8.                 // Calculate point impulse
    9.                 var worldFromEntity = new RigidTransform(r.Value, t.Value);
    10.                 var worldFromMotion = math.mul(worldFromEntity, pm.Transform);
    11.                 float3 angularImpulseWorldSpace = math.cross(point - worldFromMotion.pos, impulse);
    12.                 float3 angularImpulseInertiaSpace = math.rotate(math.inverse(worldFromMotion.rot), angularImpulseWorldSpace);
    14.                 pv.ApplyAngularImpulse(pm, angularImpulseInertiaSpace);
    15.             }
    16.         }
    18.         public static void ApplyLinearImpulse(ref this PhysicsVelocity velocityData, PhysicsMass massData, float3 impulse)
    19.         {
    20.             velocityData.Linear += impulse * massData.InverseMass;
    21.         }
    23.         public static void ApplyAngularImpulse(ref this PhysicsVelocity velocityData, PhysicsMass massData, float3 impulse)
    24.         {
    25.             velocityData.Angular += impulse * massData.InverseInertia;
    26.         }
    Notice how it converts the world space angular impulse before applying the impulse.
    The other elements that you might be hitting is that the default in PhysX is that the ForceMode is defaulting to Force. Things are a little more raw with DOTS Physics at the minute and everything is in impulses (i.e. ForceMode.Impulse). To apply forces rather than impulses, multiply your impulse by the deltaTime, which will give you a much smaller magnitude.

    1) Angular Impulses are currently in Inertia Space
    2) Impulses need multiplied by deltaTime to be converted to Forces
    LandonF likes this.
  3. Bieger


    Jul 29, 2018
    That clears up why I could not make any sense of it.
    I will try my hands at the conversion, to see if I can figure it out now.

    Thank you very much for the detailed explanation
  4. Bieger


    Jul 29, 2018
    So I have had some time to try out your suggestions and sadly I could not fix the issue. The transformation example helped me to convert my Mathf code to Unity.Math, which is nice, but since I was directly setting
    the velocity, your advice on impulses did not work for me.

    Is setting the velocity directly not desirable? I would be fine with switching to ApplyImpulse instead, but I would still be stuck on the core issue, that the rotation times do not seem to match the expected times. The cube in the image rotates around the x-axis and has just about completed one full cycle, which took 2.7 seconds. These times vary between each test, ranging from 2.7 and 3.3 seconds. The PhysicsVelocity reads the expected 6.2 rad/s.

    The whole point is to eventually simulate a robot arm using DOTS physics (both Havok and Unity).
    For now the simulation has to be a good estimate at best, but nothing too precise. Maybe I am approaching this whole thing wrong.

    How could I make a joint rotate at a set rad/s speed, so that it properly collides with other objects and
    has its movement obstructed by them? Directly rotating it through the Rotation component results in
    jittering collisions, which is why I switched over to using velocities in PhysX and the same held true
    for DOTS.

    Attached Files:

  5. slushieboy99


    Aug 29, 2014
    Is float3 point here in local space or world space?