That's a difficult thing to do the way you stated it, as you said, physics is an initial condition value problem. A joint cannot be set to an arbitrary state and expect that the integrator will just jump to that state.
When a simulation starts, the joint parameters are expected to be an accurate representation of the relation (velocity and position) between the two bodies it connects. The joint code relies on that value to be accurate and then is add a correction to it.
If the value does not represent the start of the bodied, the correction will cause huge deltas that will lead to explosions.
The offset trick, you are thinking about will not help, believe me I tried, with in the pass unsuccessfully.
The rule of thumb is that in a joint you can change almost anything to steer the state,
but you cannot change the state after the initialization, only the integrator can change the state.
This rule is not only for joints, it is, also for bodies.
The way to do it is by having a complete "set pose" function. You have the notion of most of that already.
You said you has a pose, which I assume, it is an array position orientation, velocities and angular velocities for each rigid body. (Import: the pose must save the velocity of the state.
Most the time these are zero, but they must be set on each body, else the body will use the velocity already had in the instance.
What you are missing is missing is the part that also reset the joints states.
your pose must also contain the array of all the joints part of the contraction that you are assembling
I recently had similar situation training models with deep learning, each time I re start a model,
I had big problems with joint internal states,
Finally, I decided to fix that by adding the base functionality to the base joint.
ndJointBilateralConstraint::ClearMemory();
you use as follows, after you reset the bodies state,
you iterate over the joint also resting the joint state.
This will set all internal states to default values and recalculate the joint parameters.
here is the hinge example.
- 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;
}
edit:
I just added the one for the double hinge. since you said you are using it.