More angular momentum problems

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

More angular momentum problems

Postby pHySiQuE » Tue Sep 30, 2014 2:07 pm

All bottles have the same mass, just have a different size. I don't use Newton scaling.
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: More angular momentum problems

Postby Julio Jerez » Wed Oct 01, 2014 7:04 am

there is no problem there, the torque that you are using to pick the object is not too stiff and is overshooting with body with small momentum of inertia.

the large jar have a large inertial and is damping the torque, but the same torque is too high for the other tow smaller jars.

show he function that you are using to calculate that torque.
Julio Jerez
Moderator
Moderator
 
Posts: 11039
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More angular momentum problems

Postby pHySiQuE » Wed Oct 01, 2014 8:27 pm

I am using a strength value of 0.5, so it shouldn't be overshooting the target rotation.
Code: Select all
   void Entity::PhysicsSetRotation(const Quat& quat, const float strength)
   {
      if (body)
      {
         Quat currentrotation = body->nextquat;
         Quat desiredrotation = quat;
         Quat omega = GetOmega();
         Vec3 torque = desiredrotation.GetAverageOmega(currentrotation, strength);
         torque *= 1.0 * GetMass();
         body->SetTorque(torque*60.0);
         body->SetOmega(0, 0, 0);
      }
   }
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: More angular momentum problems

Postby JoeJ » Thu Oct 02, 2014 5:52 am

pHySiQuE wrote:torque *= 1.0 * GetMass();


The mistake is: Torque is related only to inertia, like force is related to mass.
You need to transform the vector in bdy local space, aplly inertia, and transform it back:

Code: Select all
vector torque = targetAngVel / timestep;
torque = matrix.Unrotate (torque); // matrix = BodyGetMatrix
torque[0] *= Ixx; // Inertia from BodyGetMassMatrix
torque[1] *= Iyy;
torque[2] *= Izz;
torque = matrix.Rotate (torque);


We've discussion on that here: http://newtondynamics.com/forum/viewtopic.php?f=9&t=7609

I remember you got doupts about the addition of angular velocities and the thread ended in confusion but the code i've posted works.
A few days later i found a explantation why this (vector addition) is right, but i did not understad :)
User avatar
JoeJ
 
Posts: 1147
Joined: Tue Dec 21, 2010 6:18 pm

Re: More angular momentum problems

Postby Julio Jerez » Thu Oct 02, 2014 7:56 am

that function is incorrect is many levels.
first like JoeJ said you are multiplying an anglular velocity by a mass to get an impulse, when you should multiplying by the moment of inertia.

by definition inertaion is give by
I = sum (mass(I) * x(I) ^ 2) {I is each pass particle on the body}

x is the distance to the origin or the center of mass.
so if two body shave the same mass by different size, the inertial will be different by a factor for the square of the radios, if one is twice as large the inertia will be four time bagger.

the second problem is that you apply a really bad torque ( I do not know what 60.0 is),
and you are zeroing out the angular velocity. so the body is taking one step but a large torque. but after that the body acquire angular momentum that is no canceled after the last call.

I still do not get why it is that people keep using these bogus function to apply Inverse kinematic force to body. There are many utilities in the engine to achieve the same effect in a more physically sound way.

Please use these function that I separated from the sandbox demos and turn into a util function
Code: Select all
void CalculatePickForceAndTorque (const NewtonBody* const body, const dVector& pointOnBodyInGlobalSpace, const dVector& targetPositionInGlobalSpace, dFloat timestep)


you can play with eth stiffness and the angular damp, this function damp the torque the will be applied to the body, no the angular velocity that the body already have.
it is 0.95 you may want to make 0.92 or 0.9
or make a parameter.
The stiffness is 0.3 which I believe is very good. I will make too stiff and will over should 0, will do nothing at all, 0.25 to 0.3 are good values.
Julio Jerez
Moderator
Moderator
 
Posts: 11039
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: More angular momentum problems

Postby pHySiQuE » Thu Oct 02, 2014 2:10 pm

One of the most common problems my users have is they use our positioning and rotation commands, and then don't understand why the entity lost all collisions. So I added a PhysicsSetPosition and PhysicsSetRotation command.

PhysicsSetPosition is easy. I just take the difference between the current and desired position, multiply by 60 (so it moves in one frame) and that's the new velocity:
http://www.leadwerks.com/werkspace/page ... ation-r189

Code: Select all
   void Entity::PhysicsSetPosition(const float x, const float y, const float z, const float strength)
   {
      if (body)
      {
         Vec3 d;
         d.x = (x - body->nextmat[3][0]) * 60.0;
         d.y = (y - body->nextmat[3][1]) * 60.0;
         d.z = (z - body->nextmat[3][2]) * 60.0;
         d *= strength;
         body->SetVelocity(d.x,d.y,d.z);
      }
   }


PhysicsSetRotation is harder. On your advice, I implemented a GetAverageOmega() function. The calculated omega should be exactly enough to rotate the object to reach the desired rotation in one update.
http://www.leadwerks.com/werkspace/page ... ation-r189

