Thanks for this great question, Kaiwen.
Here is our thinking behind this constraint:
Simbody constraints always model some physically-possible system, always assuming that the position and velocity constraints can't be exactly satisfied (they never are in practice). It is easiest to think of this by imagining the system as very far from satisfied, that is with a large perr meaning that points P and S are far apart. We know from Newton's 3rd law that forces between two bodies at a point must be equal and opposite at that point. If the velocity constraint were written as you suggested the two forces would be applied at different points. Instead we must find the point
in space at which the two bodies are touching and generate forces there. There is some choice to be made there -- perhaps the optimal one would be (P+S)/2, halfway between the two points that are supposed to be coincident. However, that's a difficult choice to implement and probably not better in practice than choosing one of P and S and applying both forces there. In any case, to satisfy Newton's 3rd, there can only be one point in space where the bodies touch. (And if you don't satisfy Newton's laws, the system is non-physical so won't necessarily conserve energy.) Forces are generated from the acceleration-level constraints.
I think it would be possible to write a constraint using forces at P and S, but then you would need also to include a moment to account for the separation and then it is not clear what the physical mechanism would be that enforces the constraint.
With that as preamble, here is the documentation from the implementation (from ConstraintImpl.h:1870):
Code: Select all
// We have a ball joint between base body B and follower body F, located at a
// point P fixed to B and point S fixed on F. All forces will be applied at
// point S and the coincident material point C on B which is instantaneously at
// the same spatial location as S. We will work in the A frame.
//
// First, find the material point C of B that is coincident
// in space with point S of F: p_BC = p_AS-p_AB. This vector
// is *constant* in the B frame because it is a material point,
// despite the fact that its definition involves a point which
// moves with respect to B. The velocity constraint is then
// very simple: the spatial velocity of point C of B should be
// the same as the spatial velocity of point S of F:
// verr = v_AS - v_AC = v_AS - (v_AB + w_AB X p_BC) = 0
// Integrating to get perr, we get
// perr = p_AS - p_AC + constant = 0
// But p_AC=p_AS by construction, so perr=constant=0.
// The constant is defined by the fact that we want material point
// C of B to be in the same spatial location as point P of B,
// so constant=p_BC-p_BP=0. Writing in the A frame we have:
// perr = p_AS-(p_AB+R_AB*p_BP) = 0 (a constant)
// verr = v_AS - (v_AB + w_AB X R_AB*p_BC)
// aerr = a_AS - (a_AB + b_AB X R_AB*p_BC + w_AB X (w_AB X R_AB*p_BC))
// apply +lambda to S of F, -lambda to C of B.
Happy to discuss further.
Regards,
Sherm