Today, I’ll finally explain a bit about the sneak previews I recently posted.
All goes back to a crazy idea I had a long time ago, which I have elaborated on publicly for the first time in my SVP 2011 talk. I’ve written about it in three instalments here, here and here. Since and even before then I have repeatedly started writing a proper paper, but for various reasons never was happy with it. And I wasted a lot of time trying to get some kinetic/dynamic models to show what I expected – no joy, because it is very difficult to model two different motions exactly comparable. More on that later.
Anyways, let’s have a look at those sneak previews again, this time with some explanatory text.
First off, we have here – again – an old acquaintance. For all those who are not as Triassic European dinosaur-affine as me, here are a more inclusive photo:
there he is, the one on the right, drinking or feeding from the ground. By now I am absolutely sure you all have recognized the specimen: GPIT/RE/7288, a Plateosaurus engelhardti from Trossingen, SW-Germany.
So the above screenshot shows the right hind limb and the hip, plus a few proximal caudal vertebrae, as rather small digital 3D models. Derived from CT scans, so the general shapes are accurate, although fine details have been lost when the files were reduced in size. That’s by far good enough for a SIMM model, because the muscle origin and insertion sites need not be determined within SIMM, but can obviously be determined by studying the real bones. The SIMM bones need only be good enough to find the same place on them that one has decided housed the muscle attachment on the real bone. Theoretically, you can forego bones entirely in SIMM, they are only an optical aid. But that aid saves you hours upon hours of figuring out the coordinated of a muscle attachment that you’d otherwise need to put into the model.
How to build a SIMM model
I guess it is time I give you an idea of what SIMM is, and how one needs to proceed to efficiently build a model. There’s a bunch of stuff you can do in SIMM but are better served if you do it outside SIMM, and simply import the results.
First of all, it is important to understand the structure of a SIMM model, and of the program. It is a bit…. convoluted, and makes for sometimes very convoluted editing.
Basically, a SIMM model is defined in text files. There is one text file you must have, the joint file (JNT). It can have any name you want, but must have *.jnt as the extension, which is why I will use the short JNT for this file. It defines the joints of the model (well, duh!), but it also defines a ton of other things. You can write a JNT file from scratch, but it is much easier to adapt an existing one.
In a JNT file you define a lot of basic things about your model, for example the direction of gravity relative to the axes of the model, and the position of your model view window. You can define cameras (i.e., view positions) that you can later jump to; these also go in the JNT file, along with definitions of the colours SIMM is to use for displaying various materials. And a ton of other things that don’t matter for building the model, so I’ll ignore them for now.
The meat of a JNT file, though, as the segments, the joints and the gencoords of the model. “Gencoord? What’s that? I know joints and I know segments, but what is a gencoord?” you may be tempted to ask. In fact, everybody is. Well, a gencoord is nothing but a variable, a term you define the value of which can vary. In your model, a gencoord corresponds to one degree of freedom in a joint, one of the three rotation or sliding axes of a Cartesian system. For each gencoord you can set a range of values it may not exceed, and you define what the value of the gencoord depends on. That’s important because not all things change linearly, and some depends on others. A really cool example of the latter is the wrist of birds, which is coupled with the elbow. If the elbow is flexed, the wrist must follow suit. In SIMM you can mimic that behaviour by making the elbow flexion gencoord dependent on a function, and the wrist dependent to -1 times the same function. Voila, your wrist flexed with the elbow! Probably you need a few refinements to that, e.g. by using a different factor than simply -1, but you get the drift.
Now, I’ve used the baaaad baaaad f-word: function! There, did it again! 😦 Well, there’s no helping it: you need to define functions for your model to work. In SIMM, functions are defined by points, between which the program interpolates curves, for example cubic splines or simple linear connections. You can, however, create some pretty complex interactions with this setup.
So, what do you really need to build? First of all, the segments. You need to decide into how many different pieces you want to split your model. Each piece is static within itself, it can’t bend, flex or have parts within it move versus each other. Motion can only occur between segments. Thus, a segment is the model equivalent of a functional part of a vertebrate’s skeleton: a limb segment, typically, or an akinetic skull, a mandible. With the vertebral column you can use the same approach, and model each vertebra as a separate element, and each rib (or pair of ribs), but that quickly makes your model rather cumbersome to work with. Plateosaurus est omnis divisa in partes septem: pelvis, thigh, shank, metatarsus, and three segments for the proximal, second, and combined third and fourth (ungual) phalanges of the middle (3rd) toe.
Why this split? Because those are the segments I am currently interested in. The tail, swinging left to right or up and down, was not part of what I was studying, thus it was made part of the pelvis segment. I can make up a new segment and shove it in there if needs be, and I can similarly split the two unguals I grouped. I can add further segments for the missing toes I, II, and IV (V is so tiny nobody needs it).
This is what the relevant part of the JNT file looks like. You can assign a mass and define the center of mass position for each segment, and you can add “bones”. A bone is nothing but a polygon mesh file, a specific version of an STL file, using the ending *.asc. it doesn’t have to be one bone of the real animal, or a bone at all, it can be anything you want. Because typically you want to see the bones, though, to place the muscles on, the name “bone” and the command “bone” that adds a file as a “bone” object are appropriate.
So, that’s all there is to segments, aside from toggles for displaying a marker for the center of mass and for inertia.
And on the next big step: we finally get to the joints. A joint connects two segments, and you need to define not only which two, but also where it does that, and what rules govern the motion in the joint.
That’s what joint definitions look like in the JNT file. A name, two segments, definitions how the axes of the joint are arranged (in this case, all are parallel to the axes of the world coordinate systems, thus the many zeros and a few ones). And six functions for the three translations in reference to the world coordinate system (tx, ty, tz) and the three rotations (r1, r2, r3).
As you can see ALL degrees of freedom of each joint are here defined via functions. There’s f1 and f2, which are two different functions, and behind each call-out of a function is a gencoord. The one defining how the thigh segment moves versus the pelvis along the x-axis of the hip joint is called hip_Tx. The actual motion will be the y value you get from function f1 if you enter the x value you want.
But why do I have functions for each and every little shit in there? The hip joint can easily be approximated by a ball and socket joint, so no changing translation is necessary. It only needs to be positioned in a certain place, thus instead of having hip_Tx, hip_Ty and hip_Tz I could simply have numbers there! Elementary – because I am an extremely lazy person, and instead of typing all this up I simply used a deus ex machina that made me a file. More on who that genius is – later!
One thing that I should mention now is the architecture of a SIMM model. You always have a “ground”, from which your first segment must start. Any segment you now connect to the first segment is offset (the translation and rotation values), measuring from the previous joint. No, not from the world origin, but from the previous joint. This means that in the example above, the ankle is f1(Tx_ankle) further down the x-axis than the knee, not the world origin. If you forget this it can get pretty hairy pretty fast.
The other things you need to know – and no, it is not as obvious as it may sound – is that your model can branch. It can be tree-like or bush-like, with one, two or many segments hanging of one “parent”, and you can also hang several “fist” segments on the “ground”. However, what you can’t do is merge lines of segments: you can’t have loops!
OK, enough for now, next post will go into all that function stuff a bit more, and add flesh (muscles) to the bone! To make up for the dearth of photos in this post, to celebrate the beginning of summer (already! we haven’t had spring yet) here’s a Spotted Thick-knee (Burhinus capensis) tanning.