Monday, April 23, 2012

Movimentum - Rigid body constraints

We are quickly closing in on the central algorithm of Movimentum: The constraint solver. But before I try to fathom the depths of that topic, there is still something missing: Constraints that capture the rigidity of our things. To see why we need them explicitly, let's write a script for a simple horizontal bar:

    .config(1);

    Bar : 'bar.gif' P = [10,10] Q = [50,10];

    // We place the bar somewhere
    @0.0  Bar.P = [10,10]; Bar.Q = Bar.P + [_,0];

This step can be rewritten into the following scalar equations:

   barPx = 10; barPy = 10; barQx = barPx + d; barQy = barPy;

barQy can readily be computed, but not barQx! Some constraint is obviously missing. This also follows from the fact that we have four equations, but five variables: The four bar.. variables and the "slack variable" d.

Let's now rotate the bar by 45°:

    @1.0 Bar.Q = [e,e];

According to the "key convention", the constraint Bar.P = [10,10] remains in force, but the Bar.Q constraint from @0.0 is replaced. Therefore, we end up with the following four equations:

   barPx = 10; barPy = 10; barQx = e; barQy = e;

Again, we cannot compute some values - in this case, both for barQx and barQy. Again, we have five variables - the bar..s, and e -, but only four equations.

Let's now add a "length constraint":

   // implicit length constraint
   (Bar.P.x - Bar.Q.x)² + (Bar.P.y - Bar.Q.y)² = 40²

Using this constraint, we get a fifth equation. For the initial placement in step @0.0, we can now solve the equations:
 
   barPx = 10; barPy = 10; barQx = barPx + d; barQy = barPy; 
   (barPx - barQx)² + (barPy - barQy)² = 40²

We substitute barPx and barPy (as they are equal to constants) and barQy and get:

    barQx = 10 + d; (10 - barQx)² + (10 - 10)² = 40²

Dropping  (10-10)² = 0 and substituting barQx gives us

    (10 - 10 - d = 40²

and we arrive at the two solutions d = +40 and d = -40. Backsubstitution will give us the variables for the initial placement of the bar.

But ... there are two possible solutions! What do we do about this? Possibilities:
  • We require an additional explicit constraint, e.g. Bar.Q.x > Bar.P.x.
  • We assume additional implicit constraints - my suggestion: If for two anchors A and B of a thing T, we have A.x > B.x, then we also require T.A.x > T.B.x for the solution.
However, I'm afraid that implicit inequality constraints will either
  • hold too short (i.e., they are also necessary for some movements); or 
  • too long (i.e., they will prevent a single solution at some time); or
  • are not sufficient (e.g., when two solution have equal x, or when multiple quadratic equations yield four or more solutions).
So I will, for the moment, require explicit inequality constraints for unique solutions.

But also for explicit inequality constraints, the lifetime seems to be tricky - the three problems above might also occur with them. So we need a lifetime regime for inequality constraints!

Here is my suggestion: Inequality constraints are marked with the variable on the left side and the inequality operator (maybe <= is unified with <, and >= with >). Using the following "vacuous" constraint, an inequality constraint can be "killed:"

    x > _

(Another possibility would be to have infinite lifetime for inequality constraints, but invoke them only if there are two or more solutions ... but I am afraid that then, it gets even harder to get unique solutions).


Let's also try the solution for the @1.0 step: We have the five equations

   barPx = 10; barPy = 10; barQx = e; barQy = e; 
   (barPx - barQx)² + (barPy - barQy)² = 40²

We substitute all four bar.. variables and get:

   (10 - e)² + (10 - e)² = 40²

This can be solved and yields 10 - e ≈ ±28.28, or e ≈ +38.28 or e ≈ -18.28. From this, we can find the values of the bar.. variables. Again, > constraints are needed to select a unique solution.

The rigid body (length) constraints must of course remain in force for the full script. Therefore, I give them a key that can never be given to another constraint - some internal Guid or the like.

No comments:

Post a Comment