Code: Select all
   void Entity::PhysicsSetRotation(const Quat& quat, const float strength)
   {
      if (body)
      {
         Quat currentrotation = body->nextquat;
         Quat desiredrotation = quat;
         Vec3 omega = desiredrotation.GetAverageOmega(currentrotation, strength*60.0);
         body->SetOmega(omega.x, omega.y, omega.z);
      }
   }


Typically, I use 0.5 for the strength argument on these functions. It is implied that the user is calling these functions each frame, so the object stays stable. This is how we pick up objects like in Penumbra and Amnesia.

The CalculatePickForceAndTorque() function isn't really useful for this. Because it combines force and torque in one function it will interfere if I try to use it to set the position and rotation separately. Being able to position and rotate an object with physics forces is the most basic functionality my users need.
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: More angular momentum problems

Postby pHySiQuE » Thu Oct 02, 2014 2:42 pm

I found if I send 1.0 / strength to the GetAverageOmega function instead, it produces the behavior I am looking for. I also removed the multiplication by 60. I want the omega calculated to reach the desired rotation in one physics update, and I assume omega is measured per second (60 updates). But this is better at least:
Code: Select all
   void Entity::PhysicsSetRotation(const Quat& quat, const float strength)
   {
      if (body)
      {
         Quat currentrotation = body->nextquat;
         Quat desiredrotation = quat;
         Vec3 omega = desiredrotation.GetAverageOmega(currentrotation, 1.0 / strength);
         body->SetOmega(omega.x, omega.y, omega.z);
      }
   }
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: More angular momentum problems

Postby JoeJ » Thu Oct 02, 2014 4:13 pm

PhysicsSetPosition does not look well to me too. I'd avoid setting velocity directly in any case.
Newton should calculate this, because other external forces (collisions) should be able to prevent bad things when the player pushes the bottle into other bodies.
You should try to improve that - this is how the player 'feels' physics, so very important.
In my opinion the most important thing about game physics at all.

I suggest you try the positional part from my code and if you like it do the angular - they are easy to separate.
I try to harm simulation as less as possible while still having responsive interaction.


I agree that having 2 seperated functions to calculate force / tourque to target pos / orn in Newton utilies would be a great idea. Really, everyone hase troubles with that.

Code: Select all
      BodyData *data = (BodyData*) BodyGetUserData (pickedBody);

      sVec3 targetPos = handPos;
      sQuat targetOrn = handOrn;

      float mass, Ixx, Iyy, Izz; BodyGetMassMatrix (pickedBody, mass, Ixx, Iyy, Izz);
      sMat4 matrix;      BodyGetMatrix(pickedBody, matrix);
      sVec3 curLinvel;   BodyGetVelocity (pickedBody, curLinvel);
      sVec3 com = matrix[3]; // assuming there's no offset
      sQuat orn;         BodyGetRotation (pickedBody, orn);
      sVec3 curAngvel;   BodyGetAngVel (pickedBody, curAngvel); // NewtonBodyGetOmega

      sVec3 targetLinvel = (targetPos - com) / timestep; // would move move target distance in one step
      targetLinvel -= curLinvel; // subtract current velocity - we want to change it, but we should not ignore it
      sVec3 force = 0.3 * targetLinvel * (mass / timestep); // soften by factor 0.3 to avoid oszillation
      sVec3 gravity (0.0f, mass * propsPhysics::f[propsPhysics::gravity], 0.0f);
      force -= gravity; // apply reverse gravity, otherwise it seems some force is pulling the body downwards (optional)
      // note that there is no upper limit on force - this should be added, either by automatic value related to body mass,
      // or a user param like max friction in joints

      sVec3 targetAngVel = AngVelFromAToB (orn, targetOrn) / timestep;
      sVec3 torque = 0.3 * ConvertAngVelToTorque (sVec3(targetAngVel - curAngvel), matrix, timestep, Ixx, Iyy, Izz);


      data->force += force;
      data->torque += torque; // I add (not set) those later in force torque callback
User avatar
JoeJ
 
Posts: 1147
Joined: Tue Dec 21, 2010 6:18 pm

Re: More angular momentum problems

Postby Julio Jerez » Fri Oct 03, 2014 9:45 am

if you one to do like that, you fist function is still very wrong
I modified it that at least make sense, but I could not test it.
Code: Select all
void Entity::PhysicsSetRotation(const Quat& quat, const float strength)
{
   if (body)
   {
      Quat currentrotation = body->nextquat;
      Quat desiredrotation = quat;

      //Quat omega = GetOmega();
      // the the average velocity to get to the desired location
      Vec3 omega = desiredrotation.GetAverageOmega(currentrotation, strength) - GetOmega();

      // strneg muyst be less than one (0.2 or 0.3 is a goo value)
      Vec3 alpha (omega * (strength / timestep));

      // get the moment of inertia matrix of the body
      dMatrix inertiaMatrix;
      NewtonBodyGetInertiaMatrix(body, inertiaMatrix);
      Vec3 torque = inertiaMatrix.RotateVector(omega);

      body->SetTorque(torque);
      //body->SetOmega(0, 0, 0);
   }
}
Julio Jerez
Moderator
Moderator
 
Posts: 11039
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 3 guests