Saturday, April 21, 2012

Movimentum - Design of the language - What I want

So we are going to design a little language for moving mechanical objects. For this, we need a few example machines. As I said, there is that great page www.animatedengines.com. But the examples there are too complex for a first step - let us use a simpler example. What do we want? The machine  should be small - have only a few parts, it should be realistic, yet it should be "mathematically hard". Astonishingly, one of the simplest machines has all these properties - here is a quick sketch of a simple crank-and-piston mechanism (a pump, for example):


Let us assume that the crank turns with a constant angular velocity. The coordinates of its endpoint can readily be computed as [Rsin(t), Rcos(t)] where R is length of the crank, and t is the time, suitably scaled and shifted. Now, what are the coordinates of the piston? Because of the limited length of the connection rod, this is not a simple sine function: It is much more complicated - see for example http://en.wikipedia.org/wiki/Piston_motion_equations.

Our movement model language could require that the closed form solution is entered so that the positions of the piston can be computed directly. However, for more complex linkages, this is much work (which I sometimes love - but not always) ... aren't computers intended to solve such problems? With this consideration in mind, let us start with that language.

The following considerations already went through one round of "cleansing the language". It is actually a little hard to present the initial rough thought processes, so I start just here.

Here are a few concepts I want to have:
  • Vectors. Many kinetic equations are much simpler if written as vectors.
  • Scalars. Like e.g. time or angles.
  • Rigid objects. These are objects that will move "as a whole" according to two points whose movement is known.
  • Not-closed kinetic formulae. This comes from the example above.
  • 2D only. Maybe we have 3D ideas later - not now (however, I think I'll give them vectors 3 coordinates from the start).
  • Z-ordering. A 2d-object should be able to obscure another 2d object.
  • Cartesian coordinates. Also polar ones?
  • Time. Measured in seconds, preferably; maybe also in frames.
  • "Segmented movements". From instant t1 to t2, an object does not move; from t2 to t3, it moves on the trajectory jA; from t3 to t4, it moves on trajectory jB (e.g. back).
  • Units. We can measure angles in degrees or radians; time in seconds or frames; maybe length in pixels, meters, or inches (really?? well ...).
  • Free format language (i.e., not line-oriented; not column-oriented).
  • Comments in the language.
Ok - let's stop here and try to start with our example.

We want to set up a few objects. We assume we have them in GIF files somewhere. To get a "handle" on the objects, we can define points in them, relative to the [0/0] of the GIF:

Crank : 'crank.gif' P = [20,20] Q = P+[0,30];

The crank is in file crank.gif, and we define two points on it: P and Q (which is defined relatively to P). More objects:

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

Now we place the objects. For the fun of it, we want them to appear in 2 second intervals (but we not yet think how we might let them "fly into the scene"!). We need a time axis - I use @ as a prefix to times on that axis:

@000.0    Engine.P = [20,80]; // middle line of cylinder: y=80
@+02.0    Crank.P = Engine.P + [200,70];
@+02.0    Piston.P = Engine.P + [0,70]; // 70 above ground line
@+02.0    Conrod.P = Crank.Q; Conrod.Q = ...oops...

Conrod.Q cannot be placed easily. After all, the length of the conrod is fixed (by its image). So we cannot just "stretch" it to the piston's eye. But even if we put the conrod's eye into the piston travel line, the piston will most  probably be at the wrong position!

To keep things simple, we reverse the order and deal with the conrod first:

@000.0    Engine.P = [20,80];
@+02.0    Crank.P = Engine.P + [200,70];
@+02.0    Conrod.P = Crank.Q; Conrod.Q = ...still unclear...

What about Conrod.Q? Isn't the position of Conrod.Q uniquely fixed if only its y coordinate is fixed? After all, the fixed length of the conrod will place its Q on a defined point on the travel line of the piston! So we happily write:

... Conrod.Q = [x, 70];

x is some "unknown variable." But now, we have suddenly entered the area of "constraint satisfaction:" Our equations are not assignments, that compute a right hand side and assign it to the left hand side. Rather, they express a constraint between both sides, and therefore could be reversed: The following

... [x, 70] = Conrod.Q;

therefore means just the same as the line above.

There is one problem with the formulation above: Actually, there are two solutions for x! - the reason being that a circle (with center Crank.Q and radius equal to the length of the conrod) intersects the y=70 line at two places. We can easily fix this in our new constraint mechanism by requiring

... Conrod.Q = [x, 70]; x < Crank.P.x;

("But how,  by Jove, are the actual places of the objects computed?", you might ask. Answer: I don't know - we'll find a way when we are there!).

Let's go on and place the piston: Its eye should link to the conrod, so we simply write

@+02.0    Piston.P = Conrod.Q;

And this finishes the setup of our little machine. Next posting: Let's move it!

No comments:

Post a Comment