Saturday, April 21, 2012

Movimentum - Design of the language - Movement; and constraint lifetime

Our pump should now start to move.

We need an item that defines the time. Let's call it t, and we assume its unit is "second". It is not the absolute time, but the time relative to the previous time marker (the @). Our crank should rotate, so its point Q needs to go somewhere else. Let us assume that it should turn 180° in one second - i.e., take two seconds for a complete revolution. I'd like to write a rotating unit vector like this:

[1,0].rotate(180° * t)

If we add this to the crank's center, we get a rotating point - and we can use this to pull Q. However, Q does not have distance 1 from P, but some other distance, and so the equation would be over-constrained. But if we leave the length of the vector open, the equations should be uniquely solvable. Here is the resulting constraint, where c is that "dont care" variable:

@+02.0    Crank.Q = Crank.P + [c,0].rotate(180° * t);

Now our crank moves!

What about the conrod and the piston? Well, the original constraints that (a) connect crank and conrod, (b) force the other eye of the conrod on the center line of the piston, and (c) connect the piston to the conrod are still valid. Therefore, we shouldn't be forced to add any other contraints!

However, this creates a problem: If earlier constraints just remain in force, then also the constraint would still hold that put the crank in an upright position in the first place ...

... oops: When I placed the engine and the crank at the beginning, I was too lazy. I wrote

@000.0    Engine.P = [20,80]; // middle line of cylinder: y=80
@+02.0    Crank.P = Engine.P + [200,70];

But I did not restrict the direction of the engine and the crank! So the engine could be rotated around [20,80] in an arbitrary direction! There are two ways out of this:
  • Either we request that additional constraints fix the position. In the case of the engine, we need an additional point for this.
  • Or the initial placement "defaults" to a "horizontal" image.
Because the default behavior would have to be programmed, I want to avoid it. So we have to change the initial definitions:

Engine : 'engine.gif' P = [30,50] Q = P+[1,0];
Crank  : 'crank.gif'  P = [20,20] Q = P+[0,30];
Piston : 'piston.gif' P = [30,50] Q = P+[1,0];
Conrod : 'conrod.gif' P = [0,50] 
                      Q = P+[100,50]; // lies horizontally in gif

@000.0    Engine.P = [20,80]; Engine.Q = Engine.P+[_,0];
@+02.0    Crank.P = Engine.P + [200,70]; 
          Crank.Q = Crank.P + [_,0];

The engine and the piston now each have an additional point Q, horizontally from P. And the setup places these points horizontally from the location of the respective Ps. I have added another feature: A single underscore means a "dont care" variable - i.e., a new variable at each place where _ occurs.

... end of oops.

Now, we must return to the problem of the lifetime of constraints. Above, we wanted earlier constraints to hold also later - I think this will come in very handy with larger machines! However, for moving our crank we wrote

@+02.0    Crank.Q = Crank.P + [c,0].rotate(180° * t);

But there is this earlier constraint from the setup

...; Crank.Q = Crank.P + [_,0];

Obviously, we do not want to hold that constraint now! - our machine cannot move and not move at the same time! What to do?

Idea: Each constraint has a "key". If the key is used for another constraint, the earlier constraint is dropped. And if a constraint has on its left side only a single variable, that variable is the key. So the key "Crank.Q" first referenced the constraint from the setup, and then was overwritten with the constraint for the movement. Let's hope this simple rule holds out for some time.

No comments:

Post a Comment