Initial conditions in joints

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Re: Initial conditions in joints

Postby blackbird_dream » Wed Oct 02, 2024 2:36 am

Thks Julio I'll do that.
I just need to build the last version of ND4.
Dave told me it should be compatible with its engine
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby blackbird_dream » Fri Oct 11, 2024 9:28 am

Ok Dave upgraded the engine so that it is compatible with one of the latest commits.
I've just added
Code: Select all
ClearMemory();

in the constructor of my subclass. It works the same as before.
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby blackbird_dream » Fri Oct 11, 2024 10:00 am

subsidiary question :
what about an intial velocity applied to one of the ragdoll's limbs ?
How to set it?
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby Julio Jerez » Fri Oct 11, 2024 11:27 am

ahh, Remember when I mentioned that setting the way you mention may seem will work, but that it will come back to bite you in the ass, I said from my own experiences, not to be aggressive or offensive.
I did not expect you realization to come back so soon, but that's good.

Going back to summarize wht you missed.

you had the model rigged, as a set of rigid bodies
you also had a series of posies.
then you initialize the rig to a pose, and you recreate the joints.

My suggestion was that your pose was incomplete.
you need the collection of rigid bodies and the collection of joints.
them you pose array contain the array of rigid bodies state: (position, orientation, velocity and angular velocity)
to set a pose, you iterate over the body array setting the rigid body state, and after that you iterate over the joint array calling Clear Memory.

to answer your question directly. here is the code for the hinge joint.

Code: Select all
void ndJointHinge::ClearMemory()
{
   ndMatrix matrix0;
   ndMatrix matrix1;
   CalculateGlobalMatrix(matrix0, matrix1);

   ndJointBilateralConstraint::ClearMemory();

   // save the current joint Omega
   const ndVector omega0(m_body0->GetOmega());
   const ndVector omega1(m_body1->GetOmega());

   // the joint angle can be determined by getting the angle between any two non parallel vectors
   m_angle = CalculateAngle(matrix0.m_up, matrix1.m_up, matrix1.m_front);
   m_omega = matrix1.m_front.DotProduct(omega0 - omega1).GetScalar();
   m_targetAngle = m_angle;
}


you can see that, it set the joint angle, and target angle, but it also set the joint angular velocity from the velocity of the rigid bodies.

BTW, for newton 4, I put a lot of emphasis and effort on this, for that I created an object that is call a ndModel. I do not know if Dave exposed, I think he did, but maybe not all, anyway in a nutshell.
A ndModel is an object that has not physical properties, no collision, no body and no joints.
it is just a way to insert a series of call back from the engine at the appropriate time, giving the application to operate in more than one of those atomics components of a physical model.

an application of that is the ndModelArticulation. Is an arrangement of bodies and joint is a top-down hierarchy, and also support close loop joint that the application can set explicitly.

by using this, now you get a call back with all the elements that are part of your model.
and you can apply your logic to all the elements at once, in the order that you need to,
This will include the bodies that model collided with and contacts.

Most models in the real world (people, vehicles, furniture) can be approximated by an acyclic graph.
that is a graph in each node only has one parent. the one that do not follow that pattern, can also be approximated with an acyclic graph as primary joints and loops as secondary joint loops.
An example will be a vehicle, the chassis, the wheels, the motors, and many other parts are an acyclic graph, them the axle connect two wheels, so that can be set explicitly as a loop.
another example is a person, from the torso to the limbs, it is an acyclic graph, but if the person grabs an object with two hands, that will form a loop.

that's what ndModelArticulation articulation is designed for.
Julio Jerez
Moderator
Moderator
 
Posts: 12425
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Initial conditions in joints

Postby blackbird_dream » Mon Oct 14, 2024 4:44 am

thks for your prompt feedback.
I believe it's difficult to understand eachother.
you wrote :

you had the model rigged, as a set of rigid bodies
you also had a series of posies.
then you initialize the rig to a pose, and you recreate the joints.


I'm not sure it's what I did. I''l try to rephrase it like a 8yo' child (see Philadelphia ;) ).
In fact, I built the ragdoll as a subclass of ndModelNotify (and not ndModel like with the previous commit of ND4. That was the latest change made by Dave)
This subclass has all the limbs declared as members (they are objects of dgEntity* type which is a class embedding newtonbodies + opengl stuffs for 3D display).
Then I instanciated the limbs with opengl structures (e.g capsules) and Newtonbodies and Callbacks.
I positioned the newtonbodies with setMatrix commands, taking account of their initial orientation and position.
Then I built the joints with my subclass (ndPLJointHinge which is only a change of variable, in my opinion).
But I never
recreated
joints.

What I did is also adding
ClearMemory();
to the constructor of my subclass ndPLJointHinge (child of ndJointHinge).

it seems to me that I did what you suggest here:
My suggestion was that your pose was incomplete.
you need the collection of rigid bodies and the collection of joints.
them you pose array contain the array of rigid bodies state: (position, orientation, velocity and angular velocity)
to set a pose, you iterate over the body array setting the rigid body state, and after that you iterate over the joint array calling Clear Memory.


But I may misunderstand you.
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby blackbird_dream » Mon Oct 14, 2024 10:13 am

My question was about the Initial velocity of newtonbodies, not angular velocities of joints.
For example how to set the non-null velocity of the torso ?
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby Julio Jerez » Mon Oct 14, 2024 11:46 am

I suppose it is a language barrier in my part.
Hopely a pseudo code can makes it clearer.

Code: Select all
struct BodyState
{
    quaterion rotation;
    vector position
    vector velocity;
    vector omega;
}

struct RigPose
{
    arrayOfRigidBodies bodies[n]
    arrayOfRigidBodyPoses states[n]
    arrayOfJointsVonnectin joints[m]

   SetPose()
  {
    forEachBody (index in bodies) do
    {
         body[index]->SetRotationAndPosition(state[states].rotation, state[states].position);
         body[index]->SetVelocity(state[states].velocity);
         body[index]->SetVOmega(state[states].omega);
    }

     forEachJoint (index in joints) do
    {
          joints[index].ClearmMemory()
    }
}


I am calling the collection of bodies and joints a Rig.
them the set of rigid bodies, joints and states, a pose.

You can have an array of poses, ex, the start of a walk, the start of a run and so on,
you can even have intermediates keyframes poses for the same sequence that you can use as a target to move to. For example, say you have a motion capture walk sequence, and you want to adapt the rig to play that sequence but at the same time adapting to the environment.
In your system will modify the poses training to match the sequence target poses, by basically taking the difference between the model pose and a target pose, plus some error from the environment and minimize that objective function by less squares.
you can collect special key poses on that cycle that you can use as target and you interpolate between them so that the optimizer does not veer too much.
Those techniques are very popular these days among grad student using deep learning.
but there are many other ways to use it.

The point is that to jump to a specific pose, you most set the rigid body internal states and them the joints internal states.
I do not know how else explain it better.
Julio Jerez
Moderator
Moderator
 
Posts: 12425
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Initial conditions in joints

Postby blackbird_dream » Tue Oct 15, 2024 5:51 am

ok.
1st thing, I moved the method ClearMemory to the public section.

Then I rigged my ragdoll in position, that means in my case the right knee bent to 50° (this is equivalent to
body[index]->SetRotationAndPosition(state[states].rotation, state[states].position);
)

Then I instanciated the ndJointHinge for the knee with the thigh and the shank in that position (50°).

then I set:
Code: Select all
joint8->ClearMemory();


joint8 is the knee joint.

As a result the knee is bent at 50°, but joint8->GetAngle() returns 0 and not 50;
Last edited by blackbird_dream on Tue Oct 15, 2024 6:00 am, edited 1 time in total.
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby blackbird_dream » Tue Oct 15, 2024 5:58 am

User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby blackbird_dream » Tue Oct 15, 2024 6:06 am

I understand this is not what you wrote in the sense that I should have
rigged the ragdoll in the initial pose then built all the joints , then rotated the shank and all the distal limbs from it, because they must follow the shank if i rotate it.
That's not simple because I need to multiply all the matrix transforms. It's a chain reaction.

And I wonder if I can rotate the bodies with setMatrix transforms if they are already connected by joints.

With my subclass I don't need to do that because at each stage the joint is modified with a change of variable.
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby Julio Jerez » Tue Oct 15, 2024 12:22 pm

You do not create the joints when setting poses.
The bodies and joints are created once, at that time the joint angle will be zero.
You made the whole thing at a pose that will be called the T pose.
The array of joints and bodies we are calling the Rig.

Then you make an array of Poses,
that's just an array of body states in which for each pose,
each state map to one rigid body of the rig with an index.
(the T pose is just one special pose, which is the set all body states when the rig was created).

then to set an arbitrary pose, you just chose the pose from the array of poses and call the function
that I posted in the pseudo code to set all body states and all joint states.

I made a diagram to show the rig at a base pose, and one extra pose.
jointPose.png
jointPose.png (20.52 KiB) Viewed 8121 times
Julio Jerez
Moderator
Moderator
 
Posts: 12425
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Initial conditions in joints

Postby Julio Jerez » Tue Oct 15, 2024 2:38 pm

if you are having problem setting the pose of one limb, say a leg.

what you do is that you organize your rig as a hierarchy, that is, as an acyclic graph.
you can pick any body part, as the root.
(in graphs theory, you can prove that any acyclic graph only has one spanning forest)
https://en.wikipedia.org/wiki/Spanning_tree

so, thes means it does not matter what node you select as your root,
the graph will be the same as long as it is acyclic, in fact, newton uses that concept internally with the solver.

for this, I assume the torso is the root node and let us say you want to rotate a leg.
Now since each node can only have one parent, we also know that the kinematically, changing the state of that node, can only affect the state of its children.

For this, you can write a function, that let you change any arbitrary pose.

Say you want to rotate a leg by some angle, you get the new position and orientation of the leg body. but you do not know how that affect the children.
you calculate the relative state for the node,
apply the state to the node and
for each child node, apply the offset to the state of that node to get its new state,
and recursive iterates over each child node.

here is in pseudo code.

Code: Select all
SetLimbPose (limbNode, LimbState)
{
       // calculate the relative rotation for limbnode.
       state = GetBodyState(limbNode) ;
       matrixOffset = matrix * LimbState.Inverse();
       omega = LimbState.Omega - state.Omega;
       veloc = LimbState.Velocity - state.Velocity

      SetLimbNewState (LimbState);
 
      // now for each children of this node, calculate the new desire state, and reprect.
       forEacgChildrenOf(i in limbNode)
       {
           // each child inherits the relative change of state.
            childState = child[i].State
            newState =  matrixOffset * childState.Matrix
            newState.Veloc =  veloc + childState.Omega cross( disttab to paren)  + childState.Veloc;
            newState.Omega = omega  + childState.Veloc
            SetLimbPose (child[i], newState)
       }
}


This is what I mentioned in the engine, this pattern repeats over and over when dealing with this kind of hierarchical arrangement, so I put in in a class called the ndModelArticulation
in the code you can find that pseudo code is implemenetd by the function below.
void ndModelArticulation::SetTransform(const ndMatrix& matrix);

if you look at the code, you will see that is a lot simpler that the pseudo code,
and the reason is that, after you run the part that change the transform in a top-down hierarchy,
you can set anybody velocity you want without worry about the effect on the connected bodies,
because by calling the clear memory, the joints will get the proper internal state.
before that, the function was complex as the pseudo code shows.

anyway, I hope this helps.
Julio Jerez
Moderator
Moderator
 
Posts: 12425
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Initial conditions in joints

Postby blackbird_dream » Wed Oct 16, 2024 10:45 am

Ok thks , this helps.
I understand in principle.
With your method it's possible to do restarts from arbitrary poses.
With what I did, I was just able to start from an arbitray pose (which is different from neutral) but not to make a restart.
Now I must go in details to see how to implement it.

We are talking about dynamic joints aren't we ? Not kinematic ?
User avatar
blackbird_dream
 
Posts: 379
Joined: Wed Jun 07, 2006 3:08 pm
Location: France

Re: Initial conditions in joints

Postby Julio Jerez » Wed Oct 16, 2024 12:05 pm

blackbird_dream wrote:We are talking about dynamic joints aren't we ? Not kinematic ?

Yes, all entities in the engine are dynamic objects.

I use the name kinematics in some cases, but that's when the dynamic and the kinematics coincide.
As soon as you move forward in time, that kinematic state is not longer valid.
Basically you can see the dynamic as a movie of kinematics states. Each time you advance in time, the new state is a kinematic state.
Based on that idea, you can have predefined states, that you want your model reach in the future, and you can apply any action to the the model elements, usually the joints, to get as close to that state as possible.
Julio Jerez
Moderator
Moderator
 
Posts: 12425
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Previous

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron